Re: [go-nuts] Union types mindset

2017-11-21 Thread 'Paulo Matos' via golang-nuts
Josh,

Thanks for the quick and clear reply. I was not aware of the dual return
form of type conversion.

Paulo Matos

On 21/11/17 00:05, Josh Humphries wrote:
> Hi, Paulo, 
> I think you're on the right track. The main thing to note is that the
> IsInstruction method isn't that useful. A concrete implementation of
> AsmEntry is an instruction if it implements the Instruction interface,
> so you shouldn't need a separate method.
> 
> So the example you provided looks like you plan to do something like
> this when visiting entries:
> 
> if entry.IsInstruction() {
> ins := entry.(Instruction)
> // do stuff with ins
> }
> 
> 
> But instead, use the dual-return form of type conversion:
> 
> if ins, ok := entry.(Instruction); ok {
>   // do stuff with ins
> }
> 
> 
> So the interfaces are just for holding the shared methods that all
> concrete types must implement. You don't need to add discriminator methods.
> 
> However, if you do want discriminator methods (useful for when a
> concrete type /happens to /implement an interface, like if it has
> methods with commonly overloaded/used signatures), you simply move the
> implementation down to concrete types.
> 
> So instead of this, which you noted will note compile:
> 
> func (i Interface) IsInstruction() bool {
> return true
> }
> 
> 
> You would have this in various places:
> 
> func (i *SomeConcreteInstruction) IsInstruction() bool {
> return true
> }
> 
> func (i *AnotherConcreteInstruction) IsInstruction() bool {
> return true
> }
> 
> // etc
> 
> 
> I hope that makes sense. ASTs for languages typically use this same
> pattern, so they are often reasonable examples to look at.
> 
> Here's the AST for the Go language: https://godoc.org/go/ast
> It has interfaces for Node, Decl, and Expression, each implemented by
> the various kinds of concrete AST nodes.
> 
> And here's
> another: 
> https://github.com/jhump/protoreflect/blob/50b1762cd8f6881d9e0e2f806b1275022695ceb9/desc/protoparse/ast.go#L29
> It's an AST for protocol buffers, implemented in Go. It has interfaces
> for node, terminalNode, and various kinds of declarations. It also uses
> type assertions for unnamed package variables
> <https://github.com/jhump/protoreflect/blob/50b1762cd8f6881d9e0e2f806b1275022695ceb9/desc/protoparse/ast.go#L75>
> to ensure that the various concrete types implement the expected
> interfaces (this is a common pattern in Go, to make sure any change to a
> concrete type to make it /not/ implement a particular interface result
> in a compile-time error).
> 
> 
> 
> 
> 
> *Josh Humphries*
> jh...@bluegosling.com <mailto:jh...@bluegosling.com>
> 
> On Mon, Nov 20, 2017 at 4:27 PM, 'Paulo Matos' via golang-nuts
> <golang-nuts@googlegroups.com <mailto:golang-nuts@googlegroups.com>> wrote:
> 
> Hello,
> 
> I am trying to write a simple assembler file parser. I just started
> developing in Go so I have the wrong mindset. I am keen to
> understand the best way to write something like this in Go.
> 
> An assembler file at first glance is a list of instructions,
> directives and labels. I know there are some other things but for
> the purposes of the example, that's enough.
> 
> So I have
> 
> type AsmFile list.List
> 
> The elements of the list are the problematic part. It's well... a union.
> I have read on this and I have seen suggested an interface approach,
> where you can then cast to the right type.
> 
> The entries of the list above are AsmEntry
> 
> type AsmEntry interface {
> IsInstruction() bool
> IsLabel() bool
> IsDirective() bool
> }
> 
> The problem is that I start then with:
> 
> type Label string
> 
> func (Label) IsLabel() bool {
> return true
> }
> 
> func (Label) IsInstruction() bool {
> return false
> }
> 
> -- same for IsDirective
> 
> but then an instruction should be an interface since there could be
> ArmInstruction, IntelInstruction, etc
> 
> type Instruction interface {
> GetMnemonic() string
> GetArgsLen() int
> GetArg(int) string
> }
> 
> func (Instruction) IsInstruction() bool {
> return true
> }
> 
> but this doesn't actually work because the receiver cannot be an
> instruction. This already looks like I am going on the wrong path.
> Any suggestions on how to design something like this with Go?
> 
> Kind regards,
> 
> 
> -- 
> Paulo Matos
> 
>

[go-nuts] Union types mindset

2017-11-20 Thread 'Paulo Matos' via golang-nuts
Hello,

I am trying to write a simple assembler file parser. I just started developing 
in Go so I have the wrong mindset. I am keen to understand the best way to 
write something like this in Go.

An assembler file at first glance is a list of instructions, directives and 
labels. I know there are some other things but for the purposes of the example, 
that's enough.

So I have

type AsmFile list.List

The elements of the list are the problematic part. It's well... a union.
I have read on this and I have seen suggested an interface approach, where you 
can then cast to the right type.

The entries of the list above are AsmEntry

type AsmEntry interface {
IsInstruction() bool
IsLabel() bool
IsDirective() bool
}

The problem is that I start then with:

type Label string

func (Label) IsLabel() bool {
return true
}

func (Label) IsInstruction() bool {
return false
}

-- same for IsDirective

but then an instruction should be an interface since there could be 
ArmInstruction, IntelInstruction, etc

type Instruction interface {
GetMnemonic() string
GetArgsLen() int
GetArg(int) string
}

func (Instruction) IsInstruction() bool {
return true
}

but this doesn't actually work because the receiver cannot be an instruction. 
This already looks like I am going on the wrong path.
Any suggestions on how to design something like this with Go?

Kind regards,


-- 
Paulo Matos

-- 
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+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.