Re: Expression-local variables and 'let'
Daniel Bonniot <[email protected]>
| Newsgroups | gmane.comp.lang.nice.general |
|---|---|
| Message-ID | <[email protected]> |
>>you can write:
>>
>> bar(int x = foo(), x > 0);
>>
>>using(PrintStream s = ...) {
>> s.println("...");
>>}
>>
>>
>
>My initial reaction was that the scope of x should not go past the comma, and
>the scope of s should not go outside of the parentheses.
>
Then the binding would be useless, it would have an empty scope!
>But, I guess this is
>what happens in formal parameter declarations anyway.
>
I don't get that.
>But, also, don't you think
>that "int x = foo(), x > 0" looks a lot like it is saying "let x be the result
>of foo(), asserting/assuming that x > 0".
>
>
I never saw it like that, although I can now imagine you did. Note that
'bar(x = foo(), x > 0)' is already a valid C/Java/Nice expression, and
it is a call to bar with two arguments, the first one being the value of
foo(), that is also stored in the variable x. So the new syntax merely
add the option to declare a new variable at that point.
>Since "var" and "let" are "new" to Nice (compared to Java), why not just use the
>ML/OCL/Haskell "let...in" syntax for them? That is, make all 'let' and 'var'
>expressions "expression-local". Before we would write:
> int x = foo();
> bar(x, x > 0);
> rab(x, x < 0);
>
> let z = something();
> bar(z, z >= 0);
>
>Using ML syntax it would be:
> var x = foo() in {
> bar(x, x > 0);
> rab(x, x < 0);
> }
>
> let z = something() in
> bar(z, z >= 0);
>
> let s = new PrintStream in
> using (s) {
> s.println(...);
> }
>
>At least this syntax is familiar to functional programmers, instead of a brand
>new one.
>
>
But this syntax does not lead to more conciseness (exactly like what you
can currently do). So I don't see what it brings.
In the old days of C, you would write loops like this:
int x;
for(x = 0; x < len; x++) {
...
}
Then somebody realised that it would be possible to better express that
x is a "loop variable", no something that makes sense after the loop is
over, by allowing:
for (int x = 0; ...; ...) {
...
}
This form is also more arguably more readable, and one line shorter.
Expression-local variables basically take this special handling, and
generalize it to a general-purpose construct. This means that the new
construct is not alien, it's a generalization. This also means you can
implement "new syntax" like the 'using' statement purely in the language
instead of hard-wiring it in the language definition and in the parser.
This means the language is both simpler (less special cases) and more
expressive.
>Anyway, if you don't like "let" in your original expression-local let syntax,
>why not replace it with "final"? "val" has no meaning to anybody that has never
>used ML and it doesn't do much to indicate that the variable cannot be
>reassigned a value. Then you'd have:
> using (final s = new PrintStream(...)) { ... }
>
>
That's an interesting idea. The problem is that we used to have 'final'
but replaced it by 'let' because some people dislike 'final' being used
with different meanings (final class/final variable).
I don't think 'val' will only speak to ML users. Well, maybe it will
from experience, but it should not be hard to get used to it. Isn't the
idea of 'value' quite simple and appropriate? A 'let' binding is just a
name for the value it binds to.
By the way, var/val are also the keywords chosen in Scala.
Daniel
-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now.
Build and deploy apps & Web services for Linux with
a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click