From: Tom Wardrop Date: 2011-08-15T10:48:58+09:00 Subject: [ruby-core:38954] [Ruby 1.9 - Feature #4102] Proposal for 'let'. A new approach using block-defaults in 1.9 Issue #4102 has been updated by Tom Wardrop. Thanks for the tips Magnus, they're very handy. I forget that begin ... end can be used just about anywhere to encapsulate multiple expressions that lead to a single result. The #tap method I simply had no idea about. Cheers ---------------------------------------- Feature #4102: Proposal for 'let'. A new approach using block-defaults in 1.9 http://redmine.ruby-lang.org/issues/4102 Author: john mair Status: Open Priority: Normal Assignee: Category: Target version: =begin This is a very simple function, it would be implemented as follows: module Kernel private def let() yield end end First of all, do not dismiss this functionality out of hand because of its simplicity. Even though it is just a 'yield', when it is combined with Ruby 1.9's block defaults and new block-variable scoping rules it is actually quite powerful and it behaves exactly like a let* in lisp. Some advantages of this functionality are: (1) Gives you precise control over the scope of your variables. I note that after the publication of "Metaprogramming in Ruby" by Paolo Perrotta the following idiom has started to appear: proc do ..my code.. end.call It is used exactly as the proposed 'let' would be used, but is syntactically much uglier. Yes, i know an alternative is to just make shorter and smaller methods. But is the ability to control and restrict scope ever a bad thing? (2) Testing and teaching about blocks. As the proposed 'let' simply yields to a block it can be used to illustrate block behaviour and block concepts to a new Ruby programmer. It also may be useful to an experienced programmer when trying out new ideas. Here are some example uses of the proposed 'let': Example 1: Carve out a temporary scope, make 'x' local to that scope x = :outer let { |x| x = :inner } #=> :inner x #=> :outer Example 2: Here we use Ruby 1.9's block-defaults to make 'y' block-local and give it a value: let { |y=10| y } #=> 10 Example 3: Make 'x' and 'y' block-local and have 'y' value depend on 'x' (equivalent to let* in lisp) let { |x=10, y=(2*x)| [x, y] } #=> [10, 20] In summary, I think this proposal should succeed for the following reasons: (1) It is an exceptionally simple implementation. (2) More control over scope is never a bad thing. (3) I have seen people re-implementing this functionality themselves using: proc { ..code.. }.call (4) It is very useful for teaching and testing block behaviour. Thanks, John =end -- http://redmine.ruby-lang.org