Has there ever been discussion about a permission for "running as an app" that would make a distinction between web pages and apps? I like that the web gets more features that allow apps to run cross-platform, but I don't fully understand why we make no distinction between pages and apps.
> even the drug-pusher-like "Community" (first hit is free, unless/until you're making money) edition.
I mean, yeah it's not free-for-all, but "first hit is free" is kind of unfair. A company is not allowed to use it if they have more than "(a) more than 250 PCs or users or (b) one million U.S. dollars... in annual revenues" [1], and if it doesn't meet that criteria, it's usage is limited to 5 concurrent instances. More accurate would be "first hits are free, and you won't start getting charged until you're big enough where you can afford it".
Just making the distinction because I still have friends who think they can't use Community at home if they want to have a side project that makes money.
In case there's any confusion whether or not I agree with you, here's the very next thing I wrote:
> It is perfectly reasonable on their part as a company selling dev tools to do this
The Community edition licensing terms are, at best, awkward. I personally would have the hardest time with the 250 user limit - can I publish a free mobile app without fear this restriction might kick in?
It is not as blatant as the BizSpark / Imagine (DreamSpark) programs, so I guess that's a plus. The end result looks close enough to be considered the same to me.
Yep, it's annoying to have those limitations, but I sort of understand why. They could make their message a lot clearer though.
> I personally would have the hardest time with the 250 user limit
From the document, the text is "more than 250 PCs or users", so my understanding is that a company is limited if it has >= 250 computer users, not 250 customers. E.g. you could have a million free app users and it would be fine.
That fact that I had to preface that with "my understanding is that" means that the document is fuzzy, which is annoying, but at least further documents[2] can clarify a bit:
> - Any individual developer can use Visual Studio Community, to create their own free or paid apps.
> - In non-enterprise organizations up to 5 users can use Visual Studio Community. In
enterprise organizations (meaning those with >250 PCs or > $1M in annual revenue) no use is permitted for
employees as well as contractors beyond... [the exceptions as noted].
So you (as an individual not as part of a company) could create a paid or mobile app and have as many users as you want and make as much as you can. If you're a company, then you need to be under 250 PCs, <= $1M, and <= 5 Visual Studio users and you're still good. Exceed those numbers and you have to pay up.
Vivaldi isn't open source but you can read the source code, which is better than nothing....
There is some debate inside Vivaldi about making it open source and it would be easy enough to do. I'd guess that it probably doesn't make economic sense while it has such a small market share, but I don't know if that's true.
The codegen creates a cache of delegates (created using expression trees), but uses a structure more suited to the problem than a simple ConcurrentDictionary.
> FYI, I recently found out that C# can actually do multiple dispatch
But also good to know, that it can be costly and unsafe. `dynamic` is basically using reflection at run-time, which for most cases is fine, but it's something to keep in mind. It also means that type checking is delayed until run-time instead of compile-time.
A dynamic type is probably just implemented as a tagged bit of data, surely. Which is the exact same way an algebraic datatype would be done. So I dunno why it would be any slower.
I think the safety thing is a non issue as well - what arguments could you pass in to the statically typed function that would cause the use of dynamic to bite you in the ass?
> A dynamic type is probably just implemented as a tagged bit of data, surely
A dynamic "type" is really just `object` whose methods are looked up at run time. It's not tagged data at all. See [1] for more info, specifically the example(s) at the bottom, as the reflection code is what gets executed at run (albeit with caching so that methods aren't looked up all the time).
`dynamic` is a complex feature that enables multiple dispatch as a side-effect, but only because it allows a whole lot more.
> what arguments could you pass in to the statically typed function that would cause the use of dynamic to bite you in the ass
public void Output(int value);
public void Output(Person person);
...
dynamic aValue = "Some String";
Output(aValue);
Compiles, because the actual resolving of which overload to call is done at runtime, not at compile time. And at runtime, there is no overload that accepts a string.
I am talking about what value you could pass into the multiple dispatch code in the article I linked to. I know you can cause run time type errors using dynamic in general, but in the code I linked it was very well contained and water tight.
Dynamically typed languages usually represent objects as something like a struct with an int tag to represent the type, and a void pointer for its value. The actual reflection going on in the code I posted for multiple dispatch would surely be nothing more than an int comparison - same as what Ocaml probably does.
> I am talking about what value you could pass into the multiple dispatch code in the article I linked to
Ah, I misunderstood the question. Yes, in that case it's fairly type-safe.
> The actual reflection going on in the code I posted for multiple dispatch would surely be nothing more than an int comparison
Is this based on gut reaction or are you talking about optimizations that `dynamic` performs? I ask because my understanding is that `dynamic` is like a really efficient reflection-emitter, that attempts to do at runtime the same thing that the compiler would do at compile time, but slower because it has to look stuff up via reflection.
From Eric Lippert [2]:
> The magic is: the compiler emits code that starts the C# compiler again at runtime. The runtime version of the compiler analyzes the call as though the compile-time types of all the objects had been their actual runtime types, generates an expression tree representing that call, compiles the expression tree, caches the delegate for next time, and runs the delegate.
So maybe `dynamic` at runtime figures out that it can do a "a struct with an int tag to represent the type, and a void pointer for its value", but I wouldn't assume it does and from what I've read on it, I wouldn't think that it does.
Base classes already have to carry their runtime type with them anyway. As do nodes of an algebraic data type. You may well be right that the compiler might not be "sufficiently smart" to see this very limited use of dynamic and realise no special reflection magic is actually required. But considering dynamic is only used to actually pull out the runtime type in the example code, and not to call arbitrary methods on it that may or not be there, I assumed - maybe wrongly - that the runtime hit would be the same as the branching that occurs in Ocaml or Haskell or F# when it comes across a "match" statement.
But to answer your question - yes, entirely based on gut reaction and what a compiler would ideally be able to do given the code posted. So very probably wrong.
> I think the safety thing is a non issue as well - what arguments could you pass in to the statically typed function that would cause the use of dynamic to bite you in the ass?
None if the function is written correctly, but by that logic you don't need type safety at all. The point is that the dynamic technique gives you no warning if you forget to implement one of the cases.
My point was that the dynamic technique in the posted code was written in a very small, contained point where it would be impossible due to the signature of the surrounding argument for it to go wrong.
void React(Animal me, Animal other)
{
ReactSpecialization(me as dynamic, other as dynamic);
}
Unless you pass in a casted value here, it's fool proof.
The point is that if you forget to write one of the ReactSpecialization methods nothing detects it. Perhaps more importantly, if you add a new type of Animal there's nothing to tell you you need to write a bunch of new ReactSpecializations.
Only if you deliberately add the catch-all case. If you don't and just handle all the cases explicitly, many languages will give you a warning or error when you add a new unhandled variant.
Reading this reminded me of all the discussions that took/are taking place for pattern matching in C#[0]; reading this I had the same reactions that I did for C#: cool stuff. It's also nice to see the languages reach parity in features; I only hope the two language committees pay attention to the research/feedback that the other receives.
> Should tuples be mutable or immutable? The nice thing about them being
> structs is that the user can choose. If a reference to the tuple is
> readonly then the tuple is readonly.
> Now a local variable cannot be readonly, unless we adopt #115 (which is
> likely), but that isn't too big of a deal, because locals are only used
> locally, and so it is easier to stick to an immutable discipline if you
> so choose.
> If tuples are used as fields, then those fields can be readonly if
> desired.