Mixins

1,268 views
Skip to first unread message

Jessta

unread,
Mar 19, 2010, 12:15:21 AM3/19/10
to Stanley Steel, golang-nuts
On Fri, Mar 19, 2010 at 1:02 PM, Stanley Steel <st...@kryas.com> wrote:
> Can we please end this discussion so I can stop getting spammed with ++/--
> noise?  Let's discuss GO's future support for mixins!

huh? doesn't go's interfaces already allow for 'mixins'?

--
=====================
http://jessta.id.au

Stanley Steel

unread,
Mar 19, 2010, 1:19:03 AM3/19/10
to Jessta, golang-nuts

On 3/18/10 10:15 PM, Jessta wrote:
> On Fri, Mar 19, 2010 at 1:02 PM, Stanley Steel<st...@kryas.com> wrote:
>
>> Can we please end this discussion so I can stop getting spammed with ++/--
>> noise? Let's discuss GO's future support for mixins!
>>
> huh? doesn't go's interfaces already allow for 'mixins'?
>
>
I am not super familiar with Go so please explain with a simple
example. A mixin is "like" an interface with implemented methods. So,
a developer could pull functionality into a type and gain the
functionality at little cost. A similar effect can be had in java with
class (A) that implements some functionality defined within an interface
(B), and then another class (C) can "mixin" the functionality of A
through composition and implement B by explicitly delegating to all of
B's defined functionality to A. You can do this in GO to the same
effect and if it is easier than I just stated, please educate me because
that would be killer. However, given the above, it is really just
delegation and not a mixin. In practice, delegation has elegance, but
is also verbose and naming collisions occur as it has some of the same
issues as multiple inheritance.

The main difference, to me, is only in the amount of typing involved.
If you have a class, like in Java, with 10 methods and you wanted to use
it like a mixin to delegate to it for its functionality, you have to
right 10 more methods each time you choose to do this. If the language
supported mixins directly, it could be a single statement. Basically, I
like to type as little as possible when I code. Mostly because my boss
kills my time making me fill out these ridiculous TPS reports.

st...@kryas.com

unread,
Mar 19, 2010, 2:03:46 AM3/19/10
to golang-nuts

Now that I think about it, I guess what I really want are "traits" and
not "mixins". Don't get me wrong, however, I would be fine with just
"mixins". Just looking for some additional power.

James Aguilar

unread,
Mar 19, 2010, 2:08:38 AM3/19/10
to golang-nuts
On Mar 18, 11:03 pm, "st...@kryas.com" <st...@kryas.com> wrote:
> Now that I think about it, I guess what I really want are "traits" and
> not "mixins".  Don't get me wrong, however, I would be fine with just
> "mixins".  Just looking for some additional power.

Seems like you can get that fairly easily just by merging another type
with your current type. E.g.

type Foo struct {
sync.Mutex
}

var f Foo
f.Lock()
f.Unlock()

So just by declaring the mutex type in Foo, you can now use Mutex
methods on it. If that's not the type of thing you're talking about,
then a more concrete example might be in order.

-- James

Sergei Skorobogatov

unread,
Mar 19, 2010, 2:16:43 AM3/19/10
to golang-nuts
Using mixins is a way to enhance single inheritance. And since Go
doesn't support inheritance at all, there is nothing to enhance :-)

As I understand, lack of inheritance allows to keep type system
simple, and Go language designers will never add this feature.

- Sergei

P.S. Limited mixin-like effect can be achieved by type embedding. That
is, if struct A embeds struct B, then all methods of B are also
methods of A.

Stanley Steel

unread,
Mar 19, 2010, 2:45:16 AM3/19/10
to James Aguilar, golang-nuts
Hey, thanks.  It is close to what I was discussing; though, I suspect it does not go as far as I was wanting (http://en.wikipedia.org/wiki/Trait_(computer_science)).  Is there a way to do that dynamically or hide some of the methods behind an interface?  I guess I should spend more time with the language and try it out.

What if I merged another type with some of the functions named the same?  Well, I answered that one myself:

Seems like you can get that fairly easily just by merging another type
with your current type. E.g.

type Foo struct {
  sync.Mutex
}

var f Foo
f.Lock()
f.Unlock()

So just by declaring the mutex type in Foo, you can now use Mutex
methods on it. If that's not the type of thing you're talking about,
then a more concrete example might be in order.

-- James

To unsubscribe from this group, send email to golang-nuts+unsubscribegooglegroups.com or reply to this email with the words "REMOVE ME" as the subject.

  
moz-screenshot.png

Stanley Steel

unread,
Mar 19, 2010, 3:08:51 AM3/19/10
to Stanley Steel, golang-nuts

On 3/19/10 12:45 AM, Stanley Steel wrote:
Hey, thanks.  It is close to what I was discussing; though, I suspect it does not go as far as I was wanting (http://en.wikipedia.org/wiki/Trait_(computer_science)).  Is there a way to do that dynamically or hide some of the methods behind an interface?  I guess I should spend more time with the language and try it out.

What if I merged another type with some of the functions named the same?  Well, I answered that one myself:

James Aguilar

unread,
Mar 19, 2010, 3:18:53 AM3/19/10
to golang-nuts
> [IMG]http://i828.photobucket.com/albums/zz201/sesteel/Screenshot2010-03-19...[/IMG]

I believe you can disambiguate by adding the type names (e.g.
f.Mutex.Lock()). But I assume that in other languages this would
result in some kind of conflict as well. In fact, if it didn't it
could only confuse users.

Btw, there is a go.pastie.org where you can put code snippets.

-- James

Steven

unread,
Mar 19, 2010, 4:06:42 PM3/19/10
to Stanley Steel, James Aguilar, golang-nuts
On Friday, March 19, 2010, Stanley Steel <st...@kryas.com> wrote:
>
>
>
>
>
>
> Hey, thanks.  It is close to what I was discussing; though, I suspect
> it does not go as far as I was wanting
> (http://en.wikipedia.org/wiki/Trait_(computer_science)).  Is there a
> way to do that dynamically or hide some of the methods behind an
> interface?  I guess I should spend more time with the language and try
> it out.
>
> What if I merged another type with some of the functions named the
> same?  Well, I answered that one myself:
>
>
>
> On 3/19/10 12:08 AM, James Aguilar wrote:
>
>   On Mar 18, 11:03 pm, "st...@kryas.com" <st...@kryas.com> <st...@kryas.com> <st...@kryas.com> wrote:
>
>
>     Now that I think about it, I guess what I really want are "traits" and
> not "mixins".  Don't get me wrong, however, I would be fine with just
> "mixins".  Just looking for some additional power.
>
>
>
> Seems like you can get that fairly easily just by merging another type
> with your current type. E.g.
>
> type Foo struct {
>   sync.Mutex
> }
>
> var f Foo
> f.Lock()
> f.Unlock()
>
> So just by declaring the mutex type in Foo, you can now use Mutex
> methods on it. If that's not the type of thing you're talking about,
> then a more concrete example might be in order.
>
> -- James
>
> To unsubscribe from this group, send email to golang-nuts+unsubscribegooglegroups.com or reply to this email with the words "REMOVE ME" as the subject.
>
>
>
>
>
>
>
>
> To unsubscribe from this group, send email to golang-nuts+unsubscribegooglegroups.com or reply to this email with the words "REMOVE ME" as the subject.
>

Yes, you can't call a method with multiple definitions at the same
depth. There's no way to pick one. You can specify which one you want
though (eg. t.Mutex.Lock()), and you can wrap embedded methods at the
upper level to choose which one you want called.

Once you start getting into method exclusion, it starts to get tricky.
You can embed an interface, but then you are responsible for
initializing that interface in a factory method to a type that
actually implements the methods.

type foo interface { Foo() int }
type T struct { foo }

For example, you could now embed a var of T in itself, and then a call
to foo would be unresolvable at runtime, but would pass compilation.

Also, an embeded type acts as it would normally, ie it calls it's own
methods, not overriden ones. It can, of course, contain an interface:

type mixin struct { self interface {Foo()} }

And only call methods on self, letting mixin's embedders override
methods by embedding themselves in mixin. Again, this requires a
factory function to make sure everything is linked up properly.

A better approach is just to break your functionality into unitary
components that you can combine as needed, which can greatly simplify
your design compared to trying to pick subsets of the functionality
out of larger types and having to override other parts for variety.

Stanley Steel

unread,
Mar 19, 2010, 5:20:10 PM3/19/10
to Steven, James Aguilar, golang-nuts
A better approach is just to break your functionality into unitary
components that you can combine as needed, which can greatly simplify
your design compared to trying to pick subsets of the functionality
out of larger types and having to override other parts for variety.

I don't necessarily disagree with you.  I am trying to conceptualize something simple like an observer pattern.  Let me preface by saying I work in Java 98% of the time; one of my least favorite things, literally, is writing listeners and event code.  I despise it.  So, I go to great lengths to make it as painless as possible because it is repetitive, verbose, and tedious.  So, I've created a set of generic components which I rely on about 80% of the time to provide this functionality.  What is the "Go" way to implement the observer pattern?  This relates to the mixin/trait discussion and how I've conceptualized wanting to solve this problem and my hope that it is more elegant in Go.

PS: Where in the documentation is embedding discussed as James Aguilar demonstrated in his earlier post?  I've scanned the language spec several times and must have missed it.

James Aguilar

unread,
Mar 19, 2010, 5:27:51 PM3/19/10
to Stanley Steel, Steven, golang-nuts

Look at the part that talks about "anonymous fields". I have not used them much but I'm guessing that you can only use them as easily as I initially suggested if the type to embed can be used without an initialization function. 

There is a similar language construct for interfaces, which you can see in the section on interface types.

-- James

Ian Lance Taylor

unread,
Mar 19, 2010, 5:30:55 PM3/19/10
to Stanley Steel, Steven, James Aguilar, golang-nuts
Stanley Steel <st...@kryas.com> writes:

> PS: Where in the documentation is embedding discussed as James Aguilar
> demonstrated in his earlier post? I've scanned the language spec several
> times and must have missed it.

http://golang.org/doc/effective_go.html#embedding
http://golang.org/doc/go_spec.html#Struct_types

Ian

Steven

unread,
Mar 19, 2010, 6:26:38 PM3/19/10
to Stanley Steel, James Aguilar, golang-nuts
On Fri, Mar 19, 2010 at 5:20 PM, Stanley Steel <st...@kryas.com> wrote:
A better approach is just to break your functionality into unitary
components that you can combine as needed, which can greatly simplify
your design compared to trying to pick subsets of the functionality
out of larger types and having to override other parts for variety.

I don't necessarily disagree with you.  I am trying to conceptualize something simple like an observer pattern.  Let me preface by saying I work in Java 98% of the time; one of my least favorite things, literally, is writing listeners and event code.  I despise it.  So, I go to great lengths to make it as painless as possible because it is repetitive, verbose, and tedious.  So, I've created a set of generic components which I rely on about 80% of the time to provide this functionality.  What is the "Go" way to implement the observer pattern?  This relates to the mixin/trait discussion and how I've conceptualized wanting to solve this problem and my hope that it is more elegant in Go.

There needs to be a bit more context to answer that question. How your code would be written would depend on the library you're using, what you're trying to do, and such. What are your main issues with event code?

Steven

unread,
Mar 19, 2010, 11:37:11 PM3/19/10
to st...@kryas.com, golang-nuts
On Fri, Mar 19, 2010 at 2:03 AM, st...@kryas.com <st...@kryas.com> wrote:
Now that I think about it, I guess what I really want are "traits" and
not "mixins".  Don't get me wrong, however, I would be fine with just
"mixins".  Just looking for some additional power.


The idea of traits can currently be achieved by passing a value to an interface parameter of a function. I find functions as a means of providing behaviour to a type not as compelling as methods, but that's just a bias I'd be told to get over :) In my mind, it would be perfectly logical to be able to do this via methods, but putting methods on interfaces poses many challenges when it comes to passing those interfaces around and casting between them[1],  and it change the meaning of an interface. Traits would bypass this, but since Go isn't object oriented, I don't see the devs wanting to implement such a feature (but I don't speak for them, so you never know). I find method syntax compelling though, and it has many advantages[2], so anything the helps with method reuse is definitely welcome.

Generics could get around this though. Depending on implementation, this may or may not be convenient. In a way, traits are a type building form of generics anyway. 

[1] If I have a type with method foo, and wrap it in an interface requiring foo with method bar, then wrap that in an interface requiring foo and bar, I now have two levels of boxing. If this kind of thing keeps happening, I'll end up with several layers of interfaces, impacting performance.

[2] Namespace (two types can have a method with the same name), no need to specify package (since this is already known from the type), separation of what is being acted on from what is being acted with, consistent interface (allow users to immediately see all the important actions you can do to a type, rather than having to dig through libraries to find out)...

Stanley Steel

unread,
Mar 20, 2010, 2:26:32 AM3/20/10
to Steven, golang-nuts
Hey, I appreciate the fact that you actually took the time understand what I was getting at.  You even listed some of the problems with what happens when you try to develop and compose functionality by faking traits or mixins.  You get name collisions, an ugly hierarchy of functionality, and fragile software.  Sounds a lot like multiple inheritance.  What I'm after is a way, as you stated, to reuse functionality while avoiding a mess.  It seems Go's intrinsic use of composition fits well with the concept of traits, but I suppose the concept would have to be implemented as part of the language to be truly useful.  I understand 50% of traits and 25% of Go; which means I 12.5% of what is required to talk intelligently on this subject.  So, rather than me droning on about something I only partly understand, here is "the" paper that provides an explanation of traits and why it may be better:

http://scg.unibe.ch/archive/papers/Scha02bTraits.pdf

All said, their idea is directed towards an object oriented language (Smalltalk).  Anything in Go would be of a slightly different flavor, obviously.  If I had a lot of experience using traits, I might have a stronger opinion on its inclusion; not that my opinion would matter.  I am interested in a better solution for code reuse, however.  Delegation still seems better than Go's concept of embedding as you can choose what behavior to expose and control how it gets called.  I just wish delegation wasn't so damn verbose...  :)


Steven

unread,
Mar 20, 2010, 3:12:07 AM3/20/10
to Stanley Steel, golang-nuts
I was reading that paper while I was composing my reply :) Its what led me to determine that I liked the idea. I really enjoy exploring those kinds of ideas.

Its also what led me to determine that all the benefits of traits are already provided in Go by packages, interfaces, and functions, except for the convenient method syntax, but without the added complexity. I like the convenient method syntax though I'm not sure its worth the complexity on its own.

But with the thought of functions providing this, and the prospect of generics in the future, what if there were a syntactically convenient way of doing the inverse of method expressions, i.e. take a function and pull its first parameter out as a receiver? Then with generics, you would write generic functions that you could do this with, and therefore would be able to be reused for any type, just like traits. Right now, if generics were added, that would look like (pretend generics showed up somewhere):

func (t Type) Do(a, b, c ,d e, f, g int) (h, i, j int) { return pkg.Do(t, a, b, c, d, e, f, g) }

But maybe there could be a way to just do a list, like:

func (t Type) graft { pkg.Do; pgk.Undo; pkg2.Rotate; flip pkg2.Flip; Group group }

(syntax demonstrative only)

Allowing you to just list the functions you want grafted onto your type. This doesn't really make sense without generics, since it would mean a circular dependency for anything out-of-package. You could still do it in-package though, but with limited usefulness. Or maybe it could work with interfaces, essentially allowing you to convert an interface general function into a generic (then specific) method. I haven't really thought this through, but I'm putting it out there. Essentially, I'm considering what it would look like to have convenient wrapping of functions as methods, with generics possibly involved somewhere along the line.
Reply all
Reply to author
Forward
0 new messages