Forum: Ruby parallel method return value

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.
Louis-Philippe (Guest)
on 2008-12-12 05:51
(Received via mailing list)
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
Matthew M. (Guest)
on 2008-12-12 06:58
(Received via mailing list)
>>> 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
Pierre P. (Guest)
on 2008-12-12 07:20
How about
def a_method
  [1, 2, 3].reverse
end
Brian C. (Guest)
on 2008-12-12 10:49
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.
Louis-Philippe (Guest)
on 2008-12-12 21:33
(Received via mailing list)
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>
Matthew M. (Guest)
on 2008-12-12 21:47
(Received via mailing list)
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.
Louis-Philippe (Guest)
on 2008-12-12 22:29
(Received via mailing list)
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>
Matthew M. (Guest)
on 2008-12-12 23:07
(Received via mailing list)
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].
Einar Magnús Boson (Guest)
on 2008-12-12 23:42
(Received via mailing list)
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
Ezra Z. (Guest)
on 2008-12-12 23:56
(Received via mailing list)
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
Matthew M. (Guest)
on 2008-12-13 00:16
(Received via mailing list)
>> 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?   :D
Louis-Philippe (Guest)
on 2008-12-13 00:19
(Received via mailing list)
> 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 ;)

L-P
Ezra Z. (Guest)
on 2008-12-13 00:27
(Received via mailing list)
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?   :D

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

Ezra
Matthew M. (Guest)
on 2008-12-13 00:37
(Received via mailing list)
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.
Todd B. (Guest)
on 2008-12-13 00:50
(Received via mailing list)
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 ;)
>
> 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
Matthew M. (Guest)
on 2008-12-13 01:11
(Received via mailing list)
>>> irb(main):004:0> a, = foo
>>> => [1, 2, 3]
>>> irb(main):005:0> a
>>> => 1
>>
>>
>> You mean like my first example above?   :D
>
> 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!
Louis-Philippe (Guest)
on 2008-12-13 04:11
(Received via mailing list)
>
>
> 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
This topic is locked and can not be replied to.