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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.