July 22, 2015
On Wednesday, 22 July 2015 at 20:43:04 UTC, simendsjo wrote:
> When "everything" is an expressions, you can write things like
>     auto a = if(e) c else d;
>
> In D you have to write
>     type a = invalid_value;
>     if(e) a = c;
>     else  a = d;
>     assert(a != invalid_value);
>


I prefer this example from one of the various Rust tutorials

let foo = if x == 5 {
                "five"
          }
          else if x == 6 {
                "six"
          }
          else {
                "neither"
          }

You're basically using a conditional expression as an rvalue. You can do the same thing with a { } block.
July 22, 2015
On Wednesday, 22 July 2015 at 21:03:52 UTC, simendsjo wrote:
>> Macros are utterly horrible and pretty much unusable outside
>> of advanced library internals.
>
> Not sure what you are referencing here. Macros expand to code. If
> you compare this to string mixins, they are a lot easier for tool
> writers, but a lot less powerful.

Compared to string mixins they require much much more effort to learn and reason about. In our meetup group no one was able to figure out meaning of any small sample macro without detailed explanation. Compared to string mixins they are much harder to abuse because of inherent hygiene but also much harder to start using, while in D the concept comes quick and naturally but requires discipline to get used in maintainable fashion.

And they definitely don't feel any easier for library writers from my personal experience. More maintainable - yes, but not easier at all.

>> Recently I attended local Rust meetup for curious newcomers - it was very interesting to observe reaction of unbiased devs not familiar with D at all. General reaction was "this is awesome interesting language that I would never use for any production system unless I am crazy or can throw away money like crazy". Because, well, productivity.
>
> I'm having some problems interpreting this. This is people in
> a Rust meetup - in other words, early adopters. And they thing
> D is crazy "becuse productivity"? I don't understand what you
> mean.

Not early adopters, more like curious group learning new stuff together. And "crazy" was about Rust and how impractical it is for real business needs they have. No one has ever mentioned D there.


July 22, 2015
On Wednesday, 22 July 2015 at 21:36:58 UTC, jmh530 wrote:
> On Wednesday, 22 July 2015 at 20:43:04 UTC, simendsjo wrote:
>> When "everything" is an expressions, you can write things like
>>     auto a = if(e) c else d;
>>
>> In D you have to write
>>     type a = invalid_value;
>>     if(e) a = c;
>>     else  a = d;
>>     assert(a != invalid_value);
>>
>
>
> I prefer this example from one of the various Rust tutorials
>
> let foo = if x == 5 {
>                 "five"
>           }
>           else if x == 6 {
>                 "six"
>           }
>           else {
>                 "neither"
>           }
>
> You're basically using a conditional expression as an rvalue. You can do the same thing with a { } block.

Admittedly nowhere near as clean, but if you can bear to see the "return"s, function literals can turn any bunch of code in to an expression:

auto foo = { if(x == 5)
                         return "five";
                     else if(x == 6)
                         return "six";
                     else
                         return "neither";
                   }();

or of course there's the perhaps overly terse (brackets optional, i like them to visually group the condition with the ? ):

auto foo = (x == 5)? "five"
                   : (x == 6)? "six"
                   : "neither";
July 22, 2015
On Wednesday, 22 July 2015 at 18:47:33 UTC, simendsjo wrote:
>
> Traits
> ------
> I think the ability to express an interface without buying into inheritance is the right move. The alternative in D is specifying the behavior as a template and verifying the contract in a unittest for the type.

Rust only has structs. I'm not as familiar with them so it's not as clear how they overlap with D's structs and classes. It seems like you can put Rust structs on the stack or heap.

Others have already commented on how you can basically accomplish the same thing with templates, static ifs, and assert. That was my first thought as well. Nevertheless, I would add that Rust's ability to use multiple traits in the template constraints is a positive.

However, it seems like the essence of a trait in Rust is forcing some user-defined type to implement some functionality. That sounds a lot like an interface in D to me. In fact, Rust's traits seem different from Scala and PHP traits in that I don't see any examples with them using implementation. The two biggest differences between Rust traits and D interfaces are 1) inheritance of Rust traits (to my knowledge D does not have inheritance for interfaces, am I wrong?), 2) Rust traits can be easily used in template constraints. Those both seem like positives to me, though I'm not sure if they can be easily changed in D.

If you look at the Rust book's main example on traits. They use them to implement a print_area function that can only be called with structs that have a trait HasArea defined. Classes in pretty much any OOP language could use inheritance to implement a simpler version where print_area is a method instead of a separate function.

To play devil's advocate, writing a bunch of code with templates/static ifs/assert is definitely more confusing for someone new to the language than Rust's traits are. A lot of the D code makes quite a bit of sense when you understand how the different ideas combine together, but it takes a while to figure it out.

If traits were deemed important enough to add to D, I would suggest just extending interfaces so that they have inheritance and can be easily used in template constraints. I would be more interested in seeing some of these OOP features come to structs, but I have no idea how much work that requires. I feel like alias this is hacky compared to real inheritance.

>
> Algebraic data types
> --------------------
> Haven't looked into `Algebraic!`, so I won't start bashing D here :) But given the lack of pattern matching, I doubt it will be as pretty as Rust.

It seems like D's Algebraic does not allow for recursive Algebraic Types currently, whereas Rust's does. I'm honestly not that familiar with the concept. Seems cool, but I'm not sure I've ever really needed it.

>
> Borrowing
> ---------
> This is probably the big thing that makes Rust really different.  Everything is a resource, and resources have an owner and a lifetime. As a part of this, you can either have multiple aliases with read-only references, or a single reference with a writeable reference. I won't say I have a lot of experience with this, but it seems like it's not an extremely unergonomic trade-off. I cannot even remotely imagine the amount of possible compiler optimizations possible with this feature.
>

I feel like it's hard to separate borrowing from Rust's variety of pointers (& is borrowed pointer, ~ is for unique pointer, @ is for managed pointer). Nevertheless, I think having them part of the language with relatively straightforward syntax is a positive for Rust. Also, my understanding is that they are checked at compile-time for safety (at least unique and managed).

However, I feel like borrowing and lifetimes have a bit of a learning curve to them. I've read a few tutorials without a good sense of them. I would probably need to program a bit in it to grok it. I think part of it is that Rust has = potentially meaning copy or move depending on whether it is defined. Perhaps they need a separate move assignment, like <- and -> or something (to steal syntax from R, even though that's not what <- and -> do in R).
July 22, 2015
On Wednesday, 22 July 2015 at 22:35:54 UTC, John Colvin wrote:
>
> Admittedly nowhere near as clean, but if you can bear to see the "return"s, function literals can turn any bunch of code in to an expression:
>

Honestly, I don't mind doing things the D way (and I probably wouldn't have even done that your way). I just think it's interesting when another programming language has a cool feature.
July 22, 2015
On Wednesday, 22 July 2015 at 18:47:33 UTC, simendsjo wrote:
> ...

I think rust makes the ugliness of D's "push everything into phobos for simplicity" become very visible. D and Rust share many equal constructs, but D's is almost always uglier.
July 23, 2015
I've not used Rust, but don't plan to.

On Wednesday, 22 July 2015 at 18:47:33 UTC, simendsjo wrote:
> While code.dlang.org has 530 packages, crates.io has 2610 packages,

I think this tells something foremost about the size of the community. More people leads to more code.

> Traits
> ------
> I think the ability to express an interface without buying into inheritance is the right move. The alternative in D is specifying the behavior as a template and verifying the contract in a unittest for the type.

Traits can't do Design by Introspection aka compile-time duck.
C++ can on the other hand.

> Algebraic data types
> --------------------
> Haven't looked into `Algebraic!`, so I won't start bashing D here :) But given the lack of pattern matching, I doubt it will be as pretty as Rust.

You can pattern-match with visit.

> Macros
> ------
> I haven't written more than extremely simple macros in Rust, but having macros that is possible for tools to understand is a win.  Templates and string mixins is often used for this purpose, but trying to build tools when string mixins exists is probably extremely hard. If D had hygenic macros, I expect several features could be expressed with this instead of string mixins, making tooling easier to implement.

There is a difference though: Rust forces macros on you on the get go, while in D string mixing are quite a rare occurence thanks to other meta things and don't have a weird separate syntax. Regular templates + tuple foreach + static if is just easier to debug.


> Borrowing
> ---------
> This is probably the big thing that makes Rust really different.  Everything is a resource, and resources have an owner and a lifetime. As a part of this, you can either have multiple aliases with read-only references, or a single reference with a writeable reference. I won't say I have a lot of experience with this, but it seems like it's not an extremely unergonomic trade-off. I cannot even remotely imagine the amount of possible compiler optimizations possible with this feature.

The problem I see with this is that it is exactly like C++ scoped ownership except enforced. Even in Rust meeting they said they were converging on C++. It remotely feels like the same language to me.

I've worked in fully scoped ownership codebases, it's very nice and consistent, and you don't feel like you would need anything else while doing it. You must train everyone to do it. Enforcing it in the language? I'm not sure about this. There are time where you debug and you have to comment stuff out wildly.

Also if you are going to replace C++, it is a given to at least compile faster, make solve problem #1.



July 23, 2015
On 2015-07-22 20:47, simendsjo wrote:

> Traits
> ------
> I think the ability to express an interface without buying into
> inheritance is the right move. The alternative in D is specifying the
> behavior as a template and verifying the contract in a unittest for the
> type.

I completely agree and don't really like the approach D has implemented template constraints. Yeah I know, Andrei will destroy this :)

> Macros
> ------
> I haven't written more than extremely simple macros in Rust, but having
> macros that is possible for tools to understand is a win. Templates and
> string mixins is often used for this purpose, but trying to build tools
> when string mixins exists is probably extremely hard. If D had hygenic
> macros, I expect several features could be expressed with this instead
> of string mixins, making tooling easier to implement.

I completely agree. String mixins are one of the most ugliest features.

> Safe by default
> ---------------
> D is often said being safe by default, but D still has default nullable
> references and mutable by default. I don't see it being possible to
> change at this stage, but expressing when I want to be unsafe rather
> than the opposite is very nice. I end up typing a lot more in D than
> Rust because of this.

Agree.

> Pattern matching
> ----------------
> Ooooh... I don't know what to say.. D should definitely look into
> implementing some pattern matching! final switch is good for making sure
> all values are handled, but deconstructing is just so ergonomic.

Yeah, pattern matching is soooo nice. I've been trying to implement something similar in D as a library, something like this:

auto foo = Foo();
match!(foo
    Foo, (int a, int b) => writeln(a, b);
);

Which kind of works for deconstructing variable pattern. But then you want to have a pattern where "a" is 1, they it becomes much harder:

match!(foo
    Foo, (value!(1), int b) => writeln(b);
);

Or

match!(foo
    Foo, 1, (int b) => writeln(b);
);

But now you need to use different syntax for value pattern and variable pattern and soon everything becomes a big mess.

It will never be as good as proper language support.

> Expressions
> -----------
> This probably also falls in the "too late" category, but
> statements-as-expressions is really nice. `auto a = if ...` <- why not?

I really like, I use it a lot in Scala. The with the combination of automatically return the last thing in a method and methods not needing curly braces for single expression methods is really nice:

def foo(a: String) =
  if (a == "foo")
    1
  else if (a == "bar")
    2
  else
    3


> On the breaking part, the
> real issue is the "We're not going to break any code!" stance, while
> each release still breaks every codebase. The effect is that a lot of
> really long-term necessary breaking changes is never accepted - the only
> breaking changes is the unintended breaking changes!

Agree.

-- 
/Jacob Carlborg
July 23, 2015
On 2015-07-22 21:41, Jack Stouffer wrote:

> Dub is endorsed by the leadership and is included in the same Github
> organization as the complier and the standard library

It's not available in the Downloads, Compiler & Tools or Resources sections on dlang.org, so I disagree.

-- 
/Jacob Carlborg
July 23, 2015
On 2015-07-22 21:52, Alex Parrill wrote:

> You can make a `conformsToSomeInterface!T` template, and use `static
> assert`. D ranges, and the upcoming std.allocator, already use this sort
> of 'interfaces without polymorphism'.
>
> Ex. `static assert(isInputRange!(MyCoolRange));`

I would be a lot more cleaner to be able to do this:

void foo (T : MyCoolRange) (T range);

Or just:

void foo (MyCoolRange range);


> Most of what macros in C were used for are now done with templates,
> static if, etc. (I don't know how Rust's macros work). Tools could
> theoretically execute `mixin`, but it effectively requires a D
> interpreter. A library to do that would be really nice.

Macros in C have nothing to do with macros in Rust, which are called AST macros or syntax macros. It's unfortunate that they use the same word, "macro".

If D macros you could do something like this:

auto person = Person.where(e => e.name == 'Foo');

Where the lambda would be translated do an SQL string and performs a query in a database.

-- 
/Jacob Carlborg