{"action":"created","issue":{"url":"https://api.github.com/repos/qwertie/ecsharp/issues/26","repository_url":"https://api.github.com/repos/qwertie/ecsharp","labels_url":"https://api.github.com/repos/qwertie/ecsharp/issues/26/labels{/name}","comments_url":"https://api.github.com/repos/qwertie/ecsharp/issues/26/comments","events_url":"https://api.github.com/repos/qwertie/ecsharp/issues/26/events","html_url":"https://github.com/qwertie/ecsharp/issues/26","id":141753315,"number":26,"title":"Discuss: making a pluggable programming language","user":{"login":"qwertie","id":720717,"avatar_url":"https://avatars.githubusercontent.com/u/720717?v=3","gravatar_id":"","url":"https://api.github.com/users/qwertie","html_url":"https://github.com/qwertie","followers_url":"https://api.github.com/users/qwertie/followers","following_url":"https://api.github.com/users/qwertie/following{/other_user}","gists_url":"https://api.github.com/users/qwertie/gists{/gist_id}","starred_url":"https://api.github.com/users/qwertie/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/qwertie/subscriptions","organizations_url":"https://api.github.com/users/qwertie/orgs","repos_url":"https://api.github.com/users/qwertie/repos","events_url":"https://api.github.com/users/qwertie/events{/privacy}","received_events_url":"https://api.github.com/users/qwertie/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/qwertie/ecsharp/labels/discussion","name":"discussion","color":"4309d7"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":8,"created_at":"2016-03-18T02:02:13Z","updated_at":"2016-03-28T14:16:34Z","closed_at":null,"body":"Continuing from #12 .\r\n\r\nAgain, I haven't really coded in Rust yet so I don't have a complete sense of it yet. But my thinking right now is this: there is practical power in being able to say \"treat this as an `IFoo`—yeah, I know it doesn't explicitly implement IFoo, but it has all the methods of an IFoo so please treat it as one.\" That's what Go lets you do but Rust/Haskell do not.\r\n\r\nMy favorite example is `IList<T>`, which was defined first, and does not have `IReadOnlyList<T>` as a supertype even though the latter is merely a subset of the former. I have personally experienced the problems this causes, because \r\n\r\n1. if you really just want to accept a `IReadOnlyList<T>` but `IList<T>` is more popular, it is tempting to make an overload that accepts `IList<T>` and converts it (`.AsListSource()` extension method) to `IReadOnlyList<T>`. Likewise when implementing a read-only list, it's tempting to implement `IList<T>`  as well as `IReadOnlyList<T>` so it'll be compatible with libraries that only accept `IList<T>`.\r\n2. Together, this pair of accommodations causes pervasive \"ambiguity\" errors everywhere, which is a massive inconvenience that leads one to write a lot of extra methods to avoid the \"ambiguity\" errors. It is for this reason that I defined [`IListAndListSource<T>`](http://loyc.net/doc/code/interfaceLoyc_1_1Collections_1_1IListAndListSource_3_01T_01_4.html) and filled my source code with disambiguating overloads. Look for `IListAndListSource` overloads in [the `ListExt` class](https://github.com/qwertie/Loyc/blob/master/Core/Loyc.Essentials/Collections/ExtensionMethods/ListExt.cs) - it's a mess, there is no other way AFAIK to set it up that is convenient both for users of the old `IList` and new `IReadOnlyList`.\r\n\r\nI realize this is a much smaller problem in Rust than C#, because you are allowed to implement traits on types that originally did not implement them. However, the fact is, you shouldn't have to explicitly implement `IReadOnlyList<T>` at all, since it's just a subset of `IList<T>`. So I want a language that can just see this relationship by itself. Some would argue this shouldn't happen automatically... and there are cases when that makes sense. But even if there are cases when we don't want an automatic conversion, there are more cases where we clearly do, and I think a developer should have the option of getting an automatic conversion when one is desired. But of course, this means we need a solution other than littering call sites with conversions everywhere.\r\n\r\nAnother favorite example of mine would be the situation where a DLL wants to implement a \"plug-in\" interface. It's pretty silly to have to reference a tiny (say 4KB) assembly whose only purpose is to store the definition of an interface so that a plug-in can implement the interface. It would be better if the plug-in can define its own copy of the interface as source code, and then the host application can just cast the plug-in object to _its_ copy of the interface. In .NET this is impossible - both the host and the plug-in must have the \"same\" interface, and this means not only \"an interface with the same name and the same members in the same order\", but that it has to be stored in the same physical file on the hard drive too! That's waaay too restrictive IMO.\r\n\r\nAlso, I have a sense that Rust's \"coherence\", if that's defined as \"a given type can only have a single implementation of an interface/trait\", is unnecessarily restrictive. There may be some programming languages that do not have this restriction, or specific tricks you can do without it (e.g. different \"views\" of the same physical type), and therefore a language that wants to support as many type systems as possible shouldn't mandate \"coherence\". But I never studied Go deeply so I don't know if Go enforces coherence or not.\r\n\r\nI'm not sure how to \"unify\" all the type systems yet - to make them interoperable. One possible approach is \r\n\r\n1. start by thinking of \"what's the most flexible type system I know of - one that's a superset of most others?\" Union and intersection types come to mind. Possibly dependent types, except that I know nothing about them. If I start thinking low-level, I want tagged unions and pointers-that-can-also-be-integers (e.g. pointer turns into an integer if low bit = 1 - this is a core implementation detail for certain high-prformance data structures and an important implementation detail of interpreters such as Ruby.) Also, the CLR's run-time generics are great and I'd like to support them - it should be possible to instantiate new generic types at run-time. (On the other hand, because we want maximal flexibility, we ought to support C++-style templates too, which perhaps are not feasible to instantiate at runtime.)\r\n2. Based on the best ideas we can find, we design a single really flexible type system.\r\n3. Then survey several languages to see whether _their_ type system is effectively a subset of ours. If the answer is \"no\" then we ask \"what modifications are necessary to our type system to let it subsume that one?\"\r\n4. And all the while we should be asking ourselves, \"how can we modularize this, minimizing dependencies between components?\" Because when we figure that out, we'll have a way to allow 3rd-party type system components.\r\n\r\n**Note**: I would forget about type inference in the beginning - I think that's something we can figure out later, by asking the question \"what needs to be removed or altered to make type inference work well?\" But since type inference is an optional feature that some developers don't even _want_ (some see little value beyond the basics, like lambda type inference and the inference of `var` in C# - hell, I remember reading lots of opposition to \"var\" in C# 3.0, although I think most of those people are eating their words now.), I don't think we should dwell on it in the beginning.\r\n\r\nRight now I'm thinking of scaffold... a workspace where one could begin building a language with multiple type systems and multiple sets of rules. I'm thinking of a program as if it were a file system, with \"genericized\" folders called \"spaces\" (short for \"namespaces\"). A space can be a namespace, a C# class, a struct, an enum, a method body, or something else defined by a 3rd party. Each space can be parameterized. What are the parameters? I'm not sure what the parameters should be yet; it's tempting to say \"types\" but we don't even know what those are yet, and some people will want spaces parameterized by compile-time constants, as in C++ where you can use `Foo<17>`. In any case, the parameters are something that exists at compile-time, to permit genericity.\r\n\r\nEach space will have a \"kind\", like \"namespace\", \"enum\", \"interface\", \"class\", and so on. There would be special-purpose kinds, like \"C#-style class\" and \"Rust-style trait\". My thinking right now is that the \"kind\" specifies a \"gatekeeper\" for the space. It controls what can be added to the space (or maybe it just gives error messages when the wrong stuff is added), it is in charge of name resolution and overload resolution, and it might control how the type system works for code within the space.\r\n\r\n**Note**: I think parameterized namespaces are fantastic and I want a language with those. For instance I once wrote a series of math classes that supported different kinds of numbers; for example an \"affine transform\" class: `Transform3d<float>`, `Transform3d<double>`, and of course `Transform3d<FixedPoint<16> >` because an important target platform had a 400MHz CPU with no FPU. The point is, because the namespace itself cannot be parameterized, there were `<type parameters>` all over the place. If instead the number type were a parameter of the enclosing namespace, most of those `<angle brackets>` could disappear. This feature will make it easier to write generic code, and therefore programmers will write more generic code. **Edit**: Keep in mind, most people don't want to use `Transform3d<float>` and `Transform3d<double>`, but just one or the other - so it makes sense to write `using MathLibrary<double>` and drop the type parameters everywhere else.\r\n"},"comment":{"url":"https://api.github.com/repos/qwertie/ecsharp/issues/comments/202410410","html_url":"https://github.com/qwertie/ecsharp/issues/26#issuecomment-202410410","issue_url":"https://api.github.com/repos/qwertie/ecsharp/issues/26","id":202410410,"user":{"login":"jonathanvdc","id":9839946,"avatar_url":"https://avatars.githubusercontent.com/u/9839946?v=3","gravatar_id":"","url":"https://api.github.com/users/jonathanvdc","html_url":"https://github.com/jonathanvdc","followers_url":"https://api.github.com/users/jonathanvdc/followers","following_url":"https://api.github.com/users/jonathanvdc/following{/other_user}","gists_url":"https://api.github.com/users/jonathanvdc/gists{/gist_id}","starred_url":"https://api.github.com/users/jonathanvdc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jonathanvdc/subscriptions","organizations_url":"https://api.github.com/users/jonathanvdc/orgs","repos_url":"https://api.github.com/users/jonathanvdc/repos","events_url":"https://api.github.com/users/jonathanvdc/events{/privacy}","received_events_url":"https://api.github.com/users/jonathanvdc/received_events","type":"User","site_admin":false},"created_at":"2016-03-28T14:16:34Z","updated_at":"2016-03-28T14:16:34Z","body":"Aw, that's a shame. Quick-binding seems like a really useful feature. I like think of `x := y` as a generalization of the `var x = y;` pattern. Besides, weren't people opposed to `var` in the first place, as well?\r\n\r\nI think it's kind of funny that you write\r\n\r\n> Whatever syntax we use, actually implementing it will be challenging.\r\n\r\nbecause `fecs` implements `:=`, `=:` and \"block expressions\" out-of-the-box in just a few lines of code. [Quickbind.ecs](https://github.com/jonathanvdc/Flame.Loyc/blob/master/fecs/tests/ecs/Quickbind/Quickbind.ecs) works as expected.\r\n\r\nObviously, this problem is only easy from a compiler perspective. I can imagine that directly lowering block expressions to C# code is not entirely trivial. I remember implementing a pass that does just that: `-fimperative-code`, to support quick-bind-like code for `-platform c++`. I ended up spilling expression results into variables whenever a statement was encountered in an expression, to preserve the order of evaluation (Flame compiles block expressions down to expressions that contain statements)."}}