

New for loops in Rust - nikomatsakis
http://brson.github.com/rust/2012/04/05/new-for-loops/

======
chubot
I'm going to make a superficial comment and say that "cont" and "ret" are
annoying and gratuitous differences. C/C++, Java, Python, JavaScript, and I
think Perl/Ruby/Go all use "continue" and "break". It's just pointless to be
different in this respect.

A different concept should use different syntax -- and it looks like Rust has
several new concepts where they can invent whatever syntax they want. But the
same concept should use the same syntax.

~~~
p4lindromica
ruby uses the next keyword for continue

~~~
mahmud
C++ and Java iterators use next as well.

~~~
tedunangst
Calling next on an iterator and continue in a loop do very different things.
C++ iterators use ++ too, but even though ++ and loops are often found
together, I would not list ++ and continue as even remotely synonymous.

------
vilya
This looks like a bad design. It means either (a) the semantics of 'ret'
inside a lambda function can change depending on the call site (whether it's
used inside a for loop or not); (b) that a lambda function passed in from
elsewhere can cause your function to return early; or (c) that lambda
functions have different syntax rules depending on where they're being
defined. All of which seem equally bad!

I hope there's something I've missed. I've been quite impressed by the rest of
the language so far & it would be a shame if they got this wrong.

~~~
nikomatsakis
You're missing something. The semantics of `ret` are always consistent: it
always returns from out the innermost `fn()` declaration (closures written
using the sugared notation `{||...}` do not count as fn declarations, but
closures written as `fn() { ... }` do). In cases where this is not possible, a
static error is generated.

~~~
vilya
So what happens if we pass a stack closure containing a ret into another
function? For example, what would this code print out:

    
    
      fn foo(f: fn()) {
        log(info, "calling f");
        f();
        log(info, "called f");
      }
    
      fn bar() {
        log(info, "calling foo");
        foo({||
          ret;
        });
        log(info, "called foo");
      }
    

I'm not clear on whether the ret would return from foo or from bar - or
whether it would be a compile error.

BTW thanks for taking the time to reply - I appreciate it!

~~~
kibwen
Tried compiling this myself with a main function that just calls bar(),
resulting in a compiler error:

    
    
      `ret` in block function

------
kibwen
For anyone who's wondering what the point of all this is, here are the
discussions that help to explain the impetus for this change:

[https://mail.mozilla.org/pipermail/rust-
dev/2012-February/00...](https://mail.mozilla.org/pipermail/rust-
dev/2012-February/001432.html)

[https://mail.mozilla.org/pipermail/rust-
dev/2012-March/00149...](https://mail.mozilla.org/pipermail/rust-
dev/2012-March/001490.html)

<https://github.com/mozilla/rust/issues/1619>

As far as I remember it has to do with the prior inability to handle non-local
returns and the desire to honor Tennent's Correspondence Principle.

------
frewsxcv
Seems a bit...overly complex.

Also, what is the appeal to '::' instead of just '.'

Kill the semicolons with fire

~~~
zeugma
Rust is inspired by C++ which use '::' to access names inside a namespace,
here 'vec' and io are module/namespace not object, it's a static lookup.

'.' is still used for object lookup which is dynamic.

------
p4lindromica
Why is there so much sugar?! Can't a keyword just be a keyword?

~~~
exDM69
> Why is there so much sugar?! Can't a keyword just be a keyword?

Statements based on keywords _are_ syntactic sugar. What I'm seeing here in
Rust is the complete opposite, building an iteration statement from language
built-ins. It does include some sugar in it (and "for" is a special keyword)
but the semantics of the construct is based on lambda calculus and other lower
level constructs in Rust.

In general, it's better that a language has as little special syntax that
cannot be constructed from elementary blocks. The gaps are then bridged by
adding a little sugar coating to make programming convenient (for humans) but
keeping the core language clear and concise (for interpreters and compilers).

For example, in C, you cannot define your own loop structures and you're stuck
with for, do and while (C macros are so crappy that they don't count).
Haskell, on the other hand, does not have any special iteration statements in
the language core but there's a handful of iteration functions that are
regular functions and you are free to define your own. Same thing with Scheme
(and other Lisps).

~~~
frewsxcv
This is more like Splenda, not sugar

------
gioele
> the new for will work on any higher-order function with the appropriate
> signature

In the end this makes Rust loops look like Ruby loops. May I restate that
«widely used programming languages are modified until they resemble Ruby»
(<https://news.ycombinator.com/item?id=3448277>) or CLispScript
(<https://news.ycombinator.com/item?id=3448826>).

What I do not understand of the late "scripting" languages (Dart, Rust) is why
they don't just modify Ruby to have a stricter type system and call it done?
That or just abandon the scripting mindset and go for more purely functional
languages with non-C-like syntaxes like Haskell or OCaml.

~~~
andolanra
Rust is emphatically not a scripting language. It is a systems language with
many features drawn from functional languages (e.g. tagged unions for data
types, pattern matching, a type class system, type inference) as well as a
strong type system with the addition of type states, which are assertions
tracked by the compiler. Yes, its syntax is C-like, but I'd assert that it has
more in common with OCaml than Dart.

With that in mind, the suggestion that it'd be more worthwhile to strap static
types onto Ruby is like looking at engineers designing an aerodynamic, fuel-
efficient, high-speed dragster and suggesting they stick a bigger engine in a
sedan and call it done. Yes, Rust has adopted a feature superficially similar
to Ruby's; that does not mean it wishes to fill the same niche or that Ruby's
goals align with Rust's in any significant way.

