From: Brian Candler Date: 2008-11-29T04:59:08+09:00 Subject: [ruby-core:20157] Re: [Bug #797] bug or feature: local method ? On Sat, Nov 29, 2008 at 04:22:15AM +0900, Francoys wrote: > But your Lambda's version is very tempting, but my experience with the > use of Proc come at the price of performance penalty. Beware (a) premature optimisation, and (b) using your intuition to decide where hotspots are. Even the most experienced programmers usually get it wrong if they try to guess where to optimise. Profile first, optimise later. In any case, Ruby is about writing programs which are elegant and easy to maintain; performance is secondary. Don't fight the language. If you are trying to write spaghetti Ruby just to gain a 5% performance benefit, then you would be better off writing in a completely different language. > ------------------------------------------------------------------------------------------------------------------------ > > def foo4 > > @bar = 10 > > def gazonk > print @bar > end > > gazonk > end > > foo4 > -------------------------------------------------------------------------------------------------------------------------- This doesn't work the way you expect. What happens here is that every time you call foo4, you are actually *redefining* the method 'gazonk' in the top level object. So now you have the worst of all possible worlds; unnecessarily bad performance, and still no sharing of local variables. That is: in Ruby, "def xxx ... end" defines a method when the def statement is actually *executed*. Normally you write these statements inside a class statement, so they are only executed once (when the file is run). But if you stick a def statement inside a loop, or inside a method body, then it *will* redefine the method repeatedly. However you can avoid the performance penalty by rewriting your code above simply as: def gazonk print @bar end def foo4 @bar = 10 gazonk end This is perfectly fine and reasonable Ruby. > By the way, i didn't test the third model and this is the correct > version, the @ are making a big difference: This will work fine *without* using instance variables. But since you're not posting real code here, only dummy stuff, I can't be sure where you're going wrong. Perhaps in op1() you are reassigning @a_list to point to a different object. (But in that case, there is no point passing in @a_list and friends as arguments). > Unless Ruby have a radical new approach, every time that you are using a > function, the interpreter must clone the values that are passed in > parameter *. Wrong. Ruby's approach *is* different to other languages - perhaps you can call it radical if you've not seen it before. In Ruby, every value is an object reference. Absolutely *every* value. So: def foo puts foo.object_id end a = 1 foo(a) # pass a single object reference a = [1,2,3] foo(a) # pass a single object reference In both calls to foo, a single object reference is passed. There is no 'cloning' of anything. The references are passed by value (copied, if you like), but the objects themselves are not cloned. I'm afraid I was as guilty as anyone when I first came to Ruby: jumping in with "why doesn't Ruby do this" or "I expected it to do that" or "wouldn't it be better if it did the other". My advice is: go with the flow. Relax, expand your mind, open yourself to new concepts which may not be the same as what you're familiar with. Learn how these may enhance your programming; by all means compare and contrast with what you know, but don't reject what's new out of hand. Sure, other languages may have advantages over Ruby, but you may also find that you can do things in Ruby much more easily than you could do before. I'd also suggest this discussion would be better suited to ruby-talk rather than ruby-core. Regards, Brian.