Can I type assert a slice of interface values?
Asked Answered
C

2

24

I am trying to type assert from a []Node, to []Symbol. In my code, Symbol implements the Node interface.

Here is some surrounding code:

 43 func applyLambda(args []Node, env Env) Node {
 44     if len(args) > 2 {
 45         panic("invalid argument count")
 46     }
 47     fixed, rest := parseFormals(args.([]Symbol))
 48     return Func{
 49         Body: args[1],
 50         FixedVarNames: fixed,
 51         RestVarName: rest,
 52     }
 53 }

Here's the error I get:

./builtins.go:47: invalid type assertion: args.([]Symbol) (non-interface type []Node on left)

I'm sure there's a good reason for this. What's the best way to proceed?

Consumedly answered 7/5, 2012 at 8:0 Comment(0)
C
25

In saying x.(T) variable x should be of interface type, because only for variables of type interface dynamic type is not fixed. And while Node is an interface, []Node is not. A slice is a distinct, non-interface type. So it just doesn't make sense to assume a slice of interface values is an interface too.

Type Node has a clear definition in your code and thus is an interface. You have specified the list of methods for it. Type []Node isn't like that. What methods does it define?

I understand where your are coming from with this. It may be a useful shortcut, but just doesn't make sense. It's kind of like expecting syms.Method() to work when syms's type is []Symbol and Method is for Symbol.

Replacing line 47 with this code does what you want:

symbols := make([]Symbol, len(args))
for i, arg := range args { symbols[i] = arg.(Symbol) }
fixed, rest := parseFormals(symbols)
Clerk answered 7/5, 2012 at 8:49 Comment(3)
I do not agree with your sentense "So it just doesn't make sense to assume a slice of interface values is an interface too". Conversions are conversions - interfaces are interfaces. They are separate concepts (at least in my mind). Go authors could have decided to support conversions from []Node to []Symbol, but they didn't because it is too costly and such conversions aren't a common programming pattern. Theoretically, any conversion that does not entail a contradiction nor an issue makes sense - but language designers need to choose which conversions to put in the language.Shortwave
I can't say for sure what Go authors think about this matter, but I still think my assumption is true. You are right that this conversion is too costly, but I don't think that's the reason for making that illegal. As I said, in Go slice is a type. You can say type Nodes []Node. Is Nodes an interface type? No. So I see that's the reason we can't assert variables of type []Node. Would you like to do this discussion on the golang-nuts mailing list?Clerk
@Atom: The question doesn't ask about conversions; it asks about type assertionsDiastasis
S
6

Go does not allow this. You need to convert Node to Symbol individually.

The reason why it isn't allowed is that []Node and []Symbol have different representations, so the conversion would need to allocate memory for []Symbol.

Shortwave answered 7/5, 2012 at 8:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.