Passing script input as method args always global?

Quoting gvim (gvimrc@gmail.com):

Then I don't get this one:

var = 2

def f(x)
  x = x + 1
  return x
end

puts f(var) #=> 3
puts var #=> 2

The line

x = x + 1

creates a new object. You can see this by printing the object id of x
before and after the sum:

...
def f(x)
  puts("before: #{x.object_id}")
  x = x + 1
  puts("after: #{x.object_id}")
  return x
end
...

gives here:

before: 5
after: 7

Carlo

···

Subject: Re: Passing script input as method args always global?
  Date: mer 13 nov 13 11:18:48 +0000

--
  * Se la Strada e la sua Virtu' non fossero state messe da parte,
* K * Carlo E. Prelz - fluido@fluido.as che bisogno ci sarebbe
  * di parlare tanto di amore e di rettitudine? (Chuang-Tzu)

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: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

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

···

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).

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 13/11/2013 13:21, Eric MSP Veith wrote:

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

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.

···

-----Original Message-----
From: ruby-talk [mailto:ruby-talk-bounces@ruby-lang.org] On Behalf Of gvim
Sent: Wednesday, November 13, 2013 1:19 PM
To: Ruby users
Subject: Re: Passing script input as method args always global?

On 13/11/2013 02:23, Avdi Grimm wrote:

Args are always passed by reference. When you pass |in| to |doit|,
>data> and |in| point to the same string object.

Without seeing what else goes on inside |doit|, it's hard to offer
insight on the behavior you're seeing.

Then I don't get this one:

var = 2

def f(x)
   x = x + 1
   return x
end

puts f(var) #=> 3
puts var #=> 2

gvim

x = 2
def f(y)
   y = y + 1
   return y
end

puts f(x) #=> 3
puts x #=> 2

The Perl equivalent is:

my $x =2;
sub f {
   $_[0] = $_[0] + 1;
   return $_[0];
}

say f($x); # 3
say $x; # 3

Perl retains the passed reference unless modified. Not so in Ruby where y becomes a new copy as soon as it is mutated.

gvim

···

On 13/11/2013 13:21, Eric MSP Veith wrote:

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

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.

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 :wink:

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

···

Subject: Re: Passing script input as method args always global?
  Date: mer 13 nov 13 01:05:47 +0000

--
  * Se la Strada e la sua Virtu' non fossero state messe da parte,
* K * Carlo E. Prelz - fluido@fluido.as che bisogno ci sarebbe
  * di parlare tanto di amore e di rettitudine? (Chuang-Tzu)

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.

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

    JavaRanch Campfire - Pass By Value, Please

or

    http://architects.dzone.com/articles/java-pass-value-and-not-pass-0

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:21 PM, Eric MSP Veith <lists@ruby-forum.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.

···

On Wed, Nov 13, 2013 at 2:43 PM, gvim <gvimrc@gmail.com> wrote:

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
\.

···

--
Posted via http://www.ruby-forum.com/\.

Thank you! That's the only explanation that makes sense so far but others seem to disagree.

gvim

···

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.

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

···

On 13/11/2013 11:32, Carlo E. Prelz wrote:

The line

x = x + 1

creates a new object. You can see this by printing the object id of x
before and after the sum:

...
def f(x)
   puts("before: #{x.object_id}")
   x = x + 1
   puts("after: #{x.object_id}")
   return x
end
...

gives here:

before: 5
after: 7

Carlo

Ruby passes arguments *by value*. You can modify a mutable object via its
API, but that has nothing to do with call semantics.

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

···

Subject: Re: Passing script input as method args always global?
  Date: mer 13 nov 13 12:01:24 +0000

--
  * Se la Strada e la sua Virtu' non fossero state messe da parte,
* K * Carlo E. Prelz - fluido@fluido.as che bisogno ci sarebbe
  * di parlare tanto di amore e di rettitudine? (Chuang-Tzu)

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 Wed, Nov 13, 2013 at 1:01 PM, gvim <gvimrc@gmail.com> wrote:

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++.

···

--
Posted via http://www.ruby-forum.com/\.

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

···

On 13/11/2013 12:10, Carlo E. Prelz wrote:

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

Which is what I would expect, but why does x retain its original value in this example:

x = 2

def f(y)
   y = y + 1
   return y
end

puts f(x) #=> 3
puts x #=> 2

In your example a and b are mutated but in mine x remains unchanged.

gvim

···

On 13/11/2013 12:13, Xavier Noria wrote:

     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.

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

···

Subject: Re: Passing script input as method args always global?
  Date: mer 13 nov 13 12:14:36 +0000

--
  * Se la Strada e la sua Virtu' non fossero state messe da parte,
* K * Carlo E. Prelz - fluido@fluido.as che bisogno ci sarebbe
  * di parlare tanto di amore e di rettitudine? (Chuang-Tzu)