Forum: Ruby How to pass arguments by reference in a function

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
2787449f6b88f3e502017d88ba7e6e67?d=identicon&s=25 ashishwave (Guest)
on 2007-07-27 08:16
(Received via mailing list)
if i pass arguments in a function then they get passed by value. how
to get it pased by reference.
For example: if i want to swrite my own swap function (not using
multiple assignment syntax a,b=b,a) just for example example, how to
implement that in ruby

bye :-)
Ashish Ranjan
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2007-07-27 08:34
(Received via mailing list)
2007/7/27, ashishwave <ashishwave@gmail.com>:
> if i pass arguments in a function then they get passed by value. how
> to get it passed by reference.

You can't.  There are some solutions to this depending on situation:

1. inplace modification of arguments (Strings, Arrays, Hashes - all
sorts of containers)

2. multiple return values

3. work with instance variables

Generally in my experience it's not needed.

> For example: if i want to swrite my own swap function (not using
> multiple assignment syntax a,b=b,a) just for example example, how to
> implement that in ruby

irb(main):001:0> def swap(a,b) return b,a end
=> nil
irb(main):002:0> x,y=1,2
=> [1, 2]
irb(main):003:0> x,y = swap x,y
=> [2, 1]
irb(main):004:0> x
=> 2
irb(main):005:0> y
=> 1

But in reality you would just do

x,y = y,x

Kind regards

robert
Aafa8848c4b764f080b1b31a51eab73d?d=identicon&s=25 Phlip (Guest)
on 2007-07-27 13:37
(Received via mailing list)
ashishwave wrote:

> if i pass arguments in a function then they get passed by value.

Ruby supports two kinds of variables; IIRC numbers, characters,
booleans,
and nil are "immediate", and everything else is a reference to an
object.

The best way to explain this is to look at Ruby's source. A VALUE is the
union of a long and a pointer. Anything small enough to fit in a long is
an
immediate value, and everything else uses the pointer to point to a
non-immediate object.

So at function call time, Ruby passes the _VALUE_ by value. So
immediates
get copied, and objects get passed by reference.

So, in addition to your other answer, you could also put your referend
into
a class, and pass this around. That might fit the ideals of Object
Oriented
Programming better than passing immediates would.
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2007-07-27 15:40
(Received via mailing list)
2007/7/27, Phlip <phlip2005@gmail.com>:
> ashishwave wrote:
>
> > if i pass arguments in a function then they get passed by value.
>
> Ruby supports two kinds of variables; IIRC numbers, characters, booleans,
> and nil are "immediate", and everything else is a reference to an object.

Personally I find it easier to grasp (especially when starting out
with Ruby) this when you assume that everything is an object.
Although there are some optimizations going on behind the scenes all
objects behave the same - from a Ruby user's perspective. This is
totally different from Java's handling of PODs for example.

> The best way to explain this is to look at Ruby's source. A VALUE is the
> union of a long and a pointer. Anything small enough to fit in a long is an
> immediate value, and everything else uses the pointer to point to a
> non-immediate object.

Again, I would not start with Ruby sources here.

> So at function call time, Ruby passes the _VALUE_ by value. So immediates
> get copied, and objects get passed by reference.

I think "pass by reference" is not the proper term because that would
imply that you could change a variable in the calling scope, i.e. you
could do

def magic(x) x = 10 end
foo = 1
puts foo # prints 1
magic(foo)
puts foo # prints 10

which you can't.  I'd rather call it "call by reference value", i.e.
the reference is copied.

> So, in addition to your other answer, you could also put your referend into
> a class, and pass this around. That might fit the ideals of Object Oriented
> Programming better than passing immediates would.

I am not sure why you refer to immediates here.  Using instance
variables is generally one of the core OO techniques.

Kind regards

robert
Aafa8848c4b764f080b1b31a51eab73d?d=identicon&s=25 Phlip (Guest)
on 2007-07-27 16:06
(Received via mailing list)
Robert Klemme wrote:

> which you can't.
Working backwards from your example, that is the definition of an
"immediate
value". Violent agreement achieved!
E0ed615bd6632dd23165e045e3c1df09?d=identicon&s=25 Florian Gross (Guest)
on 2007-07-27 16:34
(Received via mailing list)
On Jul 27, 8:32 am, "Robert Klemme" <shortcut...@googlemail.com>
wrote:
> 2. multiple return values
>
> 3. work with instance variables

4. passing lambdas around

x, y = 1, 2
x_ref = [lambda { x }, lambda { |x| }]
y_ref = [lambda { y }, lambda { |y| }]
swap(x_ref, y_ref}

See http://flgr.0x42.net/code/variable.rb
84dc575c33a123789521d53cad0f62ae?d=identicon&s=25 Lloyd Linklater (lloyd)
on 2007-07-27 20:42
ashishwave wrote:
> For example: if i want to write my own swap function (not using
> multiple assignment syntax a,b=b,a) just for example example, how to
> implement that in ruby

That reminds me, in the old days you could do a swap without a third
variable using XOR.  e.g.

a = 13
b = 17

a ^= b
b ^= a
a ^= b

and they are swapped.

I know that Ruby might do it as mentioned above.

My question is, which is more efficient?
B8cfd5ec0f88bf5b5f2eedda7d1a0746?d=identicon&s=25 Peter Seebach (Guest)
on 2007-07-27 21:18
(Received via mailing list)
In message <0514e8b08bc1a44593d7ffe0ddb5117e@ruby-forum.com>, Lloyd
Linklater w
rites:
>and they are swapped.
>
>I know that Ruby might do it as mentioned above.
>
>My question is, which is more efficient?

The xor swap is virtually never more efficient on reasonable hardware.
A casual pass through suggests that, even for the special case of
numbers
where a, b, and a^b are all Fixnum-ranged, the straight swap ought to be
noticably faster.

More importantly:  How could doing it that way ever be idiomatic or easy
to understand?  I cannot conceive of a program where I have to swap two
objects quickly, and the need to swap them quickly is so great that a
hack
like that would be worth it... and I can't just bypass the swap by
improving
the algorithm.

-s
F62cfaca4a7a5bf58e08a664c2f41b94?d=identicon&s=25 Ian Whitlock (ian)
on 2007-07-27 21:24
Lloyd Linklater wrote:
> My question is, which is more efficient?

It may depends on the definition of efficient.
Try it with a = "13" and b = "17".

In terms of execution time it is a horse race
that doesn't matter much.  Try

require "benchmark"
include Benchmark

n = 100001

bm(10) do |x|
  a = 13
  b = 17
  x.report("XOR") {n.times {a ^= b;b ^= a;a ^= b} }
  puts a , b
  x.report("ruby") {n.times {b,a = a,b} }
  puts a , b
end

Ian
4feed660d3728526797edeb4f0467384?d=identicon&s=25 Bill Kelly (Guest)
on 2007-07-27 21:37
(Received via mailing list)
From: "Peter Seebach" <seebs@seebs.net>
> the algorithm.
Incidentally, I do recall one interesting use of this XOR swap
technique.

I believe this is how GUI menus were drawn on the screen on the
Amiga.  When you'd click the mouse to get a menu, the system
would allocate off-screen bitmap memory, and render the menu
into the off-screen bitmap.  Then it would XOR-swap the off-screen
rendered menu, with the location on the screen where the menu
would be displayed.  Thus preserving the pixels from the screen
that would be obscured by the menu, so that the pixels could
be restored when the menu was dismissed.

Pretty neat trick, since it avoided allocating an extra buffer
to store the obscured screen pixels.  (And it was fast, because
the Amiga bitmap blitter supported logical raster op's including
XOR, etc.)


Regards,

Bill
B8cfd5ec0f88bf5b5f2eedda7d1a0746?d=identicon&s=25 Peter Seebach (Guest)
on 2007-07-27 21:45
(Received via mailing list)
In message <026a01c7d085$106a05c0$6442a8c0@musicbox>, "Bill Kelly"
writes:
>Incidentally, I do recall one interesting use of this XOR swap
>technique.

>I believe this is how GUI menus were drawn on the screen on the
>Amiga.  When you'd click the mouse to get a menu, the system
>would allocate off-screen bitmap memory, and render the menu
>into the off-screen bitmap.  Then it would XOR-swap the off-screen
>rendered menu, with the location on the screen where the menu
>would be displayed.  Thus preserving the pixels from the screen
>that would be obscured by the menu, so that the pixels could
>be restored when the menu was dismissed.

Interesting.  There were a few different ways; you could request
automatic backing store, or you could do it yourself and get
notifications,
but it was mostly transparent.

>Pretty neat trick, since it avoided allocating an extra buffer
>to store the obscured screen pixels.  (And it was fast, because
>the Amiga bitmap blitter supported logical raster op's including
>XOR, etc.)

Except it does allocate a buffer, really.  I don't recall the details
anymore.

-s
Bef7ff8a0537495a1876ffebdc9f8e51?d=identicon&s=25 Lionel Bouton (Guest)
on 2007-07-27 22:06
(Received via mailing list)
Peter Seebach wrote the following on 27.07.2007 21:16 :
>
A program in assembler for a microcontroller with so few memory that
using the stack for a temporary variable is out of the question comes to
my mind.

But for sure no program written in Ruby would need this kind of hack.
Even more, if my assumptions of how Ruby internals work are correct,
using the xor in this case is less memory efficient as it should
generate new Fixnum objects instead of just swapping references to
them...

Lionel.
4feed660d3728526797edeb4f0467384?d=identicon&s=25 Bill Kelly (Guest)
on 2007-07-27 22:29
(Received via mailing list)
From: "Peter Seebach" <seebs@seebs.net>
>>would be displayed.  Thus preserving the pixels from the screen
>>that would be obscured by the menu, so that the pixels could
>>be restored when the menu was dismissed.
>
> Interesting.  There were a few different ways; you could request
> automatic backing store, or you could do it yourself and get notifications,
> but it was mostly transparent.

Menus were handled differently than windows, as I recall.
(For windows, yes, there were three buffering/backing-store
modes: SIMPLE_REFRESH, SMART_REFRESH, and SUPER_BITMAP.  But
menus, if I recall correctly, were not really windows. They
locked the layers and performed the XOR trick as described above.)


>>Pretty neat trick, since it avoided allocating an extra buffer
>>to store the obscured screen pixels.  (And it was fast, because
>>the Amiga bitmap blitter supported logical raster op's including
>>XOR, etc.)
>
> Except it does allocate a buffer, really.  I don't recall the details
> anymore.

Right, just one buffer though.  The neat trick was that with
just one buffer, you could fully render the menu off-screen,
then swap it on-screen, while simultaneously preserving the
on-screen pixels for later restoration.

What was kind of fun, is if your screen had enough bitplanes,
you could actually *see* the XOR trick in transition, if the
video beam happened to catch the screen region where the XOR
was occurring, and only some of the bitplanes had been processed
yet.  If the screen had lots of bitplanes, and a large menu
was dropping down, you'd get a momentary funky colorful flash
as the menu/screen pixels were being XOR swapped into the
off-screen buffer.


Regards,

Bill
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2007-07-27 22:31
(Received via mailing list)
On 27.07.2007 11:22, Phlip wrote:
>> puts foo # prints 10
>>
>> which you can't.
>
> Working backwards from your example, that is the definition of an "immediate
> value". Violent agreement achieved!

I'm not sure where you see the agreement and also I don't see how the
piece above makes for a definition of an immediate value.  Did I miss a
smiley somewhere?

An immediate value is something that does not live on the heap but where
the reference is the value.  Other than that it behaves the same as any
other object.  Immediate values are just an interpreter internal
optimization - you wouldn't notice if that was abandoned and Fixnums
became ordinary instances like others (apart from performance of
course).

The example presented by me does not work - regardless whether you use a
Fixnum, an Array or some other object.  This has only to do with the
parameter passing mode.

Kind regards

  robert
This topic is locked and can not be replied to.