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.