Hi --
David A. Black wrote:
...stuff deleted...
Since integers are immutable (luckily!), and local variables are
local, you can't change an integer object via a reference copied to a
method. If it helps, I can assure you that you would *not* want this
to happen. It would be very weird if my local variables bindings were
at the mercy of methods that I called.
What you're really looking for is an object container, and local
variables don't really work that way. For container semantics you
really need to use containers. You could do something like:
First, thanks for the quick answer. That was unexpected.
Unfortunately I can't say I understand the part of your response I
quoted above, other than that it says, "Nope, you can't do what you're
trying to do. Unless you're working with strings, which are somehow
different."
The "local variables _bindings_" bit implies to me this has something to
do with Ruby's underlying storage that I have not yet grasped. I'm
still thinking of a 'local variable' as really some chunk of memory, and
the way the bits are set in that memory mean something in the context of
my program. If I pass that location to a subprogram, and know that it's
going to put something else in it, that's good.
I can think of examples where I would like my subprogram to modify the
local variables of the calling code. For instance, I have two points,
and I want to calculate m and b for the formula of a line, as in y = m *
x + b. I would be inclined to write a subprogram calc_m_b(x1, y1, x2,
y2, var m, var b) (in Pascalese). I could do what amounts to the same
thing with two functions, one returning m and the other b, but that
seems sort of silly in this case. I could design an object that
represented a line in some fashion, and let it hold m and b, but that's
not always what you'd want, either.
Maybe I'm not thinking in terms of objects enough yet?
I agree my answer was sort of "You can't do the thing you just said
you can't do" But that is sort of how it is. It's axiomatic in
Ruby that local variables are local. By "bindings" I mean:
def x(a)
a = 3 # a is bound to 3
end
a = 1 # *this* (different) a is bound to 1
x(a)
puts a # still 1
The call to x does not change the existing binding of a.
The only kind of change you can do in a situation like this is when a
variable is bound to a mutable object -- or, more accurately, a
variable contains a reference to a mutable object (since basically
Ruby variables traffic in references). That's where you get into
things like:
def add_to_array(a)
a.push("New element")
end
array = [1,2,3]
add_to_array(array)
p array # [1,2,3,"New element"]
If I use 'a' instead of 'array' for my array, the fact that
add_to_array also uses 'a' is just coincidence. There's no connection
between the two. It just happens that the identifier 'a' is used in
two local scopes to handle references to the same object.
The usual patterns you see in Ruby are either container-based,
object-based (where you have an object with an attribute; you pass the
object into the method and it does something to the attribute), or
assignment-based but in the same scope:
def change_me(a)
a + 2
end
a = 1
a = change_me(a) # a is now 3
I've pushed the assignment out of the method -- where it doesn't have
any effect except to set or change the method's local variables --
into the calling context. That way, I can do whatever I want with my
identifiers in each scope.
David
···
On Sat, 25 Aug 2007, John Dearden wrote:
--
* Books:
RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242\)
RUBY FOR RAILS (http://www.manning.com/black\)
* Ruby/Rails training
& consulting: Ruby Power and Light, LLC (http://www.rubypal.com)