Question re fcns that return multiple values

120 views
Skip to first unread message

lgo...@gmail.com

unread,
Aug 6, 2019, 3:38:24 AM8/6/19
to golang-nuts
For f1 defined as func f1(k1, k2, k3 int) (x1, x2 int) {..} 
and f2 defined as func f2(x,y int)           (xR int)       {..} 

Why does the compiler complain about the call stmt 
f2 ( f1 (1,2,3)  )   ??

Adrian Ho

unread,
Aug 6, 2019, 4:00:46 AM8/6/19
to golan...@googlegroups.com
It shouldn't. What little you posted is perfectly legal in Go:
https://play.golang.org/p/CHx9_LQCCEx

Something else is wrong with your code, methinks.

--
Best Regards,
Adrian

Jesse McNelis

unread,
Aug 6, 2019, 4:01:04 AM8/6/19
to lgo...@gmail.com, golang-nuts
I'm not sure what you're asking.
The compiler doesn't complain about this.

lgo...@gmail.com

unread,
Aug 6, 2019, 2:07:53 PM8/6/19
to golang-nuts
Here a specific example:

The following compiles and runs as expected
m1x,m1y := ec.scalarMult(16,28,33)  
m2x,m2y := ec.scalarMult( 1,28,33)
rx,ry := ec.add (m1x,m1y, m2x, m2y)


However this stmt :    rx,ry= ec.add(ec.scalarMult(16,28,33), ec.scalarMult( 1,28,33))  gives the following compiler error ...

# command-line-arguments
.\ECurve.go:272:14: not enough arguments in call to ec.add
.\ECurve.go:272:28: multiple-value ec.scalarMult() in single-value context

Jan Mercl

unread,
Aug 6, 2019, 2:11:54 PM8/6/19
to lgo...@gmail.com, golang-nuts
On Tue, Aug 6, 2019 at 4:07 PM <lgo...@gmail.com> wrote:
>
> Here a specific example:
>
> The following compiles and runs as expected
> m1x,m1y := ec.scalarMult(16,28,33)
> m2x,m2y := ec.scalarMult( 1,28,33)
> rx,ry := ec.add (m1x,m1y, m2x, m2y)
>
>
> However this stmt : rx,ry= ec.add(ec.scalarMult(16,28,33), ec.scalarMult( 1,28,33)) gives the following compiler error ...
>
> # command-line-arguments
> .\ECurve.go:272:14: not enough arguments in call to ec.add
> .\ECurve.go:272:28: multiple-value ec.scalarMult() in single-value context

WAI, see https://golang.org/ref/spec#Calls

""""
As a special case, if the return values of a function or method g are
equal in number and individually assignable to the parameters of
another function or method f, then the call f(g(parameters_of_g)) will
invoke f after binding the return values of g to the parameters of f
in order. The call of f must contain no parameters other than the call
of g, and g must have at least one return value. If f has a final ...
parameter, it is assigned the return values of g that remain after
assignment of regular parameters.
""""

lgo...@gmail.com

unread,
Aug 6, 2019, 11:14:11 PM8/6/19
to golang-nuts
?? Am I wrong in saying that the statements I've submitted conform to "As a special case, if the return values..."


On Monday, August 5, 2019 at 11:38:24 PM UTC-4, L Godioleskky wrote:

Ian Lance Taylor

unread,
Aug 6, 2019, 11:26:46 PM8/6/19
to lgo...@gmail.com, golang-nuts
On Tue, Aug 6, 2019 at 4:14 PM <lgo...@gmail.com> wrote:
>
> ?? Am I wrong in saying that the statements I've submitted conform to "As a special case, if the return values..."

The special case applies to f(g()) only. It does not apply to f(g1(), g2()).

Ian


> On Monday, August 5, 2019 at 11:38:24 PM UTC-4, L Godioleskky wrote:
>>
>> For f1 defined as func f1(k1, k2, k3 int) (x1, x2 int) {..}
>> and f2 defined as func f2(x,y int) (xR int) {..}
>>
>> Why does the compiler complain about the call stmt
>> f2 ( f1 (1,2,3) ) ??
>
> --
> You received this message because you are subscribed to the Google Groups "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/d8cd287f-2a18-4143-8579-c92fdd6a3fa6%40googlegroups.com.

Adrian Ho

unread,
Aug 7, 2019, 4:44:52 AM8/7/19
to golan...@googlegroups.com
On 6/8/19 10:07 PM, lgo...@gmail.com wrote:
> Here a specific example:
>
> The following compiles and runs as expected
> m1x,m1y := ec.scalarMult(16,28,33)  
> m2x,m2y := ec.scalarMult( 1,28,33)
> rx,ry := ec.add (m1x,m1y, m2x, m2y)
>
>
> However this stmt :    rx,ry= ec.add(ec.scalarMult(16,28,33),
> ec.scalarMult( 1,28,33))  gives the following compiler error ...
>
> # command-line-arguments
> .\ECurve.go:272:14: not enough arguments in call to ec.add
> .\ECurve.go:272:28: multiple-value ec.scalarMult() in single-value context
>
This is a VERY different case than the overly-simplified example you
posted earlier.

Jan Mercl has already posted the part of the Go language spec that
mentions this, so I'll just note that this was raised almost 10 years
ago, and Rob Griesemer explained why it was a Bad Idea to allow it here:
https://github.com/golang/go/issues/973#issuecomment-142733515

--
Best Regards,
Adrian

lgo...@gmail.com

unread,
Aug 7, 2019, 1:45:18 PM8/7/19
to golang-nuts
f( g() ) compiles  when g returns exactly the number of args that f() requires, but if g() returns only 1/2 that number  f (g(), g() ) wont compile !! ...Is this not a Golang absurdity  ?? 


On Tuesday, August 6, 2019 at 7:26:46 PM UTC-4, Ian Lance Taylor wrote:
On Tue, Aug 6, 2019 at 4:14 PM <lgo...@gmail.com> wrote:
>
> ?? Am I wrong in saying that the statements I've submitted conform to "As a special case, if the return values..."

The special case applies to f(g()) only.  It does not apply to f(g1(), g2()).

Ian


> On Monday, August 5, 2019 at 11:38:24 PM UTC-4, L Godioleskky wrote:
>>
>> For f1 defined as func f1(k1, k2, k3 int) (x1, x2 int) {..}
>> and f2 defined as func f2(x,y int)           (xR int)       {..}
>>
>> Why does the compiler complain about the call stmt
>> f2 ( f1 (1,2,3)  )   ??
>
> --
> You received this message because you are subscribed to the Google Groups "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to golan...@googlegroups.com.

Ian Lance Taylor

unread,
Aug 7, 2019, 2:47:43 PM8/7/19
to lgo...@gmail.com, golang-nuts
On Wed, Aug 7, 2019 at 6:45 AM <lgo...@gmail.com> wrote:
>
> f( g() ) compiles when g returns exactly the number of args that f() requires, but if g() returns only 1/2 that number f (g(), g() ) wont compile !! ...Is this not a Golang absurdity ??

No. It avoids confusion. In case you missed Adrian's reply which was
sent to the list, I quote:

Jan Mercl has already posted the part of the Go language spec that
mentions this, so I'll just note that this was raised almost 10 years
ago, and Rob Griesemer explained why it was a Bad Idea to allow it here:
https://github.com/golang/go/issues/973#issuecomment-142733515

Ian

> On Tuesday, August 6, 2019 at 7:26:46 PM UTC-4, Ian Lance Taylor wrote:
>>
>> On Tue, Aug 6, 2019 at 4:14 PM <lgo...@gmail.com> wrote:
>> >
>> > ?? Am I wrong in saying that the statements I've submitted conform to "As a special case, if the return values..."
>>
>> The special case applies to f(g()) only. It does not apply to f(g1(), g2()).
>>
>> Ian
>>
>>
>> > On Monday, August 5, 2019 at 11:38:24 PM UTC-4, L Godioleskky wrote:
>> >>
>> >> For f1 defined as func f1(k1, k2, k3 int) (x1, x2 int) {..}
>> >> and f2 defined as func f2(x,y int) (xR int) {..}
>> >>
>> >> Why does the compiler complain about the call stmt
>> >> f2 ( f1 (1,2,3) ) ??
>> >
>> > --
>> > You received this message because you are subscribed to the Google Groups "golang-nuts" group.
>> > To unsubscribe from this group and stop receiving emails from it, send an email to golan...@googlegroups.com.
>> > To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/d8cd287f-2a18-4143-8579-c92fdd6a3fa6%40googlegroups.com.
>
> --
> You received this message because you are subscribed to the Google Groups "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/013d64ed-1048-4121-8930-bd25909ef96d%40googlegroups.com.

howar...@gmail.com

unread,
Aug 7, 2019, 3:10:10 PM8/7/19
to golang-nuts
On Wednesday, August 7, 2019 at 8:45:18 AM UTC-5, lgo...@gmail.com wrote:
f( g() ) compiles  when g returns exactly the number of args that f() requires, but if g() returns only 1/2 that number  f (g(), g() ) wont compile !! ...Is this not a Golang absurdity  ?? 


Eh. Certainly absurd from the perspective of a lot of languages, and frustrating when put up against the otherwise good support for duck-typing. But the sharp limitation of 'magic' in syntax and the emphasis on being explicit where there might be  ambiguity seems in line with Go's ethos to me.

At any rate, you can do almost this, if you really, really want to for some reason.

It would be f(h(g,g)) instead of f(g(),g()), but if you had some situation where you legitimately needed to make the call a lot, maybe it might be worth it over putting the variable collection in each call site.

On the whole, though, it really seems like trying to shoehorn a different language's behavior into Go, and maybe you might be better off just finding a different way to express the pattern.

For example, instead of returning x and y from your scalarmult(scale, x, y) function, you could use a Point struct.


type Point struct {
x, y int
}

func scalarMult(scale int, a Point) Point {
return Point{a.x*scale,a.y*scale}
}

func add(a Point, b Point) Point {
return Point{a.x+b.x,a.y+b.y}
}

func main() {
m1 := scalarMult(16,Point{28,33})  
m2 := scalarMult( 1,Point{28,33})
r := add(m1, m2)
fmt.Println(r)
}

{476 561}

Howard

Michel Levieux

unread,
Aug 7, 2019, 3:43:54 PM8/7/19
to golang-nuts
It avoids confusion AND silent errors. Imagine you have:

func f() (int, int)
func g() (int, int)
func h(int, int, int, int) int

And somewhere in your code this line appears:

v = h(f(), g())

But for some reason, someday you need to change your code and now your function f and g have the following signature:

f() int
g() (int, int, int)

Then if what you suggest was allowed, the line

v = h(f(), g())

would still compile --> h takes four arguments, and f and g have a total number of return values of 4. However, there has been a major change in the way things work: do you really want your compiler to say nothing and keep doing its thing? I don't think so. Moreover, in a real project, there's only a small chance f, g and h are in the same file (or package), which makes it even likelier that you will never see this (silent) error.

Hope this helps!

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/9efbd578-8258-4d5f-a47a-5ac72ea609aa%40googlegroups.com.

Robert Engels

unread,
Aug 7, 2019, 4:28:42 PM8/7/19
to Michel Levieux, golang-nuts
I’m not sure that is the best argument. If it was a major change most likely the return types have changed as well, especially if new values are added, and thus it still would not compile. 

Adrian Ho

unread,
Aug 7, 2019, 4:46:40 PM8/7/19
to golan...@googlegroups.com
On 7/8/19 9:44 PM, lgo...@gmail.com wrote:
> f( g() ) compiles  when g returns exactly the number of args that f()
> requires, but if g() returns only 1/2 that number  f (g(), g() ) wont
> compile !! ...Is this not a Golang absurdity  ??

On the contrary, it's a good example of Go's pragmatism, allowing some
relatively safe syntactic sugar without opening a Pandora's box of
complete generality.

To illustrate Rob Griesemer's point, in his comment that I linked to in
my earlier reply
(https://github.com/golang/go/issues/973#issuecomment-142733515),
consider the following package that's maintained by someone else (your
colleague or an Internet stranger):

===

package mu

func CalcDispersion (in []float64) (variance float64, stddev float64) {
... }

func CalcAvg (in []float64) (sma21 float64, ema21 float64) { ... }

===

Then you use it as follows, assuming a future Go version that allows
"spreading" of multi-valued function returns:

===

v, sd := mu.CalcDispersion(i)

sma, ema := mu.CalcAvg(i)

func delta (a, b float64) float64 { return a-b }

d1 := delta(mu.CalcDispersion(i))

d2 := delta(mu.CalcAvg(i))

func me (variance float64, stddev float64, sma21 float64, ema21 float64)
float64 { ... }

m := me(mu.Alpha(i), mu.Beta(i))

===

All well and fine, until one day, the package interface changes after
some discussion:

===

package mu

func CalcDispersion (in []float64) (variance float64, stddev float64,
range float64) { ... }

func CalcAvg (in []float64) (sma21 float64) { ... }

===

Yes, that's a breaking change, and the Go compiler helpfully screams at
you on every assignment statement ...except the last one. And since the
compiler was silent about that last line, you're almost certainly gonna
miss the HUGE logic error in it...and spend days scratching your head at
the absurd results your program throws up.

--
Best Regards,
Adrian

L Godioleskky

unread,
Aug 7, 2019, 11:25:48 PM8/7/19
to Adrian Ho, golang-nuts
OK ...I now see the wisdom of why Go does not allow my simple example...Thanks ALL for you help on this

--
You received this message because you are subscribed to a topic in the Google Groups "golang-nuts" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/golang-nuts/lFBWugE1nt0/unsubscribe.
To unsubscribe from this group and all its topics, send an email to golang-nuts...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/504b90aa-afea-02b7-dfd9-eabf9eace9dc%4003s.net.
Reply all
Reply to author
Forward
0 new messages