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)
> 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
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.
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
> 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