concatenation of variadic ...

102 views
Skip to first unread message

Dave Miller

unread,
Feb 2, 2010, 4:55:35 PM2/2/10
to golang-nuts
I love variadics and use them a lot. I was surprised by this:

func foo (v ...) { Println ("foo: ", v) }
func main () { foo (1, 2, 3) }

which panics:
newValue ...
panic PC=0x2dfad0
reflect.newValue+0x2b2 /home/dave/go/src/pkg/reflect/value.go:1286
<snip>

there's an obvious workaround, but it seems like a kluge.

since this is legal for the compiler, shouldn't concatenation of
variadics be supported natively?

While I'm on the subject, is this the pattern for extracting arguments
from a variadic?

func foo (v ...) {
fields := reflect.NewValue(v).(*reflect.StructValue)
n := fields.NumField()
for i := 0; i < n; i++ {
field := fields.Field (i)
val := field.Interface()
doSomethingWith (val)
}
}

It seems like this could be provided by reflect, so that v could
behave like a slice, or even a chan.

While I'm on that subject, wouldn't is be really go-ish for slices to
have a chan behaviour?

Dave (in nz)

Ian Lance Taylor

unread,
Feb 2, 2010, 5:12:39 PM2/2/10
to Dave Miller, golang-nuts
Dave Miller <dave...@gmail.com> writes:

> I love variadics and use them a lot. I was surprised by this:
>
> func foo (v ...) { Println ("foo: ", v) }
> func main () { foo (1, 2, 3) }
>
> which panics:
> newValue ...
> panic PC=0x2dfad0
> reflect.newValue+0x2b2 /home/dave/go/src/pkg/reflect/value.go:1286
> <snip>
>
> there's an obvious workaround, but it seems like a kluge.

Please file an issue for this. I'm not quite sure what it should
print but it certainly shouldn't panic. Thanks.


> While I'm on the subject, is this the pattern for extracting arguments
> from a variadic?
>
> func foo (v ...) {
> fields := reflect.NewValue(v).(*reflect.StructValue)
> n := fields.NumField()
> for i := 0; i < n; i++ {
> field := fields.Field (i)
> val := field.Interface()
> doSomethingWith (val)
> }
> }
>
> It seems like this could be provided by reflect, so that v could
> behave like a slice, or even a chan.

Yes, that is the pattern. In tip we now have something simpler. You
can write "v ... T" and within the function v will be []T. You can
still take any value via "v ... interface{}".


> While I'm on that subject, wouldn't is be really go-ish for slices to
> have a chan behaviour?

I'm not sure what you're thinking of here.

Ian

Dave Miller

unread,
Feb 2, 2010, 5:47:19 PM2/2/10
to golang-nuts
On Feb 3, 11:12 am, Ian Lance Taylor <i...@google.com> wrote:
> Please file an issue for this.

Issue 584

> > While I'm on that subject, wouldn't is be really go-ish for slices to
> > have a chan behaviour?
>
> I'm not sure what you're thinking of here.

Just dreaming, of things like <- slice and slice <- .
But range is just fine, thanks.

Dave Miller

unread,
Feb 4, 2010, 1:45:49 AM2/4/10
to golang-nuts
I think I finally got it. After discarding lots of complaining post
I'd like to share what I've found, and ask if I'm understanding
correctly.

guidelines:

- do implementation in slice-land
- make variadic helpers to get into sliceland
- use ...T, not the untyped ..., which is ugly
- for untyped, use ...interface{}

example:

// implementation in slice-land
func sum(x int, ys []int) int {
if len(ys) == 0 { return x }
return x + sum(ys[0], ys[1:])
}

func sumList(xs []int) int { return sum(0, xs) }

// variadic helper
func Sum (xs ... int) int { return SumList (xs) }

To reuse a variadic like fmt.Sprintf inside a variadic, you *must* use
typed ..., eg:

// given
type person struct {
name string
/* other stuff */
}

// this will fail
func (p *person) Name(format string, v ...) {
p.name = fmt.Sprintf(format, v)
}

// this will work
func (p *person) Name(format string, v ...interface{}) {
p.name = fmt.Sprintf(format, v)
}

Is this correct and/or helpful?

Is there a case to be made for a reserved word "any" as a synonym for
the somewhat ugly "interface {}"?

-dave

Rob 'Commander' Pike

unread,
Feb 4, 2010, 4:45:25 AM2/4/10
to Dave Miller, golang-nuts

On 04/02/2010, at 5:45 PM, Dave Miller wrote:

> I think I finally got it. After discarding lots of complaining post
> I'd like to share what I've found, and ask if I'm understanding
> correctly.
>
> guidelines:
>
> - do implementation in slice-land

Yes. ... without a type will be deprecated.

> - make variadic helpers to get into sliceland

If necessary.

> - use ...T, not the untyped ..., which is ugly

Agreed.

> - for untyped, use ...interface{}

Yes.

>
> example:
>
> // implementation in slice-land
> func sum(x int, ys []int) int {
> if len(ys) == 0 { return x }
> return x + sum(ys[0], ys[1:])
> }
>
> func sumList(xs []int) int { return sum(0, xs) }
>
> // variadic helper
> func Sum (xs ... int) int { return SumList (xs) }
>
> To reuse a variadic like fmt.Sprintf inside a variadic, you *must* use
> typed ..., eg:
>
> // given
> type person struct {
> name string
> /* other stuff */
> }
>
> // this will fail
> func (p *person) Name(format string, v ...) {
> p.name = fmt.Sprintf(format, v)
> }
>
> // this will work
> func (p *person) Name(format string, v ...interface{}) {
> p.name = fmt.Sprintf(format, v)
> }
>
> Is this correct and/or helpful?

Correct and probably helpful to others.


>
> Is there a case to be made for a reserved word "any" as a synonym for
> the somewhat ugly "interface {}"?

We've talked about it but no.

-rob

Reply all
Reply to author
Forward
0 new messages