Method arguments

Lähettäjä: Nash Kabbara <nash@oplink.net>
Aihe: Re: Method arguments

Hmmm. Is it safe to pass a Hash and modify it in a function then use it?

for example:

a = Hash.new
modify(a)
do_something_useful(a)

after reading the response below, it's making me think how hashs behave
and whether it's safe to do the above.

It depends on what you expect :slight_smile:

def foo(hsh)
  hsh[:a] = 'b'
end

h = {:a => 'a'}
foo(h)

h[:a] # => 'b'

Thanks

Mikael Brockman wrote:
> "Tookelso" <tookskie-googlegroups@yahoo.com> writes:
>
>
>>Hello,
>>
>>Sorry for asking this basic question, but I couldn't find it in the
>>PickAxe book.
>>
>>When you pass an argument to a method, is it passed by reference, or by
>>value?
>
>
> By value. But remember that the value of a variable is always a
> reference! (That's not *technically* true for Fixnums, but since
> Fixnums are entirely immutable, the abstraction holds up.)
>
>
>>Or, does it depend on the object's type?
>>
>>For example, in the simple script below, the program outputs "0".
>>#-----------------------------------
>>def test(c_count)
>>c_count = c_count + 1
>>end
>># begin program
>>c_count = 0
>>test(c_count)
>>puts c_count
>>#-----------------------------------
>>I realize that for simple things, it's better to return a value from
>>the method, but I would like to know *why* it's not modifying my
>>"c_count" value.
>
>
> (In this explanation, I'm ignoring the fact that Fixnums are special --
> that fact is a pure implementation detail. Just an optimization.)
>
> When you initialize c_count, the 0 is evaluated first. Ruby will
> allocate space for a Fixnum. Let's say it allocates some bytes over at
> the memory location 0xCAFEBABE. It copies 0x0000, or whatever the
> machine representation of 0 is, to 0xCAFEBABE.
>
> Then it creates a new instance variable. Sets its value to 0xCAFEBABE.
>
> When you call ``test'', c_count is passed by value, as always. The
> value passed is 0xCAFEBABE.
>
> Now, what happens when you receive an argument is this: a new instance
> variable is created. This c_count has nothing in common with the other
> c_count -- except that they happen to share values. Of course, you
> could name the test parameter ``snuggly_taco'', and the program would
> work the same.
>
> When you assign to snuggly_taco, the only thing that happens is that the
> value of snuggly_taco is changed, to the address of that new number
> you're making. This affects neither 0xCAFEBABE nor c_count.
>
> If you really want to change the value of an instance variable from
> another function -- bad luck. You can't.
>
> Actually, I lied. You can do it. If you use Florian Groß's
> binding_of_caller and eval.
>
> But that's an extremely obscure hack. Avoid it! The clean solution is,
> as always, adding another layer of indirection. Make it so that by
> setting something you actually can change -- like an instance variable
> -- you change the effective value.
>
> > class Box
> > attr_accessor :value
> >
> > def initialize value=nil
> > @value = value
> > end
> > end
> >
> > def test c_count
> > c_count.value = c_count.value + 1
> > end
> >
> > c_count = Box.new 0
> > test c_count
> > puts c_count
>
> This box is perfectly analogous with a C pointer (except, of course,
> that you can't do pointer arithmetic). Instead of ``*foo'', we write
> ``foo.value''.
>
> (By the way, is there a class like this in the stdlib?)
>
> mikael
>
>
>
>

E