In Perl I used to do this:
print 'Enter data: ';
chomp(my $in = <STDIN>);
sub doit {
my $data = shift;
.........
return $data;
}
doit($in);
In Ruby the equivalent seems to be:
puts 'Enter data: '
in = gets.chomp
def doit(data)
........
return data
end
doit(in)
However, Ruby passes arguments by reference so it seems the variable
'data' is always accessing and changing the file-global variable 'in'.
Is there a more Perl-like, way of lexicalising the scope of variables
passed as arguments to functions?
gvim

gvim <gvimrc@gmail.com> wrote:
> However, Ruby passes arguments by reference so it seems the variable> 'data' is always accessing and changing the file-global variable> 'in'. Is there a more Perl-like, way of lexicalising the scope of> variables passed as arguments to functions?
Make a copy of the argument when you call the method:
doit(in.dup)

On 13/11/2013 01:57, Eric Wong wrote:
>> Make a copy of the argument when you call the method:>> doit(in.dup)
I seem to have misunderstood something. Changing 'data' within the
'doit' method does not seem to alter the 'in' variable even though it is
passed as an argument to the method. So it seems args are passed by
value after all ..... unless I'm mistaken .... again.
gvim

On Tue, Nov 12, 2013 at 9:10 PM, gvim <gvimrc@gmail.com> wrote:
So it seems args are passed by value after all ..... unless I'm mistaken
> .... again.
Args are always passed by reference. When you pass in to doit, data
and inpoint to the same string object.
Without seeing what else goes on inside doit, its hard to offer insight
on
the behavior youre seeing.

Gerald Vim wrote in post #1127104:
> On 13/11/2013 01:57, Eric Wong wrote:>>>> Make a copy of the argument when you call the method:>>>> doit(in.dup)>> I seem to have misunderstood something. Changing 'data' within the> 'doit' method does not seem to alter the 'in' variable even though it is> passed as an argument to the method. So it seems args are passed by> value after all ..... unless I'm mistaken .... again.>> gvim
No, you were right to start with, ruby passes by reference. However,
Ruby often implements copy-and-modify (as opposed to destructive
modify-in-place) methods; as a general rule: if the method ends with an
exclamation mark ! it modifies the object in place, and if not, it
doesn't (except for some that do).
--- 8< ---
irb(main):001:0> foo = gets.chomp
Hello Matty!
=> "Hello Matty!"
irb(main):002:0> def doit(data) data.gsub!(/(.)\1+/){ $1 }; end
=> nil
irb(main):003:0> doit foo
=> "Helo Maty!"
irb(main):004:0> foo
=> "Helo Maty!"
--- >8 ---
Note how in the `doit' method I called gsub! (which modifies the
receiver in place), and not gsub (which creates a copy first).
There's also a difference between 'modifying the object' and 'updating
the variable to refer to a different object'. If I did:
def doit(data)
data = "The data is #{data}"
#...
end
that would be creating a new String object, then assigning that to the
variable called `data'. It would not be the same as modifying the
characters inside the original `data' String object.

On Nov 12, 2013, at 7:09 PM, gvim <gvimrc@gmail.com> wrote:
>> return data> end>> doit(in)>>> However, Ruby passes arguments by reference so it seems the variable 'data' is
always accessing and changing the file-global variable 'in'. Is there a more
Perl-like, way of lexicalising the scope of variables passed as arguments to
functions?
>> gvim
The thing Ive come to in my own understanding is that since everything
is an object in Ruby, that means every variable is actually a pointer to
an object in Ruby as well.
So when you pass in to the doit method, you are passing the reference
into the local method variable data. Initially, data and in are pointing
to the same object. But then you have to be aware of what things you are
doing on the data variable. If its things with modify the same object
originally point to by in, then the object in points to is being
changed. Thus it looks like in is changed.
Doing other things can create new objects in ruby, though, so doing
something to data that ends up creating a new object also ends up
making in look unchanged when doit exits, which is so.
So lets try this.
def doit2(data)
data.shuffle
end
According to the docs, shuffle creates a new array. So:
$ pry
[1] pry(main)> start_data = [1,2,3,4,5].freeze
=> [1, 2, 3, 4, 5]
[2] pry(main)> a_ary = start_data
=> [1, 2, 3, 4, 5]
[3] pry(main)> def doit(data)
[3] pry(main)* data.shuffle
[3] pry(main)* end
=> nil
[4] pry(main)> doit(a_ary)
=> [2, 4, 5, 3, 1]
[5] pry(main)> a_ary
=> [1, 2, 3, 4, 5]
[6] pry(main)> a_ary.object_id
=> 70307654300780
[7] pry(main)> doit(a_ary).object_id
=> 70307649978420
[8] pry(main)> doit(a_ary).object_id
=> 70307650161900
So you can see that .shuffle is creating a new object each time.
But remember we froze the source data up there? a_ary is also pointing
to the frozen array, so when you change doit to something like this:
[9] pry(main)> def doit(data)
[9] pry(main)* data.shift
[9] pry(main)* end
=> nil
[10] pry(main)> a_ary
=> [1, 2, 3, 4, 5]
[11] pry(main)> a_ary.object_id
=> 70307654300780
[12] pry(main)> b_ary = doit(a_ary)
RuntimeError: can't modify frozen Array
from (pry):12:in `shift
It fails because we tried to change a frozen object.
Now if we do this:
[13] pry(main)> b_ary = doit(a_ary.dup)
=> 1
[14] pry(main)> a_ary
=> [1, 2, 3, 4, 5]
[15] pry(main)>
doit is working on a new object that isnt frozen.

I think you are passing a _copy_ of the reference to the object. This is
why
you can manipulate the object itself, but you can also point that
reference
to another object, without affecting the original.

On 13/11/2013 11:48, Xavier Noria wrote:
> Ruby passes arguments *by value*. You can modify a mutable object via> its API, but that has nothing to do with call semantics.>
Thank you! That's the only explanation that makes sense so far but
others seem to disagree.
gvim

On Wed, Nov 13, 2013 at 2:09 AM, gvim <gvimrc@gmail.com> wrote:
In Perl I used to do this:
> doit($in);> end>> doit(in)>>> However, Ruby passes arguments by reference so it seems the variable> 'data' is always accessing and changing the file-global variable 'in'. Is> there a more Perl-like, way of lexicalising the scope of variables passed> as arguments to functions?
Perl only has pass by reference (the elements of @_ are aliases of the
ones
in the caller), and Ruby has only pass by value.
But, Perl has a number of basic types like arrays that you handle
directly:
@a = (1);
is an array, and
$x = \@a;
is a reference to an array.
In Ruby you basically only have the latter. And since that's the only
thing
you have no arrow is needed to dereference, you are always dealing with
reference values so there is no extra syntax. That is, in Ruby
array[0]
translates to Perl as:
$arrayref->[0]
Therefore, if you are going to mutate the string in the doit method and
do
not want the caller to see the mutation you need to clone the argument:
def doit(data)
data = data.dup
...
end
I personally prefer to clone in the method rather than in the caller. My
caller code should not be just paranoid and defensive, on the other hand
doit *knows* he is going to mutate, and *knows* it is not a good
practice
to mutate arguments, so he is responsible for cloning in my view.
Xavier

On 13/11/2013 11:32, Carlo E. Prelz wrote:
> x = x + 1> Carlo>
So a parameter is passed by reference but as soon as you modify it
you've cloned the object? Then what's the point passing it by reference
in the first place?
gvim

Subject: Re: Passing script input as method args always global?
Date: mer 13 nov 13 12:01:24 +0000
Quoting gvim (gvimrc@gmail.com):
> So a parameter is passed by reference but as soon as you modify it> you've cloned the object? Then what's the point passing it by> reference in the first place?
It is not always true that the object is cloned. It depends on the
method. See this example:
class Tally
attr_reader(:v)
def initialize(v)
@v=v
end
def +(v)
@v+=v
self
end
def to_s
@v.to_s
end
end
var=Tally::new(2)
def f(x)
x=x+1
return x
end
puts f(var) #=> 3
puts var #=> 3
Carlo

On Wed, Nov 13, 2013 at 1:01 PM, gvim <gvimrc@gmail.com> wrote:
So a parameter is passed by reference but as soon as you modify it
you've
> cloned the object? Then what's the point passing it by reference in the> first place?
There is some terminology going on here. I am going to explain it below
for
completeness, but the main issue in this thread is that you understand
that
Ruby passes a reference to the string, as if you hace a reference to a
scalar in Perl.
So, you need to think in terms of references always in Ruby. In Perl, if
you pass a reference to an array a subroutine can change the array in
the
caller via the reference, right? That's always the case in Ruby because
there are always references going on (conceptually, there are some
exceptions in the implementation of MRI but that's not relevant).
Now for the jargon. Passing "a reference" to a method, is not the same
as
"passing by reference" calling semantics.
In Perl, you can do this (written off the top of my head):
sub foo {
$_[0] = 1;
}
$a = 0;
foo($a)
print "$a\n"; # => 1
because $a is passed by reference. $_[0] and $a are containers that
point
to the same scalar (think symbol tables).
In pass by reference semantics you can write swap this way (pseudocode):
a = 1
b = 2
def swap(a, b)
b, a = a, b
end
a == 2 # => true
b == 1 # => true
That's the idea. Perl implements pass by reference, and Ruby pass by
value.
Ruby passes references to objects by value.

On 13/11/2013 12:10, Carlo E. Prelz wrote:
> self> x=x+1> return x> end>> puts f(var) #=> 3> puts var #=> 3>> Carlo>
I don't see the connection with my simple function example. You have
used 'v' in 3 different contexts here - :v, @v and (plain old)v. This is
what I find so confusing about Ruby, along with this parameter passing.
Can you use an example without classes?
gvim

Subject: Re: Passing script input as method args always global?
Date: mer 13 nov 13 12:14:36 +0000
Quoting gvim (gvimrc@gmail.com):
> You have> used 'v' in 3 different contexts here - :v, @v and (plain old)v.> This is what I find so confusing about Ruby, along with this> parameter passing.
No! :v, v and @v are THREE DIFFERENT THINGS altogether.
:v is a symbol that, where it is used, references the name of an
instance variable
@v is the instance variable (local to the class instance, and thus
maintaining its value for the life of the instance)
v is a local variable whose scope is limited to each of the two
methods where it is used.
Carlo

On 13/11/2013 12:20, Carlo E. Prelz wrote:
>> Carlo>
I know they're different. It's just that my example was simplified to
try to work out what's going on but your use of a class with 3 different
variable types doesn't clarify anything.
gvim

Gerald Vim wrote in post #1127142:
> On 13/11/2013 11:32, Carlo E. Prelz wrote:>> x = x + 1>> So a parameter is passed by reference but as soon as you modify it> you've cloned the object?
No, not at all.
``x = x + 1'' breaks down like this:
1. construct an object which is an Integer whose value is 1
2. find the object referred to by the variable named "x"; in this case,
an Integer
3. invoke the method called "+" on that object, passing the newly-minted
Integer as the first/only parameter*
4. update the variable named "x" to refer to the result of that method
invocation (i.e. this is the "=" part)
*Note: the "+" method on an Integer is non-destructive, internally it
creates a new Integer object whose value is the sum of the receiver and
the parameter, and returns that. Integer objects are immutable in ruby.
There are all sorts of other specifics going on (singleton Fixnums for
starters) but this simplification isn't inaccurate. Assignment is an
operation on the *variable* (a reference), and method invocations
(including "+") are operations on the *object* referred to by the
variable.
---
Here is a counter-example, assuming y = "abc", because I like writing
more than necessary:
y = ( y << "d" )
1. construct an object which is a String whose value is "d"
2. find the object referred to by the variable named "y"; in this case,
our a String
3. invoke the method called "<<" on that object, passing the
newly-minted String as the first/only parameter
4. update the variable named "y" to refer to the result of that method
invocation
In this case the "<<" method on a String *is* destructive; it changes
the value of the Object, by appending the parameter to it. Fortunately
for
us, it also returns the (now updated) receiver. We could have left the
code as:
y << "d"
... which would have saved us a variable assignment, but both snippets
result in an identical state.

On Wed, Nov 13, 2013 at 1:23 PM, gvim <gvimrc@gmail.com> wrote:
On 13/11/2013 12:13, Xavier Noria wrote:
>> value. Ruby passes references to objects by value.> return y> end>> puts f(x) #=> 3> puts x #=> 2>> In your example a and b are mutated but in mine x remains unchanged.
That example illustrates what you could do if you **had** pass by
reference
semantics. And Ruby does not have those semantics, it has pass by value
semantics, therefore it works as you are seeing.

Subject: Re: Passing script input as method args always global?
Date: mer 13 nov 13 12:23:22 +0000
Quoting gvim (gvimrc@gmail.com):
> In your example a and b are mutated but in mine x remains unchanged.
Because in your method:
> def f(y)> y = y + 1> return y> end
you receive an object, but you return another one. The fact that it is
still called 'y' (within your local method) does not insure that it is
the same thing.
Thus, the original object is indeed unchanged.
This is because the implementators of the sum of the Numeric class
decided that it was appropriate to return a new object when performing
a sum.
If you go back to my previous example, and substitute the plus method
so that instead of
def +(new_v)
@v+=new_v
self
end
it reads
def +(new_v)
Tally::new(@v+new_v)
end
(note that I changed the name of the local variable so that things may
be easier to understand), then you will still have
puts f(var) #=> 3
puts var #=> 2
Carlo

On 13/11/2013 12:33, Matthew Kerwin wrote:
> 4. update the variable named "x" to refer to the result of that method> variable.> our a String>> y << "d">> ... which would have saved us a variable assignment, but both snippets> result in an identical state.>
I'm beginning to see Ruby's "everything is an object" as a serious
barrier to comprehension, epsecially when this object-orientation is
dressed up in procedural syntax. Perl seems a lot more natural by
comparison.
gvim

Gerald Vim wrote in post #1127156:
> On 13/11/2013 12:33, Matthew Kerwin wrote:>> 4. update the variable named "x" to refer to the result of that method>> variable.>> our a String>>>> y << "d">>>> ... which would have saved us a variable assignment, but both snippets>> result in an identical state.>>>> I'm beginning to see Ruby's "everything is an object" as a serious> barrier to comprehension, epsecially when this object-orientation is> dressed up in procedural syntax. Perl seems a lot more natural by> comparison.>> gvim
If you like, you can rewrite all of the above as:
x = x.+(1);
y = y.<<("d");
Everything else is syntactic sugar.
Also, for the record, there's this: x += 1
Which expands out to: x = x.+(1)

On Wed, Nov 13, 2013 at 1:39 PM, gvim <gvimrc@gmail.com> wrote:
I'm beginning to see Ruby's "everything is an object" as a serious
barrier
> to comprehension, epsecially when this object-orientation is dressed up in> procedural syntax. Perl seems a lot more natural by comparison.
Ruby has a simpler model than Perl in this regard. It is easier in that
sense, but coming from Perl you need to adjust.
In Perl you have values (scalars, arrays, hashes, ...), and references
to
values (which are in turn scalars). In Ruby you only have references.
That's the whole story.
In Ruby
s = "foo"
t = s
s << 'bar'
puts t
prints "foobar". Everything are references, s holds a reference to a
string, t hods the same reference, therefore in-place mutations are seen
in
both of them.

On 13/11/2013 12:47, Xavier Noria wrote:
> string, t hods the same reference, therefore in-place mutations are seen> in both of them.>
I get that but it sets up an expectation that this:
x =2
def f(y)
y = y + 1
puts y
end
f(x)
... will mutate x but I now understand, from what others have explained,
that it doesn't. It's just counter-intuitive, that's all. This and the
various rules about symbols as named arguments have led me to the
conclusion that Ruby is an unnecessarily complicated language. Perl is
much simpler.
gvim

Subject: Re: Passing script input as method args always global?
Date: mer 13 nov 13 12:52:47 +0000
Quoting gvim (gvimrc@gmail.com):
> Ruby's beauty is looking increasingly skin-deep to me as I learn> more.
What is happening is that you resist change. What you lose seems to
you of greater value than what you gain.
Which might just as well be in your case. It is up to you to
decide whether to dedicate precious brain-space with Ruby.
Ruby's #1 beauty is for me that it allows you to become an intimate
friend of the OO paradigm without compromises, and with an almost
perfect clarity.
Carlo

On 13/11/2013 12:53, Carlo E. Prelz wrote:
> val=3> puts val # 3> val=val+1> puts val # what??>> Carlo>
I'm sure there are many more contortions like this that Ruby facilitates
but my months spent learning the language have led me to the conclusion
that one can easily get lost in what's going on in the language under
the surface. It's surface simplicity and elegance falls apart quite
quickly in my experience.
gvim

On Wed, Nov 13, 2013 at 1:57 PM, gvim <gvimrc@gmail.com> wrote:
... will mutate x but I now understand, from what others have
explained,
> that it doesn't. It's just counter-intuitive, that's all. This and the> various rules about symbols as named arguments have led me to the> conclusion that Ruby is an unnecessarily complicated language. Perl is much> simpler.
The conclusion you need to reach is that you do not understand pass by
value. You need to understand pass by value, is what the vast majority
of
programming languages implement. Perl is the outlier here (not implying
it
is worse, I love Perl, just to put things in perspective).

On 13/11/2013 13:00, Carlo E. Prelz wrote:
>> Ruby's #1 beauty is for me that it allows you to become an intimate> friend of the OO paradigm without compromises, and with an almost> perfect clarity.>> Carlo>
I understand where you're coming from but for me arithmetic operators
implemented as objects is just plain back-to-front and goes half way to
explaining why my x = x + 1 didn't behave as expected. Even worse when
those operators can be overridden.
gvim

On 13/11/2013 13:02, Xavier Noria wrote:
>>> The conclusion you need to reach is that you do not understand pass by> value. You need to understand pass by value, is what the vast majority> of programming languages implement. Perl is the outlier here (not> implying it is worse, I love Perl, just to put things in perspective).>>
PHP, I believe, adopted pass-by-reference a few major version back.
Avdi, and others, earlier stated "Args are always passed by reference"
so which is it?
gvim

When we talk about "pass by reference", "reference" means a reference to
the container, to the variable. You have to visualize two symbol tables
that have aliased *key*s. The value they hold is not relevant to this
terminology. Going through one or the other, you reach the same memory
slot.

Subject: Re: Passing script input as method args always global?
Date: mer 13 nov 13 01:05:47 +0000
Quoting gvim (gvimrc@gmail.com):
> I understand where you're coming from but for me arithmetic> operators implemented as objects is just plain back-to-front and> goes half way to explaining why my x = x + 1 didn't behave as> expected. Even worse when those operators can be overridden.
I am not sure you know where I come from ;-)
Anyway, if you want to gain the advantage that OO gives, you must
learn to consider everything that happens to your things as methods
applied to objects. Once you do that, things will start to make more
sense, I hope.
In Ruby, arithmetic operators are implemented as methods because there
is no other way.
PS in a previous mail I wrote
> A haiku may be this one:
I apologize to the many Japanese readers of this list: I meant
> A koan may be this one:
Carlo

Gerald Vim wrote in post #1127166:
> I'm sure there are many more contortions like this that Ruby facilitates> but my months spent learning the language have led me to the conclusion> that one can easily get lost in what's going on in the language under> the surface. It's surface simplicity and elegance falls apart quite> quickly in my experience.
Well, Perl does the same unless explicitly told.
sub f {
my $y = shift;
$y = $y + 1;
return $y;
}
my $x = 2;
print f($x), "\n"; # => 3
print $x, "\n"; # => 2
Java, in contrast, does not know about pass by value and always does
pass by reference.
The most expressive would be C++ here:
float f(float x);
float f_with_sideeffect(float &x);
(And C++ allows to overload operators, too! Have fun with that...)
In general, you'd like to avoid side effects whenever possible.

On 13/11/2013 13:21, Eric MSP Veith wrote:
> my $x = 2;> print f($x), "\n"; # => 3> print $x, "\n"; # => 2>
The difference is that Perl explicitly shifts the parameter into a new
lexical variable. This is not what's happening in my Ruby example and
that's why I find it confusing. Why have a named parameter which is
passed by reference if as soon as you mutate it the reference is lost,
a-la Ruby? This is not what Perl does at all.
gvim

On Wed, Nov 13, 2013 at 2:21 PM, Eric MSP Veith
<lists@ruby-forum.com>wrote:
Gerald Vim wrote in post #1127166:
> my $y = shift;> $y = $y + 1;> return $y;> }>> my $x = 2;> print f($x), "\n"; # => 3> print $x, "\n"; # => 2>> Java, in contrast, does not know about pass by value and always does> pass by reference.
Not true. Java is pass by value, the JLS is clear about this:
When the method or constructor is invoked (§15.12),
the values of the actual argument expressions initialize
newly created parameter variables, each of the declared
Type, before execution of the body of the method or
constructor.
There are many informal resources out there about this debate, see for
example
http://www.javaranch.com/campfire/StoryPassBy.jsp
or
http://architects.dzone.com/articles/java-pass-val...
In Ruby, as in Java, the fact that you are dealing with references
belongs
to the conceptual model of the language. It is not the case that you are
supposed to be dealing with objects directly and references are
implementation. The language tells you that you are dealing with
references. (The fact that MRI uses pointers *is* implementation.)
So in Ruby, as in Java, the arguments hold references, and call
semantics
are pass by value. You pass references to objects by value.

On Wed, Nov 13, 2013 at 2:43 PM, gvim <gvimrc@gmail.com> wrote:
Perl retains the passed reference unless modified. Not so in Ruby where
y
> becomes a new copy as soon as it is mutated.
Not really. When you call a method in Ruby, the parameter variables are
initialized with a copy of the values hold by the arguments. Right away,
it
doesn't depend on anything being mutated.
The semantics are easy:
1) Variables hold references to objects.
2) When a method is invoked, the arguments are used to initialize the
parameter variables.
That's all the mental model you need to build in Ruby.

Gerald Vim wrote in post #1127177:
> This is not what Perl does at all.
This conversation has gone on quite a bit. It started out like "I don't
know why this happens this way" and there were some attempts at
explaining it, but now it's a lot more like "I want it to work like
Perl" and a bunch of ruby-evangelistic responses.
If you want it to do what Perl does, use Perl. Perl does Perl better
than Ruby.
> Perl retains the passed reference unless> modified. Not so in Ruby where y becomes> a new copy as soon as it is mutated.
You need to be really careful when using words like "reference" and
"copy" and "mutated" that you are using them in the context of the
language.
### START OF SCRIPT:
our $SCOPE_0_VARIABLES = {};
# x = 1;
my $x_object = new Fixnum(1);
$SCOPE_0_VARIABLES->{x} = \$x_object;
# def foo x
# x = x + 1
# end
our $SCOPE_foo_VARIABLES = {x=>undef}; # variables in scope
our $SCOPE_foo_FINAL_VALUE = undef; # return value
#y = foo x
$SCOPE_foo_VARIABLES->{x} = $SCOPE_0_VARIABLES->{x};
# copy outer-x to inner-x
### IN SUBROUTINE:
# x = x + 1
my $intermediate_value = $($SCOPE_foo_VARIABLES->{x}) + 1; # x + 1
$SCOPE_foo_VARIABLES->{x} = \$intermediate_value; # x = ...
$SCOPE_foo_FINAL_VALUE = $SCOPE_foo_VARIABLES->{x}; # return value
### IN OUTER SCOPE:
$SCOPE_0_VARIABLES->{y} = $SCOPE_foo_FINAL_VALUE; # y = ...
There is no x.
Apologies if my perl is bad, I can never remember when to use % or -> or
\.

On Wed, Nov 13, 2013 at 7:13 AM, Xavier Noria <fxn@hashref.com> wrote:
> Ruby passes references to objects by value.
Thanks for spelling this out. I'd gotten pass-by-reference and
pass-reference-by-value mixed up in my head, probably because it's been
ages since I had to deal with pass-by-reference.

Xavier Noria wrote in post #1127181:
> Not true. Java is pass by value, the JLS is clear about this:>> When the method or constructor is invoked (§15.12),> the values of the actual argument expressions initialize> newly created parameter variables, each of the declared> Type, before execution of the body of the method or> constructor.>
Whoops, I got that mixed up then, sorry. The effect is that of a
void f(SomeType *Klazz);
in C/C++.