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