How to return more than one result from a method?

I’m trying to code a method that has two result values. The values are
very different objects: an Image (a large and complicated object) and a
plain ol’ Ruby Float. I’m not sure what the best way to handle this is. I
could return them an Array with 2 elements, but that feels too
lightweight. I could return a Hash with 2 members. I could define a new
class with two attributes, but that feels too heavyweight. I even thought
of having the method yield to a block, passing the two results as
arguments to the block, but that just seems bizarre.

So I’m soliciting advice. How has this been solved before?

I’m trying to code a method that has two result values. The values are

very different objects: an Image (a large and complicated object) and a

plain ol’ Ruby Float. I’m not sure what the best way to handle this is. I

could return them an Array with 2 elements, but that feels too

lightweight. I could return a Hash with 2 members. I could define a new

class with two attributes, but that feels too heavyweight. I even thought

of having the method yield to a block, passing the two results as

arguments to the block, but that just seems bizarre.

What does the Float represent? Perhaps there is a relationship between
the two that would make a new type of class communicate better. My
thought is (generally) that if you can’t tie the two return values
together in some kind of meaningful way, you may be doing more than one
job in the method and you could split the method in two. That’s just a
heuristic of course. Can you explain what the method does a little more?

Chad

···

On Fri, 19 Dec 2003, Tim Hunter wrote:

Hi –

I’m trying to code a method that has two result values. The values are
very different objects: an Image (a large and complicated object) and a
plain ol’ Ruby Float. I’m not sure what the best way to handle this is. I
could return them an Array with 2 elements, but that feels too
lightweight. I could return a Hash with 2 members. I could define a new
class with two attributes, but that feels too heavyweight. I even thought
of having the method yield to a block, passing the two results as
arguments to the block, but that just seems bizarre.

So I’m soliciting advice. How has this been solved before?

Could you just assign them directly to variables in the calling scope?
Technically you’d be returning an Array but you don’t have to deal
with it directly:

irb(main):001:0> def two; return 1,2; end
=> nil
irb(main):002:0> a,b = two
=> [1, 2]
irb(main):003:0> a
=> 1
irb(main):004:0> b
=> 2

That might be the best way if you don’t need to deal with the two
values as a pair beyond getting them back from the method.

David

···

On Fri, 19 Dec 2003, Tim Hunter wrote:


David A. Black
dblack@wobblini.net

The method compares two Images and returns a “difference” image (a new
Image that graphically highlights the differences between the two input
images). The Float is a “distortion” statistic - a measure of the amount
of difference between the two.

···

On Fri, 19 Dec 2003 09:12:20 +0900, Chad Fowler wrote:

What does the Float represent? Perhaps there is a relationship between
the two that would make a new type of class communicate better. My
thought is (generally) that if you can’t tie the two return values
together in some kind of meaningful way, you may be doing more than one
job in the method and you could split the method in two. That’s just a
heuristic of course. Can you explain what the method does a little more?

“David A. Black” dblack@wobblini.net schrieb im Newsbeitrag
news:Pine.LNX.4.44.0312181612570.29763-100000@wobblini…

Hi –

I’m trying to code a method that has two result values. The values are
very different objects: an Image (a large and complicated object) and a
plain ol’ Ruby Float. I’m not sure what the best way to handle this is.
I
could return them an Array with 2 elements, but that feels too
lightweight. I could return a Hash with 2 members. I could define a new
class with two attributes, but that feels too heavyweight. I even
thought
of having the method yield to a block, passing the two results as
arguments to the block, but that just seems bizarre.

So I’m soliciting advice. How has this been solved before?

Could you just assign them directly to variables in the calling scope?
Technically you’d be returning an Array but you don’t have to deal
with it directly:

irb(main):001:0> def two; return 1,2; end
=> nil
irb(main):002:0> a,b = two
=> [1, 2]
irb(main):003:0> a
=> 1
irb(main):004:0> b
=> 2

That might be the best way if you don’t need to deal with the two
values as a pair beyond getting them back from the method.

Even if you need to deal with them as pair this is the appropriate method:

irb(main):001:0> def two; return 1,2; end
=> nil
irb(main):002:0> all = two
=> [1, 2]
irb(main):003:0>

Regards

robert
···

On Fri, 19 Dec 2003, Tim Hunter wrote:

On Fri, 19 Dec 2003 09:12:20 +0900, Chad Fowler wrote:

>

> What does the Float represent? Perhaps there is a relationship between

> the two that would make a new type of class communicate better. My

> thought is (generally) that if you can’t tie the two return values

> together in some kind of meaningful way, you may be doing more than one

> job in the method and you could split the method in two. That’s just a

> heuristic of course. Can you explain what the method does a little more?

>

···

On Fri, 19 Dec 2003, Tim Hunter wrote:

The method compares two Images and returns a “difference” image (a new

Image that graphically highlights the differences between the two input

images). The Float is a “distortion” statistic - a measure of the amount

of difference between the two.

I think I might just “return new_image, distortion” in this case. :slight_smile:

Tim Hunter wrote:

···

On Fri, 19 Dec 2003 09:12:20 +0900, Chad Fowler wrote:

What does the Float represent? Perhaps there is a relationship between
the two that would make a new type of class communicate better. My
thought is (generally) that if you can’t tie the two return values
together in some kind of meaningful way, you may be doing more than one
job in the method and you could split the method in two. That’s just a
heuristic of course. Can you explain what the method does a little more?

The method compares two Images and returns a “difference” image (a new
Image that graphically highlights the differences between the two input
images). The Float is a “distortion” statistic - a measure of the amount
of difference between the two.

Here are some ways to do it.

  • an array might be easiest
  • a Struct might be an option – it’s a little lighter weight than
    a class
  • you could add the distortion as a singleton method on the new image

Hal

Hi –

“David A. Black” dblack@wobblini.net schrieb im Newsbeitrag
news:Pine.LNX.4.44.0312181612570.29763-100000@wobblini…

irb(main):001:0> def two; return 1,2; end
=> nil
irb(main):002:0> a,b = two
=> [1, 2]
irb(main):003:0> a
=> 1
irb(main):004:0> b
=> 2

That might be the best way if you don’t need to deal with the two
values as a pair beyond getting them back from the method.

Even if you need to deal with them as pair this is the appropriate method:

Do you mean: even if you don’t need to deal… ?

irb(main):001:0> def two; return 1,2; end
=> nil
irb(main):002:0> all = two
=> [1, 2]
irb(main):003:0>

I’m not sure what you mean by appropriate. Can you elaborate?

David

···

On Fri, 19 Dec 2003, Robert Klemme wrote:


David A. Black
dblack@wobblini.net

No, the original message addressed the not-needing-to-deal; this was the
opposite. The point is, the caller can do either:

    var1, var2 = obj.meth

and thereby get the results in separate variables, or

    onevar = obj.meth

and get the results as an array stored in a single variable.

-Mark

···

On Fri, Dec 19, 2003 at 10:28:49PM +0900, David A. Black wrote:

That might be the best way if you don’t need to deal with the two
values as a pair beyond getting them back from the method.

Even if you need to deal with them as pair this is the appropriate method:

Do you mean: even if you don’t need to deal… ?

“David A. Black” dblack@wobblini.net schrieb im Newsbeitrag
news:Pine.LNX.4.44.0312190524460.4320-100000@wobblini…

Hi –

“David A. Black” dblack@wobblini.net schrieb im Newsbeitrag
news:Pine.LNX.4.44.0312181612570.29763-100000@wobblini…

irb(main):001:0> def two; return 1,2; end
=> nil
irb(main):002:0> a,b = two
=> [1, 2]
irb(main):003:0> a
=> 1
irb(main):004:0> b
=> 2

That might be the best way if you don’t need to deal with the two
values as a pair beyond getting them back from the method.

Even if you need to deal with them as pair this is the appropriate
method:

Do you mean: even if you don’t need to deal… ?

irb(main):001:0> def two; return 1,2; end
=> nil
irb(main):002:0> all = two
=> [1, 2]
irb(main):003:0>

I’m not sure what you mean by appropriate. Can you elaborate?

Sorry for the delay. I meant “return a,b” is the appropriate idiom for
accessing single values as well as for accessing all values in an array. Of
course you can do “return [a,b]” as well. So with the definition above you
can do “x,y = two()” as well as “z = two()” where z is an array.

Regards

robert
···

On Fri, 19 Dec 2003, Robert Klemme wrote:

Hi –

That might be the best way if you don’t need to deal with the two
values as a pair beyond getting them back from the method.

Even if you need to deal with them as pair this is the appropriate method:

Do you mean: even if you don’t need to deal… ?

No, the original message addressed the not-needing-to-deal; this was the
opposite. The point is, the caller can do either:

    var1, var2 = obj.meth

and thereby get the results in separate variables, or

    onevar = obj.meth

and get the results as an array stored in a single variable.

Yes, that was our starting point :slight_smile: My var1, var2 suggestion was as
an alternative to the grabbing-as-an-array approach. I think the
subsequent confusion was over the word ‘pair’, which I took to mean
‘array’ in Robert’s usage.

Anyway, Robert seemed to be suggesting that, of the two ways that have
been demonstrated, returning a single array is the ‘appropriate’ way
and that was what I wasn’t following.

David

···

On Sat, 20 Dec 2003, Mark J. Reed wrote:

On Fri, Dec 19, 2003 at 10:28:49PM +0900, David A. Black wrote:


David A. Black
dblack@wobblini.net

David A. Black wrote:

Hi –

That might be the best way if you don’t need to deal with the two
values as a pair beyond getting them back from the method.

Even if you need to deal with them as pair this is the appropriate method:

Do you mean: even if you don’t need to deal… ?

No, the original message addressed the not-needing-to-deal; this was the
opposite. The point is, the caller can do either:

   var1, var2 = obj.meth

and thereby get the results in separate variables, or

   onevar = obj.meth

and get the results as an array stored in a single variable.

Yes, that was our starting point :slight_smile: My var1, var2 suggestion was as
an alternative to the grabbing-as-an-array approach. I think the
subsequent confusion was over the word ‘pair’, which I took to mean
‘array’ in Robert’s usage.

Anyway, Robert seemed to be suggesting that, of the two ways that have
been demonstrated, returning a single array is the ‘appropriate’ way
and that was what I wasn’t following.

A semantic issue. But then, isn’t everything?

The actual return is an array either way. Whether you then assign
it to one var or two is beyond the control or concern of the method.

Hal

···

On Sat, 20 Dec 2003, Mark J. Reed wrote:

On Fri, Dec 19, 2003 at 10:28:49PM +0900, David A. Black wrote:

Hi –

David A. Black wrote:

Anyway, Robert seemed to be suggesting that, of the two ways that have
been demonstrated, returning a single array is the ‘appropriate’ way
and that was what I wasn’t following.

A semantic issue. But then, isn’t everything?

The actual return is an array either way. Whether you then assign
it to one var or two is beyond the control or concern of the method.

I should have said: I thought Robert meant that saving to one variable
was the appropriate way – i.e., I thought he was saying that there was
something inherently bad about doing:

a,b = meth

and that one should always do:

all = meth

Aside from not having expressed clearly what I thought he meant, I
later realized that he hadn’t meant that anyway – he was talking
about the rhs (i.e., what’s appropriate is to do: return a,b).

David

···

On Sat, 20 Dec 2003, Hal Fulton wrote:


David A. Black
dblack@wobblini.net

“David A. Black” dblack@wobblini.net schrieb im Newsbeitrag
news:Pine.LNX.4.44.0312191252330.28731-100000@wobblini…

Hi –

David A. Black wrote:

Anyway, Robert seemed to be suggesting that, of the two ways that have
been demonstrated, returning a single array is the ‘appropriate’ way
and that was what I wasn’t following.

A semantic issue. But then, isn’t everything?

The actual return is an array either way. Whether you then assign
it to one var or two is beyond the control or concern of the method.

I should have said: I thought Robert meant that saving to one variable
was the appropriate way – i.e., I thought he was saying that there was
something inherently bad about doing:

a,b = meth

and that one should always do:

all = meth

Aside from not having expressed clearly what I thought he meant, I
later realized that he hadn’t meant that anyway – he was talking
about the rhs (i.e., what’s appropriate is to do: return a,b).

:-))) Exactly.

Cheers & merry christmas!

robert
···

On Sat, 20 Dec 2003, Hal Fulton wrote: