discard returned values

1,568 views
Skip to first unread message

Ryanne Dolan

unread,
Nov 19, 2009, 4:51:03 AM11/19/09
to golang-nuts
I know that the following idioms can be used to discard extra return values:

val, _ := foo (); // throws away second return value
foo (); // throws away both return values

... but what if I want to use foo() in an expression?

if foo() > 0 ...

In particular, what if I want to chain calls to functions that return
more than one value?

v := a.plus(b).plus(c);

Is this possible? If not, may I suggest that Go adopt Lua's syntax,
such that '(' <exp> ')' always discards all but the first return
value?

if (foo ()) > 0 ...

v := (a.plus(b)).plus(C);

Thanks.
Ryanne

--
www.ryannedolan.info

Peter Bourgon

unread,
Nov 19, 2009, 4:55:30 AM11/19/09
to Ryanne Dolan, golang-nuts
> ... but what if I want to use foo() in an expression?
>
> if foo() > 0 ...

if x, _ := foo(); x>0 {
...

Ryanne Dolan

unread,
Nov 19, 2009, 11:25:55 AM11/19/09
to peter....@gmail.com, golang-nuts
Peter,

That's not what I mean. The if-statement has a special syntax to
handle this, but that isn't an expression per se. More examples:

result := product(a, product(b, c)); // doesn't compile if product
resturns two results
result := a.plus(b).plus(c); // same

This is a real problem (unless I am overlooking some strange syntax)
because I'd like to design my product and plus functions above to
perform error checking, but then they become useless in the above
contexts. All I can think of is to create a second function:

result := productEatError (a, productEatError(b, c));
result := a.plusEatError(b).plusEatError(c);

or even

result,_ := product (a, eatError (product(b,c));
result,_ := eatError(a.plus(b)).plus(c);

or, god forbid,

result := product (a, product (b,c))
if result.err {...

None of these are very elegant tho. Is there another way?

Thanks.
Ryanne

--
www.ryannedolan.info

Crwth

unread,
Nov 19, 2009, 11:41:30 AM11/19/09
to Ryanne Dolan, peter....@gmail.com, golang-nuts
If the idea of your product() and plus() functions is to be able to chain them, without caring about their secondary return values, then it seems to me that there shouldn't be a second return value.  If that second return value is for returned error values, then each call should, for correctness, be checking it, and not blindly chaining calls together (regardless of how nice and succinct it makes the code.

Not that I don't understand where you're coming from; I'm a Lua programmer myself, and enjoy the ability to discard extra values in that manner.  But I think Go, in this sense, is a different environment for the purposes of multiple return values, and if they're there, they should be read and handled appropriately.

--
  Crwth

Helmar

unread,
Nov 19, 2009, 11:54:09 AM11/19/09
to golang-nuts
Hi,

On Nov 19, 4:55 am, Peter Bourgon <peterbour...@gmail.com> wrote:
> > ... but what if I want to use foo() in an expression?
>
> > if foo() > 0 ...
>
> if x, _ := foo(); x>0 {
>  ...
>
>
>
> }

hacky bullshit. Why := or = is privileged about other operators? a, _
+ foo(x) would be nice, but I think this collides somewhere with
syntax.

That taking a simple expression to the if-statement is absolutely
nonsense and only invented to make answers like this possible. The
simple expression would not take much place more a line before. I've
tried this... It does not even increase readability that much. Well,
you can introduce a kind of scope to local variables with this. But
that is almost all - if not the most important thing why this exists.
The more interesting fact in reality is getting rid of something I do
not need from these multiple returns inside a normal expression.

-Helmar

philcolbourn

unread,
Nov 20, 2009, 6:05:02 AM11/20/09
to golang-nuts
Perhaps treat them as an array?

result := a.plus(b)[0].plus(c)[0];

or use their return value names somehow?

result := a.plus(b).x.plus(c).x;
result := a.plus(b)x.plus(c)x;



On Nov 20, 3:25 am, Ryanne Dolan <ryannedo...@gmail.com> wrote:
> Peter,
>
> That's not what I mean.  The if-statement has a special syntax to
> handle this, but that isn't an expression per se.  More examples:
>
> result := product(a, product(b, c)); // doesn't compile if product
> resturns two results
> result := a.plus(b).plus(c); // same
>
> This is a real problem (unless I am overlooking some strange syntax)
> because I'd like to design my product and plus functions above to
> perform error checking, but then they become useless in the above
> contexts.  All I can think of is to create a second function:
>
> result := productEatError (a, productEatError(b, c));
> result := a.plusEatError(b).plusEatError(c);
>
> or even
>
> result,_ := product (a, eatError (product(b,c));
> result,_ := eatError(a.plus(b)).plus(c);
>
> or, god forbid,
>
> result := product (a, product (b,c))
> if result.err {...
>
> None of these are very elegant tho.  Is there another way?
>
> Thanks.
> Ryanne
>
> --www.ryannedolan.info
>

John Asmuth

unread,
Nov 21, 2009, 1:41:25 AM11/21/09
to golang-nuts
Treating them as an array would make the grammar messy, I think. The
compiler would have to check whether what is being returned is an
array type or a multiple value type.

Naming them doesn't work, because 1) the return types aren't
necessarily named and 2) you could return a type that genuinely has
field x.

I am a compilers amateur, but I believe these kinds of ambiguities are
something the go team is trying to avoid.

If we were to do anything at all here, it would have to be something
that is not overloaded elsewhere.

a.plus(b)_0, a.plus(b)#0 come to mind. the _0 could work because, even
though _ is a valid character for identifiers, you would never have an
identifier immediately after a function call. there would be a ',' or
a ';' first. # because I don't think # is used anywhere else, though
perhaps it is with some obscure bit shifting notation...those always
get me.

I think either make intuitive sense - _0 because in latex that means
subscript zero, a common way of indexing vectors, and #0 because it's
the thing's #0th element.

For when a type *is* named, a.plus(b)_x or a.plus(b)#x could make
sense.

Could also do something like

a.plus(b)# for the first, a.plus(b)## for the second, etc, but that
could get ugly fast.

Though I think that a.plus(b)_<number or identifier> would be elegant
and fairly nice :)

Leaves the door open to things like

x, y = a.plus(b)_(0,2)

if there were three returned values and you wanted the first and last,
though I see this as less useful than a simple "extract one" scheme.

- John
Reply all
Reply to author
Forward
0 new messages