On Tue, May 29, 2007 at 04:55:01PM +0900, Ronald Fischer wrote:
> > > A more
> > > general solution could be like this:
> > > 
> > >   let a+b+c in
> > >     let foo=d*e in
> > >       let x/y in
> > >         puts ($1+foo)*($1-$2)-$2/($1-foo)
> > > 
> > > Here, $1 would be bound to x/y (innermost unnamed let 
> > > binding), $2 would
> > > be bound to a+b+c (second innermost unnamed let binding). 
> 
> > You're working too hard:
> > 
> > def let(*args)
> >   yield *args
> > end
> > 
> > def use_let(a,b,c)
> >   let a+b+c do |it|
> >     return it if it < 10
> >   end
> > end
> > 
> > use_let(1,2,3) # 6
> > use_let(4,5,6) # nil
> > 
> > No need for additional keywords or even global variables, 
> > just a little method named let.
> 
> With the crucial difference that in your solution, you are *required*
> to name the bound variable (here: it), while in my proposal, you are
> not.

Implicit variables make me queasy. I don't like Perl's $_, I don't like x86
assembly's numerous ops with implicit source and/or destination registers,
and I don't like a magical "it" appearing out of nowhere.

> I think if we only want to introduce an auxiliary variable as
> "abbreviation" for an expression which occurs repeatedly in a block, Ruby
> indeed has many ways to do it, as do most other languages I know. The
> problem becomes interesting IMO if we are libarated from the requirement
> to invent a name for such a variable.
> 
> The OP suggested to have a "reserved variable" named 'it' which is kind
> of implicitly bound, but this is a special case for a special type of
> programming pattern. My alternative suggestion go into a more general
> direction, where you can have more than one binding, and where it is the
> programmer's choice whether or not to name the variables.

The OP brought up an interesting issue, but what made it interesting is not
the implicit binding but the need for a scoped temporary value. There are
three important optimization goals to it:

1) avoid holding onto memory any longer than necessary (memory)
2) avoid clumsy use of temporary values (readability)
3) avoid recomputing the same value more than once (speed)

See http://weblog.raganwald.com/2006/10/why-are-local-variables-bad.html
for a discussion of local variables and better ways of doing things
(including the functional let).

Importantly, an implicit variable name has two problems. First, it reduces
readability. Second, even if naming the variable explicitly is optional
rather than required, you get the same sorts of maintenance problems caused
by the optionally braceless block notation for single statements in C-derived
syntaxes, e.g.

let Time.now in
  puts "starting at #{$1}"
  let a+b+c in
    puts "sum = #{$1}" if $1 > 3
  end
end

...is as bad an issue as...

for (int i=0; i<5; ++i)
  printf("%d\n", i);
  fprintf(stderr, "%d\n", i);

Basically, if you need to add an outer scope, you have to renumber all of
the temporaries. This is unnecessary and unreasonable pain to inflict on
maintainers of the code, even if it's your own code.

Looking at it from a different perspective, consider whether any proposed
change to Ruby moves it closer to language X (which I'm equating to Perl)
or closer to language Y (which I'm equating to Lisp). Moving toward X means
making things easy to express tersely at the expense of overall readability
and maintainability. Moving toward Y means simplifying the expression of
things using existing syntax and functionality. I claim that we should
strive to avoid shortcuts that bring Ruby closer to X and strive to solve
our problems in ways that bring Ruby closer to Y.

> Ronald
--Greg