Simple issue giving problems

B

Brad

Hello all,

I have a problem that may or may not be an easy fix. :)

Given the following:


a=1
b=2

def swapper(dest,src)
dest,src=src,dest
end

swapper(a,b)
p [ a, b ]



Why are the values of the variables not swapped? Is there
a way to coerce ruby into doing a and b by using src and dest?

Any help is greatly appreciated.

Thanks,

Brad
 
J

Jamis Buck

Brad said:
a=1
b=2

def swapper(dest,src)
dest,src=src,dest
end

swapper(a,b)
p [ a, b ]

Well... given that the swap is only a one-liner, you really don't need
to do the function call at all. However, I understand there is a deeper
issue here--sometimes you want to modify the parameters... What I
usually do is just return the modified parameters, like this:

def swaper( dest, src )
dest, src = src, dest
return [ dest, src ]
end

a, b = swapper( a, b )
p [ a, b ]
 
G

Gennady

Hello all,

I have a problem that may or may not be an easy fix. :)

Given the following:


a=1
b=2

def swapper(dest,src)
dest,src=src,dest
end


If you put it this way:

a=1
b=2

dest=a
src=b

dest,src=src,dest

It swaps dest and src. And I do not think you would expect a and b
being swapped as well as a result of this. Same with calling a method
as in your example. You cannot deal with variables' addresses in Ruby
as in C.
swapper(a,b)
p [ a, b ]



Why are the values of the variables not swapped? Is there
a way to coerce ruby into doing a and b by using src and dest?

Any help is greatly appreciated.

Thanks,

Brad

Sincerely,
Gennady Bystritsky
 
B

Brad

Jamis said:
Brad said:
a=1
b=2

def swapper(dest,src)
dest,src=src,dest
end

swapper(a,b)
p [ a, b ]

Well... given that the swap is only a one-liner, you really don't need
to do the function call at all. However, I understand there is a deeper
issue here--sometimes you want to modify the parameters... What I
usually do is just return the modified parameters, like this:

def swaper( dest, src )
dest, src = src, dest
return [ dest, src ]
end

a, b = swapper( a, b )
p [ a, b ]


Thanks for your speedy response. You are quite correct as there is a
deeper issue, rather a larger project. I figured that 8 lines of code
were more illustrative than several hundred. :)

I figured it couldn't hurt to ask.

Thanks,
Brad
 
B

Brad

Gennady said:
If you put it this way:

a=1
b=2

dest=a
src=b

dest,src=src,dest

It swaps dest and src. And I do not think you would expect a and b
being swapped as well as a result of this. Same with calling a method
as in your example. You cannot deal with variables' addresses in Ruby
as in C.

True, in the case you present I would not expect a and b to be altered.
But what I was wondering was if there were some way to allow
manipulation of
swapper(a,b)
p [ a, b ]



Why are the values of the variables not swapped? Is there
a way to coerce ruby into doing a and b by using src and dest?

Any help is greatly appreciated.

Thanks,

Brad

Sincerely,
Gennady Bystritsky
 
B

Brad

Brad said:
Gennady said:
Hello all,

I have a problem that may or may not be an easy fix. :)

Given the following:


a=1
b=2

def swapper(dest,src)
dest,src=src,dest
end


If you put it this way:

a=1
b=2

dest=a
src=b

dest,src=src,dest

It swaps dest and src. And I do not think you would expect a and b
being swapped as well as a result of this. Same with calling a method
as in your example. You cannot deal with variables' addresses in Ruby
as in C.
swapper(a,b)
p [ a, b ]



Why are the values of the variables not swapped? Is there
a way to coerce ruby into doing a and b by using src and dest?

Any help is greatly appreciated.

Thanks,

Brad

Sincerely,
Gennady Bystritsky

True, in the case you present I would not expect a and b to be altered.
But what I was wondering was if there were some way to allow
manipulation of

Sorry didn't mean to send that one. :) Hit wrong key sequence.

What I was trying to say was...

I was wondering if there were some way to allow manipulations of
function/methods parameters such that the calling processes variable
values would be modified.

As I understand it now this is not possible, though being new to Ruby I
thought it couldn't hurt to ask.

Thanks for your response.

Regards,
Brad
 
S

Simon Strandgaard

I was wondering if there were some way to allow manipulations of
function/methods parameters such that the calling processes variable
values would be modified.


irb(main):001:0> ary=%w(a b c d)
=> ["a", "b", "c", "d"]
irb(main):002:0> def test(val)
irb(main):003:1> val[2] = 42
irb(main):004:1> end
=> nil
irb(main):005:0> test(ary)
=> 42
irb(main):006:0> ary
=> ["a", "b", 42, "d"]
irb(main):007:0>
 
G

gabriele renzi

il Thu, 11 Dec 2003 20:26:53 -0400, Brad <[email protected]> ha
scritto::

Sorry didn't mean to send that one. :) Hit wrong key sequence.

What I was trying to say was...

I was wondering if there were some way to allow manipulations of
function/methods parameters such that the calling processes variable
values would be modified.

As I understand it now this is not possible, though being new to Ruby I
thought it couldn't hurt to ask.

I don't think this is possible. The only thing you can do is wrap vars
in a bigger datastruct (i.e. an array), then pass the object to your
swapper method.

Oh, and I think you can change variable bindings from within a Proc
object, if that helps :)
 
J

Josef 'Jupp' SCHUGT

Hi!

* Jamis Buck; 2003-12-12, 00:33 UTC:
def swaper( dest, src )
dest, src = src, dest
return [ dest, src ]
end

That code can be significantly improved:

def swapper(first, second)
return [second, first]
end

Using names dest, src would be okay for something like this:

def assigner(dest, src)
return [src, src]
end

Josef 'Jupp' SCHUGT
 
R

Robert Klemme

Josef 'Jupp' SCHUGT said:
Hi!

* Jamis Buck; 2003-12-12, 00:33 UTC:
def swaper( dest, src )
dest, src = src, dest
return [ dest, src ]
end

That code can be significantly improved:

def swapper(first, second)
return [second, first]
end

usually

a,b = b,a

is sufficient.
Using names dest, src would be okay for something like this:

def assigner(dest, src)
return [src, src]
end

How do you want to use that method? I can't see a use of this.

Regards

robert
 
R

Robert Klemme

Brad said:
Sorry didn't mean to send that one. :) Hit wrong key sequence.

What I was trying to say was...

I was wondering if there were some way to allow manipulations of
function/methods parameters such that the calling processes variable
values would be modified.

Actually you don't need that since you can always use a parallel
assignment:

a,b = b,a

foo[10], foo[7] = foo[7], foo[10]

bar["x"], baz["eee"] = baz["eee"], bar["x"]
As I understand it now this is not possible, though being new to Ruby I
thought it couldn't hurt to ask.

Seems like you come from a perl background where such aliasings exist...

robert
 
G

gabriele renzi

Hello all,

I have a problem that may or may not be an easy fix. :)

Given the following:

on a sidenote, I've been playing with:

def swapper(obj,a,b)
obj.instance_eval("#{a},#{b}=#{b},#{a}")
end

swapper(self,:a,:b)


but this does'nt work.

Anyway, if I do this:

p a
p b

self.instance_eval("#{:a},#{:b}=#{:b},#{:a}")
p a
p b

it works as expected (i.e. swaps the variables)

Some hints to explain me this ?
 
K

Kent Dahl

gabriele said:
on a sidenote, I've been playing with:

def swapper(obj,a,b)
obj.instance_eval("#{a},#{b}=#{b},#{a}")
end

swapper(self,:a,:b)


but this does'nt work.

Because the scope of the variables is different, I believe. The method
does not have access to local variables of the calling method. Even if
you use instance_eval, you will just have access to instance variables
of the given self, not local variables for any arbitrary local method
called on it further up the callchain.
Anyway, if I do this:

p a
p b

self.instance_eval("#{:a},#{:b}=#{:b},#{:a}")
p a
p b

it works as expected (i.e. swaps the variables)

Some hints to explain me this ?


a = 3
b = 5

# Will not work, different scopes.
def swapper(obj,a,b)
obj.instance_eval("#{a},#{b}=#{b},#{a}")
end
swapper(self,:a,:b)
print a, b, "\n" #=> 35

# Pass scope deliberately as a Proc.
def swapper2(a,b,&block)
eval("#{a},#{b}=#{b},#{a}", block)
end
swapper2:)a,:b){}
print a, b, "\n" #=> 53


You can do a lot of fancy (but ugly) things with the latter form. I tend
to rewrite it to pass arguments through the Proc, just to make it look
as ugly as it really is.

# Pass scope deliberately as a Proc.
def swapper3(&block)
a,b = block.call
eval("#{a},#{b}=#{b},#{a}", block)
end
swapper3{[:a,:b]}
print a, b, "\n" #=> 35


HTH
 
J

Josef 'Jupp' SCHUGT

Hi!

* Robert Klemme; 2003-12-12, 22:34 UTC:
usually

a,b = b,a

is sufficient.

Of course. Unless the aim is an exercise in functional programming.
Using names dest, src would be okay for something like this:

def assigner(dest, src)
return [src, src]
end

How do you want to use that method? I can't see a use of this.

I cannot see it, either. It was just the example involving least
changes where src and dest make sense.

Josef 'Jupp' SCHUGT
 
J

Jim Weirich

Brad said:
What I was trying to say was...

I was wondering if there were some way to allow manipulations of
function/methods parameters such that the calling processes variable
values would be modified.

As I understand it now this is not possible, though being new to Ruby I
thought it couldn't hurt to ask.

No, it doesn't hurt to ask.

There is a way of modifying the variable bindings in the calling method,
but it is not widely used. You need to create a "reference" to the
variable and pass that into the swap function. I use a "helper"
function "ref" to create the reference ...

Here's an example ...

require 'reference'

def swap(a,b)
a.value, b.value = b.value, a.value
end

x = 10
y = 11

puts "BEFORE: x = #{x}, y = #{y}"
swap(ref{:x}, ref{:y})
puts "AFTER: x = #{x}, y = #{y}"

Note that those are curly braces, not parenthesis after "ref". This
will print ...

BEFORE: x = 10, y = 11
AFTER: x = 11, y = 10

Here's the reference.rb file that you will need ...

class Reference
def initialize(&block)
sym = block.call
fail "Block must yield symbol" unless Symbol === sym
@getter = eval "proc { #{sym} }", block
@setter = eval "proc { |v| #{sym} = v }", block
end
def value
@getter.call
end
def value=(v)
@setter.call(v)
end
end

def ref(&block)
Reference.new(&block)
end
 
B

Brad

Jim said:
No, it doesn't hurt to ask.

There is a way of modifying the variable bindings in the calling method,
but it is not widely used. You need to create a "reference" to the
variable and pass that into the swap function. I use a "helper"
function "ref" to create the reference ...

Here's an example ...

require 'reference'

def swap(a,b)
a.value, b.value = b.value, a.value
end

x = 10
y = 11

puts "BEFORE: x = #{x}, y = #{y}"
swap(ref{:x}, ref{:y})
puts "AFTER: x = #{x}, y = #{y}"

Note that those are curly braces, not parenthesis after "ref". This
will print ...

BEFORE: x = 10, y = 11
AFTER: x = 11, y = 10

Here's the reference.rb file that you will need ...

class Reference
def initialize(&block)
sym = block.call
fail "Block must yield symbol" unless Symbol === sym
@getter = eval "proc { #{sym} }", block
@setter = eval "proc { |v| #{sym} = v }", block
end
def value
@getter.call
end
def value=(v)
@setter.call(v)
end
end

def ref(&block)
Reference.new(&block)
end

Jim:

Thanks for the reply, it's appreciated. I think this may be what I'm
looking for. I'll give it a try and get back to you with the results.


Thanks,
Brad
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,142
Messages
2,570,818
Members
47,362
Latest member
eitamoro

Latest Threads

Top