August 13, 2016 Re: Fact checking for my talk | ||||
---|---|---|---|---|
| ||||
Posted in reply to deadalnix | On Sat, 13 Aug 2016 16:28:57 +0000, deadalnix wrote:
> C# use generic (aka type erasure) for objects
Incorrect:
---
public class Foo {}
var fooList = new List<Foo>();
var objectList = (List<object>)(object)fooList;
---
This throws InvalidCastException. Which isn't possible with type erasure. The equivalent Java code will not throw an exception because, after type checking, List<T> is converted to List<Object>. That's the definition of type erasure.
Similarly, you can inspect the methods on List<Foo> at runtime in C# and see that, for instance, the `Add` method takes a parameter of type Foo. And you can look at the type of `fooList` with reflection and see that it's List with generic parameter 0 set to Foo. That's stuff you can't do with type erasure.
The code that .NET generates for a generic instantiation with class type is different from the code it generates for a generic instantiation for a struct simply because structs are not like classes.
|
August 13, 2016 Re: Fact checking for my talk | ||||
---|---|---|---|---|
| ||||
Posted in reply to Chris Wright | On Saturday, 13 August 2016 at 17:27:35 UTC, Chris Wright wrote:
> On Sat, 13 Aug 2016 16:28:57 +0000, deadalnix wrote:
>> C# use generic (aka type erasure) for objects
>
> Incorrect:
>
> ---
> public class Foo {}
> var fooList = new List<Foo>();
> var objectList = (List<object>)(object)fooList;
> ---
>
> This throws InvalidCastException. Which isn't possible with type erasure. The equivalent Java code will not throw an exception because, after type checking, List<T> is converted to List<Object>. That's the definition of type erasure.
>
> Similarly, you can inspect the methods on List<Foo> at runtime in C# and see that, for instance, the `Add` method takes a parameter of type Foo. And you can look at the type of `fooList` with reflection and see that it's List with generic parameter 0 set to Foo. That's stuff you can't do with type erasure.
>
> The code that .NET generates for a generic instantiation with class type is different from the code it generates for a generic instantiation for a struct simply because structs are not like classes.
I guess what he meant is that there will be just one code generation, as all class types are just pointers. So on this side it behaves like Java (if we only talk about reference types).
The difference is that the .NET IL retains complete type information for the variables, even if it dispatches to the same instantiation.
|
August 13, 2016 Re: Fact checking for my talk | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ethan Watson | On Saturday, 13 August 2016 at 12:47:40 UTC, Ethan Watson wrote: > | Rust | Swift | C# | > -----------------------------|---------+---------+---------| > Template Constraints | Y | Y | where | [1] > -----------------------------|---------+---------+---------| > Template "if" Constraints | where | where | where | > -----------------------------|---------+---------+---------| > static if | N | N | N | > -----------------------------|---------+---------+---------| > Eponymous templates | N | N | N | > -----------------------------|---------+---------+---------| > Compile time reflection | N | N | N | > -----------------------------|---------+---------+---------| > CTFE | N | N | N | > -----------------------------|---------+---------+---------| > User defined attributes | Crates | Runtime | Y | > -----------------------------|---------+---------+---------| Hmm... does "Crates" mean that the feature is available as an optional package on crates.io? Otherwise I fail to see the connection between crates and UDAs... > Deep function inspection | N | N | N | > -----------------------------|---------+---------+---------| > Mixins | N | N | N* | [2] > -----------------------------|---------+---------+---------| String mixins or template mixins? |
August 13, 2016 Re: Fact checking for my talk | ||||
---|---|---|---|---|
| ||||
Posted in reply to Liam McSherry | On 8/13/2016 6:02 AM, Liam McSherry wrote:
> For "static if," C# also has a very limited conditional compilation system that
> is barely comparable. Symbols can be defined at compile time, but they can't
> have values and they can only be used with specific directives:
> ---
> #define X
>
> #if X
> doA();
> #else
> doB();
> #endif
> ---
That seems to correspond with D's 'version' construct.
|
August 13, 2016 Re: Fact checking for my talk | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ethan Watson | On 8/13/2016 5:47 AM, Ethan Watson wrote:
> [2] Mixins in swift are essentially traits and protocol extentions, not like D
> mixins at all
s/extentions/extensions/
|
August 13, 2016 Re: Fact checking for my talk | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ethan Watson | On 8/13/2016 9:19 AM, Ethan Watson wrote:
> I believe Swift has something like Objective C does but I did not find concrete
> info on it. No idea about Rust.
It's risky to compare with languages you aren't strongly familiar with. All it takes is one mistake and one audience member who knows more than you about it, and it can seriously derail and damage the entire presentation.
I recommend sticking with describing the unique D features, and let the audience members who know other languages draw their own comparisons.
|
August 13, 2016 Re: Fact checking for my talk | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ethan Watson | On Sat, 13 Aug 2016 17:21:37 +0000, Ethan Watson wrote:
> On Saturday, 13 August 2016 at 17:19:42 UTC, Chris Wright wrote:
>> C# can do this. Check System.Reflection.MethodInfo and System.Reflection.ParameterInfo.
>
> Runtime only? I'll make the distinction on my slides.
Runtime only, but you can generate code at runtime, albeit awkwardly.
|
August 14, 2016 Re: Fact checking for my talk | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ethan Watson | On Saturday, 13 August 2016 at 12:47:40 UTC, Ethan Watson wrote: > So I fly to Cologne tomorrow morning, and will be presenting on Tuesday. Got my talk written, gave it a dry run at the office and got feedback on it. Seems to be in a good spot. > > But before I go up and feature compare to other languages, it'll be a good idea to get my facts right. > > There's three spots in my talk where I go through some D code, and then show a table indicating whether the features I used in those examples are available in other, trendier languages. In some cases, the features become available with after-market add ons. But I'm focusing exclusively on stuff you can get out of the box, ie write some code and compile it with a stock DMD/LDC/GDC/SDC install and it'll Just Work(TM). > > So here's a dodgy table indicating the features I'm showing on the slides, and the languages that are most relevant to game developers - C# and Swift - with Rust thrown in since that's the new language everyone knows about. > > If I've got something wrong with the out-of-the-box solution, please let me know. If there is something you can do with an add-on, also let me know since it will allow me to prepare for the inevitable audience questions saying "but you can do this with this etc etc" > > > | Rust | Swift | C# | > -----------------------------|---------+---------+---------| > Template Constraints | Y | Y | where | [1] > -----------------------------|---------+---------+---------| > Template "if" Constraints | where | where | where | > -----------------------------|---------+---------+---------| > static if | N | N | N | > -----------------------------|---------+---------+---------| > Eponymous templates | N | N | N | > -----------------------------|---------+---------+---------| > Compile time reflection | N | N | N | > -----------------------------|---------+---------+---------| > CTFE | N | N | N | > -----------------------------|---------+---------+---------| > User defined attributes | Crates | Runtime | Y | > -----------------------------|---------+---------+---------| > Deep function inspection | N | N | N | > -----------------------------|---------+---------+---------| > Mixins | N | N | N* | [2] > -----------------------------|---------+---------+---------| > > [1] Limited comparisons can be made with template where constraints > [2] Mixins in swift are essentially traits and protocol extentions, not like D mixins at all > static if N Rust does have an extremely limited form of static if - `#[cfg()]` [1] - similar to C#'s #if and D's `version ()` which (AFAIU [2]) can only test build-time constants. There's a cfg! macro [3] in the standard library which allows to evaluate (at CT) the expression for example in `if` statements, but it wont [4] delete the not-taken branch (so the code in both branches must be valid), which makes it quite useless. I found a `cfg_if!` macro in their libc FFI bindings [5], which it looks like it [6] can disable the not taken branch, but still, it's quite incapable compared to D's `static if`. > User defined attributes As per [7] currently you're not allowed to create your own attributes, only the Rust compiler defines them. From my understanding they're a syntax used for what `pragma`, `extern` and dub.json are used in D (in Rust packages (a.k.a crates) are built into the language). Rust attributes also cover many things for which usually the C/C++ __attribute__ extension is used. So I would say "N" on this one. Also note that in contrast with D, where attributes don't change the behavior of the attributed symbol, in Rust they're strictly used for controlling behavior. > Eponymous templates N > Compile time reflection N Yeah, definitely no. > Mixins N > CTFE N I would say that Rust macros are the closest thing to string mixins, but are still light years away, because they can't be generated imperatively like you can in D with CTFE. OTOH, they're used in more places in their standard library, than mixins are used in Phobos, because of the lack of variadic templates, because in Rust you can't generalize over mutability, like you can in D with `inout` and also because of the stupidly designed trait system (e.g. see [9]). From my understanding of Rust macros, they're kind of like the AliasSeq algorithms in std.meta (because they're declarative), but instead of operating on sequences (e.g. template arguments lists) they operate on Rust's AST (e.g. statements and expressions). Actually I guess you can say that they're similar to D's template mixins, with the exception that template mixins can't mix expressions and statements into your code - Rust macros operate at the AST level, whereas D template mixin's are a bit higher-level, closer to the type system. | Rust | Swift | C# | D | C++ | --------------------|---------+---------+---------+--------+---------+ Compiler plugins | Y [8] | N | Roslyn | N | Clang | --------------------|---------+---------+---------+--------|---------+ However their compiler plugin systems looks quite fleshed-out [8] (at least compared to D's situation) so that's one metaprogramming area where definitely Rust has the lead. [1]: https://doc.rust-lang.org/book/conditional-compilation.html [2]: https://doc.rust-lang.org/reference.html#conditional-compilation [3]: https://doc.rust-lang.org/std/macro.cfg!.html [4]: https://users.rust-lang.org/t/cfg-macro-for-features/1337 [5]: https://github.com/rust-lang/libc/blob/0.2.15/src/macros.rs#L9 [6]: https://github.com/rust-lang/libc/blob/0.2.15/src/windows.rs#L10 [7]: https://doc.rust-lang.org/book/attributes.html [8]: https://doc.rust-lang.org/book/compiler-plugins.html [9]: https://github.com/rust-lang/rust/blob/master/src/libcore/slice.rs#L804 |
August 14, 2016 Re: Fact checking for my talk | ||||
---|---|---|---|---|
| ||||
Posted in reply to ZombineDev | On Sunday, 14 August 2016 at 18:05:12 UTC, ZombineDev wrote: [...] > OTOH, they're used in more places in their standard library, than mixins are used in Phobos, because of the lack of variadic templates, because in Rust you can't generalize over mutability, like you can in D with `inout` and also because of the stupidly designed trait system (e.g. see [9]). I'm confused by your example. How exactly is Rust's trait system 'stupidly designed'? [...] > From my understanding of Rust macros, they're kind of like the AliasSeq algorithms in std.meta (because they're declarative), but instead of operating on sequences (e.g. template arguments lists) they operate on Rust's AST (e.g. statements and expressions). The AliasSeq algorithms are defined recursively for obvious reasons, but they rely on branching and a lot of obviously not declarative code in their definition. :? [...] > [9]: https://github.com/rust-lang/rust/blob/master/src/libcore/slice.rs#L804 |
August 14, 2016 Re: Fact checking for my talk | ||||
---|---|---|---|---|
| ||||
Posted in reply to Enamex | On Sunday, 14 August 2016 at 18:17:58 UTC, Enamex wrote: > On Sunday, 14 August 2016 at 18:05:12 UTC, ZombineDev wrote: > [...] >> OTOH, they're used in more places in their standard library, than mixins are used in Phobos, because of the lack of variadic templates, because in Rust you can't generalize over mutability, like you can in D with `inout` and also because of the stupidly designed trait system (e.g. see [9]). > > I'm confused by your example. How exactly is Rust's trait system 'stupidly designed'? Ok, maybe it's a matter of taste and opinion, but I consider them to be bad design (idea-wise, not implementation-wise) because they're sort of the opposite of DbI and compile-time duck-typing. Maybe they fit nicely in Rust's world but they're definitely something I would want NOT to use. Concepts/traits are useless when you have DbI, because you can implement them in a library if you need dynamic dispatch (e.g. std.range.InputRangeObject, std.experimental.allocator.allocatorObject, std.typecons.wrap, etc.). > [...] >> From my understanding of Rust macros, they're kind of like the AliasSeq algorithms in std.meta (because they're declarative), but instead of operating on sequences (e.g. template arguments lists) they operate on Rust's AST (e.g. statements and expressions). > > The AliasSeq algorithms are defined recursively for obvious reasons, but they rely on branching and a lot of obviously not declarative code in their definition. :? > and a lot of obviously not declarative code Like what? They're definitely not imperative (e.g. in-place mutation is not possible), so I consider them to be declarative. The fact you can call any imperative D function at CT as the conditional expression is just a nice coincidence. > [...] >> [9]: https://github.com/rust-lang/rust/blob/master/src/libcore/slice.rs#L804 |
Copyright © 1999-2021 by the D Language Foundation