Parallel method return value


#1

Hi all,
this is assignment behaviour:

a,b = 1,2,3
=> [1, 2, 3]

a
=> 1

b
=> 2

and with a method:

def a_method
return 1, 2, 3
end
=> nil

a,b = a_method
=> [1, 2, 3]

a
=> 1

b
=> 2

If I want only one lvalue, is this:

a, = 1, 2, 3
=> [1, 2, 3]

a
=> 1
the only way to get it?

I would have liked for the return behaviour to be set on the right side,
to allow method invocation like:

puts a_method

to return:
1

instead of
1
2
3

Thanks all!

L-P


#2

b
side,
to allow method invocation like:

puts a_method

to return:
1

instead of
1
2
3

So… uh, why wouldn’t you just return one value? That is:

def a_method
return 1
end

???

Perhaps, if it’s an array you have, then just use method #first:

def a_method
return some_array.first
end


#3

How about
def a_method
[1, 2, 3].reverse
end


#4

Louis-Philippe wrote:

and with a method:

def a_method
return 1, 2, 3
end

This behaves identically to

return [1, 2, 3]

That is, a single array object is returned. AFAIK, methods always return
exactly one value.

If I want only one lvalue, is this:

a, = 1, 2, 3
=> [1, 2, 3]

a
=> 1
the only way to get it?

a = a_method

is saying “assign whatever object is returned from a_method to a”, and
if that’s an array, then an array is what you get.

You can use the multiple-assignment syntax to drop the rest, or other
Array operations like

a = a_method[0]

a = a_method.first

I would have liked for the return behaviour to be set on the right side,
to allow method invocation like:

puts a_method

to return:
1

instead of
1
2
3

If a function returns an array, that’s what I want to see; I wouldn’t
want it to be arbitarily munged.


#5

Hi guys,

Thanks for your answer,I get your points…
but in this case, what I really want to do is have the method return the
right number of values for the corresponding quantity of lvalues
presented
to it, to make it context sensitive you know, so I can have, for
example, a
boolean first return value when it is called with one lvalue and a
boolean
plus a string when called with two rvalue. The assignment operator does
it,
so I would have expected the same behaviour to also work with a method.

right now my options are:

a, = a_method

or

a = a_method[0]

both ways still involve to ask for only one to return. What I am
looking
for, if it exist, is for the method to automatically detect context and
act
from it like the = operator. I find how the assignment operator
implements
this is very elegant, and am crave it for methods!!
But… those are probably the only ways to do it, because as Brian
said “methods
always return exactly one value”, and that is what I had previously
concluded from experimentation and reading the documentation.
Anybody can prove this wrong? (please!!)

thanks!

L-P

2008/12/12 Brian C. removed_email_address@domain.invalid


#6

On Dec 12, 2008, at 1:25 PM, Louis-Philippe wrote:

boolean
plus a string when called with two rvalue. The assignment operator
does it,
so I would have expected the same behaviour to also work with a
method.

But as was pointed out, methods always return one value, even if it
appears to return multiple values. They are lumped together into one
array.

for, if it exist, is for the method to automatically detect context
and act
from it like the = operator. I find how the assignment operator
implements
this is very elegant, and am crave it for methods!!

There isn’t any way for the method call to recognize the context in
which it is being called. You’d have to pass an argument, such as the
“number of return values” to return.

 a, b = a_method(2)
 a = a_method(1)

Which seems pointless, when you can instead do what you’ve already
identified as the proper technique:

 a, = a_method
 a, b = a_method
 a, b, c = a_method
 # etc.

Anybody can prove this wrong? (please!!)

No, because what was provided before wasn’t wrong.


#7

On Dec 12, 2008, at 2:21 PM, Louis-Philippe wrote:

Thanks Matthew,

“No, because what was provided before wasn’t wrong.”

Yeah… I believe you, but would really like it to be else!

Think of it this way…

 def foo
   return 1, 2, 3
 end

 a = foo

Now, you want a to be 1, but Ruby would need the power to read minds
to accommodate that. See, because if I do the same, I want a to be [1,
2, 3]. How is foo supposed to figure that out? Or why should your want
be more/less preferable than my want?

Simply, the interpreter can’t know. There has to be some syntax or
something that gives foo, or the assignment to a, that key information.

Telling foo would be passing an arg:

 def foo(nargs)
   return [1, 2, 3][0...nargs]
 end

 a = foo(1)

Any of the other examples come after foo is done, so:

 def foo

return 1, 2, 3
end

 a, = foo
 a = foo[0]
 a = foo.first

All three of those do the same… assign 1 to a. The latter two
request specifically the first item, while the first does parallel
assignment (of array components to particular variables… in this
case, only a). Since you seem interested in parallel assignment to a
variable number of variables, the first seems appropriate. Granted,
forgetting the comma might be easy, but there’s no way for foo to know
that you want a = foo to return 1 and that someone else that does a =
foo wants [1, 2, 3].


#8

On 12.12.2008, at 20:58 , Matthew M. wrote:

Think of it this way…
your want be more/less preferable than my want?

a = foo.first

He isn’t asking ruby to read minds, he is asking about overloading on
expected number of return values like e.g. matlab does. But it is like
everyone is saying, Ruby doesn’t do that, sorry.

einarmagnus


#9

Thanks Matthew,

"No, because what was provided before wasn't wrong."

Yeah… I believe you, but would really like it to be else!

L-P

2008/12/12 Matthew M. removed_email_address@domain.invalid


#10

Hi~

On Dec 12, 2008, at 12:58 PM, Matthew M. wrote:

Think of it this way…
your want be more/less preferable than my want?

a = foo.first

All three of those do the same… assign 1 to a. The latter two
request specifically the first item, while the first does parallel
assignment (of array components to particular variables… in this
case, only a). Since you seem interested in parallel assignment to a
variable number of variables, the first seems appropriate. Granted,
forgetting the comma might be easy, but there’s no way for foo to
know that you want a = foo to return 1 and that someone else that
does a = foo wants [1, 2, 3].

you can use the masign commas to get sort of what you want:

irb(main):001:0> def foo
irb(main):002:1> return 1,2,3
irb(main):003:1> end
=> nil
irb(main):004:0> a, = foo
=> [1, 2, 3]
irb(main):005:0> a
=> 1

Cheers-

Ezra Z.
removed_email_address@domain.invalid


#11

foo to know that you want a = foo to return 1 and that someone else
irb(main):005:0> a
=> 1

You mean like my first example above? :smiley:


#12

On Dec 12, 2008, at 2:08 PM, Matthew M. wrote:

for foo to know that you want a = foo to return 1 and that someone
irb(main):005:0> a
=> 1

You mean like my first example above? :smiley:

Yes exactly like that! /me wanders off to get some glasses…

Ezra


#13

Now, you want a to be 1, but Ruby would need the power to read minds to
accommodate that. See, because if I do the same, I want a to be [1, 2, 3].
How is foo supposed to figure that out? Or why should your want be more/less
preferable than my want?

You’re totally right Matthew, I was twisted into thinking assignment
would
do it for one lvalue with multiple rvalues…
Its probably a crazy idea, and who am I to have idea about language
design
without any means to implement them…
but anyway, here’s my thought (its this one that got me twisted).
Since the splat operator does nothing when preceding a rvalue of only
one
array, like in:

a = *[1,2,3] # => a = [1,2,3]
a = [1,2,3] # => a = [1,2,3]

a,b = *[1,2,3] # => a = 1, b = 2
a,b = [1,2,3] # => a = 1, b = 2

It would be in line with its normal use, to make all array items
absolutely
separate,
allowing for the impossible: a = *[1,2,3] # => a = 1 (I know, this
is
not working code, but thats how my head go previously twisted).
… I was just thinking out loud, I believe there is certainly a really
good
logic to explain why this fabulous language doesn’t already implement
this
feature, it surely won’t stop me in my unconditional ruby love :wink:

L-P


#14

On Fri, Dec 12, 2008 at 4:12 PM, Louis-Philippe removed_email_address@domain.invalid
wrote:

but anyway, here’s my thought (its this one that got me twisted).
separate,
allowing for the impossible: a = *[1,2,3] # => a = 1 (I know, this is
not working code, but thats how my head go previously twisted).
… I was just thinking out loud, I believe there is certainly a really good
logic to explain why this fabulous language doesn’t already implement this
feature, it surely won’t stop me in my unconditional ruby love :wink:

L-P

Perhaps bring your interests to the ruby core list. I like it the way
it is. Ruby’s parser assumes you require a single object unless the
left hand side is specified otherwise. I see no weirdness about this.

Todd


#15

irb(main):004:0> a, = foo
=> [1, 2, 3]
irb(main):005:0> a
=> 1

You mean like my first example above? :smiley:

Yes exactly like that! /me wanders off to get some glasses…

I can sympathize. It does seem to be “the right way”, but it also
seems to be an easy screwup.

Go unit tests!


#16

On Dec 12, 2008, at 4:12 PM, Louis-Philippe wrote:

would
do it for one lvalue with multiple rvalues…
Its probably a crazy idea, and who am I to have idea about language
design
without any means to implement them…

Well, I shouldn’t have said, “No, completely impossible.” Other
languages may do what you want. As far as Ruby goes, the options I see
are:

  1. Deal with it.
  2. Change design/spec of Ruby to return multiple values instead of one
    array. (Serious work and impact.)
  3. Have some sort of macro mechanism? (IE, where the call to foo would
    be inlined… perhaps then allowing parallel assignment).
  4. Support something like a = *[1, 2, 3] to mean a, = 1, 2, 3.
    (Umm… hmm… dunno about that.)
  5. Return a proxy? (This might not be any different from current
    situation.)
  6. Lambda/procs?
  7. Make a a proxy/class/wrapper that does what you want.

My guess is that #1 is current situation, #2 and #4 won’t happen, #3
I’ve no idea, #5 is no different than #1, and #6-7 I’d have to spend
some time thinking about. Maybe others have ideas on those.


#17

Perhaps bring your interests to the ruby core list.

The way it works is already plentiful, I was just asking to know up to
where
I could push it.
Maybe when I my knowledge of ruby gets a bit more maturity I’ll be
willing
to integrate the core list,
I don’t feel I have enough perspective on the language right now to
bring
anything to the ones which are into language design thinking.

Thanks,

L-P