www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - More on Rust

reply bearophile <bearophileHUGS lycos.com> writes:
The Development of the Rust language from Mozilla and Graydon Hoare is going
on. It will probably become a quite interesting system language, quite more
interesting than Go. One of the most interesting features of Rust will be its
typestate.

Rust has structural typing too, this is sometimes useful (but to use it well
you need something like pattern matching used in functional languages like ML,
that I don't know if is present in Rust).


Graydon is following D idea of putting a basic unit testing feature in the
language:
https://mail.mozilla.org/pipermail/rust-dev/2010-December/000160.html
https://mail.mozilla.org/pipermail/rust-dev/2010-December/000163.html
https://mail.mozilla.org/pipermail/rust-dev/2010-December/000165.html
Rust also puts basic logging as a built-in feature.


This is a blog post about Rust type inference:
http://pcwalton.blogspot.com/2010/10/rust-features-i-type-inference.html

Rust doesn't have a whole program type inferencer (as ML), like a
Hindley-Milner algorithm, to keep things simple and allow separate compilation
(and probably to keep compilation times low, etc). So you have to give type to
function arguments, and if you want you are free to use "auto" everywhere
inside the function to infer types locally. I think this is good. So on this
it's quite similar to D, but there are some differences.

Rust allows to do this ("log" is a built-in logging feature, I don't know how
they call the logarithm function):


auto x;
if (localtime().hours >= 8) {
    x = "awake!"
} else {
    x = "asleep, go away."
}
log "I'm " + x;


From the blog post:

Rust features what I call feed-forward type inference, which is summed up by
this rule: Variables have no type until they are assigned a value, at which
point their type can't change.<

Here, we didn't initialize x in its declaration, but this code still compiles
and runs properly. This is because Rust is able to wait until x is assigned to
determine its type. Unlike, say, C# (and, of course, languages like ML in which
variables must be assigned a value at declaration time), Rust doesn't require
that auto declarations be initially assigned a value to determine a type for
them. At the same time, unlike C, the compiler will emit an error if you ever
forget to assign a value to the variable in any branch of your code. For
instance, if you omit the else branch above, the code won't compile.<

Rust is statically typed, so this is an error, it's not possible (unless you use some kind of variant): log "do you want to add strings or ints?"; auto use_str = input.readline == "strings"; if (use_str) { a = "hello "; b = "world!"; } else { a = 1; b = 1; } log a + b; Both branches of the "if" must assign the same types to a and b, like when in D you use an auto return type, and the D compiler makes sure all your return statements return exactly the same type. "Variables have no type until they are assigned a value, at which point their type can't change." looks meaningless if you see types as timeless things, that are are always true and immutable for a variable. But in Rust there are typestates, so while a variable can't change type, its type sometimes changes state along the flow of the code, such state of the type may be different in different parts of the code. Bye, bearophile
Feb 09 2011
next sibling parent reply so <so so.so> writes:
 Rust is statically typed, so this is an error, it's not possible (unless  
 you use some kind of variant):

Not quite clear in the example but just add an extra line after if block.
 log "do you want to add strings or ints?";
 auto use_str = input.readline == "strings";
 if (use_str) {
     a = "hello ";
     b = "world!";
 } else {
     a = 1;
     b = 1;
 }
 auto c = b - a; // wah?

 log a + b;

 ...

 Bye,
 bearophile

Already love it, lowercase ftw! Although built-in logging is nice, both the name and the operator of logging are very bad choices. Especially for a standard library.
Feb 09 2011
parent so <so so.so> writes:
 both the name and the operator of logging are very bad choices.

Oh '+' is string concat in Rust, and log is not that bad either!
Feb 09 2011
prev sibling next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"bearophile" <bearophileHUGS lycos.com> wrote in message 
news:iivb5n$na3$1 digitalmars.com...
 auto x;
 if (localtime().hours >= 8) {
    x = "awake!"
 } else {
    x = "asleep, go away."
 }
 log "I'm " + x;

That would be really nice to have in D. There's been many times I've needed to move a declaration up one scope from its initialization and was therefore forced to get rid of the "auto". Not a major problem obviously, but that sure would be nice.
Feb 09 2011
next sibling parent reply spir <denis.spir gmail.com> writes:
On 02/10/2011 06:43 AM, Nick Sabalausky wrote:
 "bearophile"<bearophileHUGS lycos.com>  wrote in message
 news:iivb5n$na3$1 digitalmars.com...
 auto x;
 if (localtime().hours>= 8) {
     x = "awake!"
 } else {
     x = "asleep, go away."
 }
 log "I'm " + x;

That would be really nice to have in D. There's been many times I've needed to move a declaration up one scope from its initialization and was therefore forced to get rid of the "auto". Not a major problem obviously, but that sure would be nice.

I don't like that at all. The second main feature of staticity if self-doc code. How is one, as a reader, supposed to guess what x is and means? I'm not a great fan of auto, neither, use it would happily live w/o it, except for functions operating on ranges, that return types coming from who-knows where (certainly another planet). Denis -- _________________ vita es estrany spir.wikidot.com
Feb 10 2011
parent reply Jean Crystof <a a.a> writes:
spir Wrote:

 On 02/10/2011 06:43 AM, Nick Sabalausky wrote:
 "bearophile"<bearophileHUGS lycos.com>  wrote in message
 news:iivb5n$na3$1 digitalmars.com...
 auto x;
 if (localtime().hours>= 8) {
     x = "awake!"
 } else {
     x = "asleep, go away."
 }
 log "I'm " + x;

That would be really nice to have in D. There's been many times I've needed to move a declaration up one scope from its initialization and was therefore forced to get rid of the "auto". Not a major problem obviously, but that sure would be nice.

I don't like that at all. The second main feature of staticity if self-doc code. How is one, as a reader, supposed to guess what x is and means? I'm not a great fan of auto, neither, use it would happily live w/o it, except for functions operating on ranges, that return types coming from who-knows where (certainly another planet).

How about this? spir Wrote: auto x = if (localtime().hours>= 8) { "awake!" } else { "asleep, go away." }; log "I'm " + x; I think it solves the problem of unkown type for x nicely. And it's very close to what we already have. something ? foo : bar might do the same, but if() [} else {} is much more readable IMO.
Feb 10 2011
parent Jesse Phillips <jessekphillips+D gmail.com> writes:
Jean Crystof Wrote:

 How about this?
 spir Wrote:
 
 auto x =
   if (localtime().hours>= 8) {
     "awake!"
   } else {
     "asleep, go away."
   };
 
 log "I'm " + x;
 
 I think it solves the problem of unkown type for x nicely. And it's very close
to what we already have. something ? foo : bar might do the same, but if() [}
else {} is much more readable IMO.

Humm, what we currently have: auto x = { if (localtime().hours>= 8) { "awake!" } else { "asleep, go away." }; }(); log "I'm " + x;
Feb 10 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 2/10/11, spir <denis.spir gmail.com> wrote:
 I'm not a great fan of auto, neither, use it would happily live w/o it,
 except
 for functions operating on ranges, that return types coming from who-knows
 where (certainly another planet).

auto is great for rapid prototyping. And so are templated functions. After I'm satisfied with the functionality of my code I usually replace much of my use of auto with the actual type (mostly variable declarations). auto is still useful in templates, where writing a return type can be complicated.
Feb 10 2011
prev sibling next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
Nick Sabalausky wrote:
 "bearophile" <bearophileHUGS lycos.com> wrote in message 
 news:iivb5n$na3$1 digitalmars.com...
 auto x;
 if (localtime().hours >= 8) {
    x = "awake!"
 } else {
    x = "asleep, go away."
 }
 log "I'm " + x;

That would be really nice to have in D.

auto x = (localtime().hours >= 8) ? "awake!" : "asleep, go away.";
Feb 10 2011
next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2011-02-10 20:15, Walter Bright wrote:
 Nick Sabalausky wrote:
 "bearophile" <bearophileHUGS lycos.com> wrote in message
 news:iivb5n$na3$1 digitalmars.com...
 auto x;
 if (localtime().hours >= 8) {
 x = "awake!"
 } else {
 x = "asleep, go away."
 }
 log "I'm " + x;

That would be really nice to have in D.

auto x = (localtime().hours >= 8) ? "awake!" : "asleep, go away.";

For this simple if statement it works but as soon you have a few lines in the if statement it will become really ugly. But one could wrap the if statement in a function instead. In other languages where statements really are expressions this works: auto x = if (localtime().hours >= 8) "awake!"; else "asleep, go away."; log "I'm " + x; -- /Jacob Carlborg
Feb 10 2011
parent reply Jim <bitcirkel yahoo.com> writes:
Jacob Carlborg Wrote:

 On 2011-02-10 20:15, Walter Bright wrote:
 Nick Sabalausky wrote:
 "bearophile" <bearophileHUGS lycos.com> wrote in message
 news:iivb5n$na3$1 digitalmars.com...
 auto x;
 if (localtime().hours >= 8) {
 x = "awake!"
 } else {
 x = "asleep, go away."
 }
 log "I'm " + x;

That would be really nice to have in D.

auto x = (localtime().hours >= 8) ? "awake!" : "asleep, go away.";

For this simple if statement it works but as soon you have a few lines in the if statement it will become really ugly. But one could wrap the if statement in a function instead. In other languages where statements really are expressions this works: auto x = if (localtime().hours >= 8) "awake!"; else "asleep, go away."; log "I'm " + x;

Other languages may have bloated syntaxes, with no particular benefit. auto x = localtime().hours >= 8 ? "awake!" : "asleep, go away."; log( "I'm " ~ x ); If the expressions are complex I put them in functions. 1) It hides and isolates details, which allows you to focus on the more abstract aspects. 2) It gives the expression a name and facilitates reuse.
Feb 10 2011
next sibling parent Jean Crystof <a a.a> writes:
Jim Wrote:

 Jacob Carlborg Wrote:
 
 On 2011-02-10 20:15, Walter Bright wrote:
 Nick Sabalausky wrote:
 "bearophile" <bearophileHUGS lycos.com> wrote in message
 news:iivb5n$na3$1 digitalmars.com...
 auto x;
 if (localtime().hours >= 8) {
 x = "awake!"
 } else {
 x = "asleep, go away."
 }
 log "I'm " + x;

That would be really nice to have in D.

auto x = (localtime().hours >= 8) ? "awake!" : "asleep, go away.";

For this simple if statement it works but as soon you have a few lines in the if statement it will become really ugly. But one could wrap the if statement in a function instead. In other languages where statements really are expressions this works: auto x = if (localtime().hours >= 8) "awake!"; else "asleep, go away."; log "I'm " + x;

Other languages may have bloated syntaxes, with no particular benefit. auto x = localtime().hours >= 8 ? "awake!" : "asleep, go away."; log( "I'm " ~ x );

You're right. ? : is a masterpiece among syntaxes. Maybe a bit too terse, but it does exactly what people expect it to do and it has existed since C was born.
Feb 11 2011
prev sibling next sibling parent Jacob Carlborg <doob me.com> writes:
On 2011-02-11 08:39, Jim wrote:
 Jacob Carlborg Wrote:

 On 2011-02-10 20:15, Walter Bright wrote:
 Nick Sabalausky wrote:
 "bearophile"<bearophileHUGS lycos.com>  wrote in message
 news:iivb5n$na3$1 digitalmars.com...
 auto x;
 if (localtime().hours>= 8) {
 x = "awake!"
 } else {
 x = "asleep, go away."
 }
 log "I'm " + x;

That would be really nice to have in D.

auto x = (localtime().hours>= 8) ? "awake!" : "asleep, go away.";

For this simple if statement it works but as soon you have a few lines in the if statement it will become really ugly. But one could wrap the if statement in a function instead. In other languages where statements really are expressions this works: auto x = if (localtime().hours>= 8) "awake!"; else "asleep, go away."; log "I'm " + x;

Other languages may have bloated syntaxes, with no particular benefit. auto x = localtime().hours>= 8 ? "awake!" : "asleep, go away."; log( "I'm " ~ x ); If the expressions are complex I put them in functions. 1) It hides and isolates details, which allows you to focus on the more abstract aspects. 2) It gives the expression a name and facilitates reuse.

And that was the first thing I said one could do. -- /Jacob Carlborg
Feb 11 2011
prev sibling parent Jim <bitcirkel yahoo.com> writes:
spir Wrote:

 On 02/11/2011 08:39 AM, Jim wrote:
 Jacob Carlborg Wrote:

 On 2011-02-10 20:15, Walter Bright wrote:
 Nick Sabalausky wrote:
 "bearophile"<bearophileHUGS lycos.com>  wrote in message
 news:iivb5n$na3$1 digitalmars.com...
 auto x;
 if (localtime().hours>= 8) {
 x = "awake!"
 } else {
 x = "asleep, go away."
 }
 log "I'm " + x;

That would be really nice to have in D.

auto x = (localtime().hours>= 8) ? "awake!" : "asleep, go away.";

For this simple if statement it works but as soon you have a few lines in the if statement it will become really ugly. But one could wrap the if statement in a function instead. In other languages where statements really are expressions this works: auto x = if (localtime().hours>= 8) "awake!"; else "asleep, go away."; log "I'm " + x;

Other languages may have bloated syntaxes, with no particular benefit. auto x = localtime().hours>= 8 ? "awake!" : "asleep, go away."; log( "I'm " ~ x ); If the expressions are complex I put them in functions. 1) It hides and isolates details, which allows you to focus on the more abstract aspects. 2) It gives the expression a name and facilitates reuse.

Agreed. But in practice I often end up beeing dubious about seemingly nice features like, precisely, the ternary operator. In languages that do not have such a nicety people end up writng eg: if (localtime().hours>= 8) x = awake; else x = "asleep, go away."; Apart from the very mild annoyance, I guess, of writing twice "x =", this is all gain: code is both more compact and legible. Precisely, because the ternary operator is a bit weird syntactically (and not that commonly needed and used in real code), people feel, just like you, the need to clarify it in code, finally using more vertical space. Note that the case here is the simplest possible, expressions being plain literal constants. I personly only consume 3 lines: auto x = (localtime().hours>= 8) ? "awake!" : "asleep, go away."; What do you think?

I always make a conscious effort to write succinct expressions. My rule is to only use the ternary operator when it actually makes the code cleaner. Why? Branches should be conspicuous because they increase the number of code paths. Exceptions are the other big source of code paths. This is, btw, why I think that scope statements in D are just superb.
Feb 11 2011
prev sibling parent Christopher Nicholson-Sauls <ibisbasenji gmail.com> writes:
On 02/10/11 13:49, Andrej Mitrovic wrote:
 On 2/10/11, Walter Bright <newshound2 digitalmars.com> wrote:
 auto x = (localtime().hours >= 8) ? "awake!" : "asleep, go away.";

Aye, a one liner! I hate seeing things like this: if (funcall()) { var = "foo"; } else { var = "bar"; } So much clutter instead of using the simple: var = funcall() ? "foo" : "bar"; I also see this sometimes: auto var = funcall(); if (var == "foo" || var == "bar" || var == "foobar" || var == "barfoo") { // some complex code } else if (var == "blue" || var == "green") { // some complex code } else if ()// more and more code.. { } But not many people seem to know that D supports strings in case statements: switch(funcall()) { case "foo": case "bar": case "foobar": case "barfoo": { // complex code } break; case "blue": case "green": { // complex code } break; default: }

Even better: switch( funcall() ) { case "foo", "bar", "foobar", "barfoo": { // complex code break; } case "blue", "green": { // complex code break; } default: // do nothing -- i like to comment defaults } Also often forgotten, that 'case' clauses take an argument list, not just an expression. And yeah, in this case at least... it still fits in 80 columns. (I prefer 90 myself, but it's moot.) -- Chris N-S
Feb 11 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 2/10/11, Walter Bright <newshound2 digitalmars.com> wrote:
 auto x = (localtime().hours >= 8) ? "awake!" : "asleep, go away.";

Aye, a one liner! I hate seeing things like this: if (funcall()) { var = "foo"; } else { var = "bar"; } So much clutter instead of using the simple: var = funcall() ? "foo" : "bar"; I also see this sometimes: auto var = funcall(); if (var == "foo" || var == "bar" || var == "foobar" || var == "barfoo") { // some complex code } else if (var == "blue" || var == "green") { // some complex code } else if ()// more and more code.. { } But not many people seem to know that D supports strings in case statements: switch(funcall()) { case "foo": case "bar": case "foobar": case "barfoo": { // complex code } break; case "blue": case "green": { // complex code } break; default: } Not everybody will like this since it wastes a lot of vertical space. But at least it fits in 80 columns! (:p). Plus you don't need to create a temporary variable. The cool thing is the compiler will warn you if you miss out setting the default switch, which is something you won't get with if/elseif's. The final switch statement is even better when using enums. Added another enum member, but forgot to update the final switch statement? Boom, compiler error! It's a great thing for avoiding bugs imo.
Feb 10 2011
prev sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 2/11/11, Christopher Nicholson-Sauls <ibisbasenji gmail.com> wrote:
 Even better:

 switch( funcall() ) {
     case "foo", "bar", "foobar", "barfoo": {
         // complex code
         break;
     }

     case "blue", "green": {
         // complex code
         break;
     }

     default:
         // do nothing -- i like to comment defaults
 }

 Also often forgotten, that 'case' clauses take an argument list, not
 just an expression.  And yeah, in this case at least... it still fits in
 80 columns.  (I prefer 90 myself, but it's moot.)

 -- Chris N-S

Damn I didn't know that! Thanks.
Feb 11 2011
prev sibling next sibling parent spir <denis.spir gmail.com> writes:
On 02/11/2011 08:39 AM, Jim wrote:
 Jacob Carlborg Wrote:

 On 2011-02-10 20:15, Walter Bright wrote:
 Nick Sabalausky wrote:
 "bearophile"<bearophileHUGS lycos.com>  wrote in message
 news:iivb5n$na3$1 digitalmars.com...
 auto x;
 if (localtime().hours>= 8) {
 x = "awake!"
 } else {
 x = "asleep, go away."
 }
 log "I'm " + x;

That would be really nice to have in D.

auto x = (localtime().hours>= 8) ? "awake!" : "asleep, go away.";

For this simple if statement it works but as soon you have a few lines in the if statement it will become really ugly. But one could wrap the if statement in a function instead. In other languages where statements really are expressions this works: auto x = if (localtime().hours>= 8) "awake!"; else "asleep, go away."; log "I'm " + x;

Other languages may have bloated syntaxes, with no particular benefit. auto x = localtime().hours>= 8 ? "awake!" : "asleep, go away."; log( "I'm " ~ x ); If the expressions are complex I put them in functions. 1) It hides and isolates details, which allows you to focus on the more abstract aspects. 2) It gives the expression a name and facilitates reuse.

Agreed. But in practice I often end up beeing dubious about seemingly nice features like, precisely, the ternary operator. In languages that do not have such a nicety people end up writng eg: if (localtime().hours>= 8) x = awake; else x = "asleep, go away."; Apart from the very mild annoyance, I guess, of writing twice "x =", this is all gain: code is both more compact and legible. Precisely, because the ternary operator is a bit weird syntactically (and not that commonly needed and used in real code), people feel, just like you, the need to clarify it in code, finally using more vertical space. Note that the case here is the simplest possible, expressions being plain literal constants. I personly only consume 3 lines: auto x = (localtime().hours>= 8) ? "awake!" : "asleep, go away."; What do you think? Denis -- _________________ vita es estrany spir.wikidot.com
Feb 11 2011
prev sibling parent Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
On 10/02/2011 00:23, bearophile wrote:
 But in Rust there are typestates, so while a variable can't change type, its
type sometimes changes state along the flow of the code, such state of the type
may be different in different parts of the code

Hum, this typestate concept actually looks quite interesting. I need to look in more detail, but it seems similar to some ideas I roughly considered several times before, about having a language being able to track which assertions are true for a given variable/value at any (or most) given points in code. I'm fond of ideas that could make a static type system even more powerful (more checking capabilities), without making it significantly more obtuse or verbose. I wonder if many improvements could be made on this area, enough even for it to be considered a significant step forward in language design/evolution. Oh how I wish that a day would have 48 hours... -- Bruno Medeiros - Software Engineer
Feb 23 2011