Alexey Veselovsky | 7 Aug 2012 23:56
Picon

How to satisfy this interface?

Hello.

I have basic interface:

type Node interface {
    Next() Node
}

And I have dummy struct that don't know anything about this interface:

type ListNode struct {
}
func (l ListNode) Next ListNode {
    return l
}

In my test function:

func test() {
    var l ListNode
    var n Node = l
}

compiler says:

cannot use l (type ListNode) as type Node in assignment:
        ListNode does not implement Node (wrong type for Next method)
                have Next() ListNode
                want Next() Node

(Continue reading)

Patrick Mylund Nielsen | 8 Aug 2012 00:16
Favicon
Gravatar

Re: How to satisfy this interface?

It should work if you make each Next func return a Node not FooNode or BarNode.

On Tue, Aug 7, 2012 at 11:56 PM, Alexey Veselovsky <alexey.veselovsky-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
Hello.

I have basic interface:

type Node interface {
    Next() Node
}

And I have dummy struct that don't know anything about this interface:

type ListNode struct {
}
func (l ListNode) Next ListNode {
    return l
}

In my test function:

func test() {
    var l ListNode
    var n Node = l
}

compiler says:

cannot use l (type ListNode) as type Node in assignment:
        ListNode does not implement Node (wrong type for Next method)
                have Next() ListNode
                want Next() Node

How ListNode can satisfy Node interface if when I implement ListNode I
don't know anything about Node interface?

(or how to write common interface for several simple types:

type ListNode struct {
}
func (l ListNode) Next ListNode {
    return l
}

type SomeOtherNode struct {
}
func (l SomeOtherNode) Next SomeOtherNode {
    return l
}

and so on)

Thanks, Alexey

Patrick Mylund Nielsen | 8 Aug 2012 00:21
Favicon
Gravatar

Re: How to satisfy this interface?

Sorry, just realized I misunderstood your premise, that the funcs can't "use" Node. AFAIK you can't do this. You could return an define Next as func Next() interface{} and type-assert, but why not just return a Node then? Howcome they can't know about Node if they are implementing it? I suspect there's a better approach.


On Wed, Aug 8, 2012 at 12:16 AM, Patrick Mylund Nielsen <patrick-5OwhuJu8WGN86Ms11P7pYQC/G2K4zDHf@public.gmane.org> wrote:
It should work if you make each Next func return a Node not FooNode or BarNode.


On Tue, Aug 7, 2012 at 11:56 PM, Alexey Veselovsky <alexey.veselovsky-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
Hello.

I have basic interface:

type Node interface {
    Next() Node
}

And I have dummy struct that don't know anything about this interface:

type ListNode struct {
}
func (l ListNode) Next ListNode {
    return l
}

In my test function:

func test() {
    var l ListNode
    var n Node = l
}

compiler says:

cannot use l (type ListNode) as type Node in assignment:
        ListNode does not implement Node (wrong type for Next method)
                have Next() ListNode
                want Next() Node

How ListNode can satisfy Node interface if when I implement ListNode I
don't know anything about Node interface?

(or how to write common interface for several simple types:

type ListNode struct {
}
func (l ListNode) Next ListNode {
    return l
}

type SomeOtherNode struct {
}
func (l SomeOtherNode) Next SomeOtherNode {
    return l
}

and so on)

Thanks, Alexey


Alexey Veselovsky | 8 Aug 2012 00:27
Picon

Re: How to satisfy this interface?

> Sorry, just realized I misunderstood your premise, that the funcs can't
> "use" Node. AFAIK you can't do this. You could return an define Next as func
> Next() interface{} and type-assert, but why not just return a Node then?
> Howcome they can't know about Node if they are implementing it? I suspect
> there's a better approach.

I just read FAQ:
http://golang.org/doc/go_faq.html#t_and_equal_interface and it seems
like it is really not possible.

I should change architecture of my application. Thanks.

PS. Waiting for templates/generics for Go :-)

Jan Mercl | 8 Aug 2012 07:02
Picon

Re: How to satisfy this interface?

On Tue, Aug 7, 2012 at 11:56 PM, Alexey Veselovsky
<alexey.veselovsky@...> wrote:
> I have basic interface:
>
> type Node interface {
>     Next() Node
> }
>
> And I have dummy struct that don't know anything about this interface:
>
> type ListNode struct {
> }
> func (l ListNode) Next ListNode {
>     return l
> }
>
> In my test function:
>
> func test() {
>     var l ListNode
>     var n Node = l
> }
>
> compiler says:
>
> cannot use l (type ListNode) as type Node in assignment:
>         ListNode does not implement Node (wrong type for Next method)
>                 have Next() ListNode
>                 want Next() Node
>
> How ListNode can satisfy Node interface if when I implement ListNode I
> don't know anything about Node interface?
>
> (or how to write common interface for several simple types:
>
> type ListNode struct {
> }
> func (l ListNode) Next ListNode {
>     return l
> }
>
> type SomeOtherNode struct {
> }
> func (l SomeOtherNode) Next SomeOtherNode {
>     return l
> }
>
> and so on)

I'm not sure if I understood the task correctly:
http://play.golang.org/p/iwWpyluJPP

-j

si guy | 8 Aug 2012 19:46
Picon

Re: How to satisfy this interface?

Presumably the Node interface is declared in another package and is not / cannot be imported (circular
dep?) so the type trying to implement it cannot have access to it. Interfaces are implemented by name so
this won't work... Is there a way to anonymously implement an interface? Perhaps re-declare it locally or something?

Patrick Mylund Nielsen | 8 Aug 2012 20:11
Favicon
Gravatar

Re: How to satisfy this interface?

Presumably the Node interface is declared in another package and is not / cannot be imported (circular dep?) 


Sounds like a design problem.

Is there a way to anonymously implement an interface? 

That is how Go interfaces work, right? There's no "implements." The Next function just doesn't have the correct type signature, so doesn't implement the desired interface.

On Wed, Aug 8, 2012 at 7:46 PM, si guy <sjwatt-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
Presumably the Node interface is declared in another package and is not / cannot be imported (circular dep?) so the type trying to implement it cannot have access to it. Interfaces are implemented by name so this won't work... Is there a way to anonymously implement an interface? Perhaps re-declare it locally or something?

si guy | 8 Aug 2012 20:17
Picon

Re: How to satisfy this interface?

Sorry, I worded that badly, I should have said: is there a way to implement a self referring interface
blindly? I.e. When the interface decl is not available?

>design problem
I agree, the simplest solution is to move the interface decl to a third package and import it where necessary.

Russ Cox | 10 Aug 2012 02:09
Favicon

Re: How to satisfy this interface?

On Wed, Aug 8, 2012 at 2:17 PM, si guy <sjwatt@...> wrote:
> Sorry, I worded that badly, I should have said: is there a way to implement a self referring interface
blindly? I.e. When the interface decl is not available?

No.

Scott Lawrence | 8 Aug 2012 07:10
Picon

Re: How to satisfy this interface? (fwd)

And... hit the wrong button. Below.

-- 
Scott Lawrence

---------- Forwarded message ----------
Date: Tue, 7 Aug 2012 22:09:51
From: Scott Lawrence <bytbox@...>
To: Jan Mercl <0xjnml@...>
Subject: Re: [go-nuts] How to satisfy this interface?

On Wed, 8 Aug 2012, Jan Mercl wrote:

> On Tue, Aug 7, 2012 at 11:56 PM, Alexey Veselovsky
> <alexey.veselovsky@...> wrote:
>> I have basic interface:
>> 
>> type Node interface {
>>     Next() Node
>> }
>> 
>> And I have dummy struct that don't know anything about this interface:
>> 
>> type ListNode struct {
>> }
>> func (l ListNode) Next ListNode {
>>     return l
>> }
>> 
>> In my test function:
>> 
>> func test() {
>>     var l ListNode
>>     var n Node = l
>> }
>> 
>> compiler says:
>> 
>> cannot use l (type ListNode) as type Node in assignment:
>>         ListNode does not implement Node (wrong type for Next method)
>>                 have Next() ListNode
>>                 want Next() Node
>> 
>> How ListNode can satisfy Node interface if when I implement ListNode I
>> don't know anything about Node interface?
>> 
>> (or how to write common interface for several simple types:
>> 
>> type ListNode struct {
>> }
>> func (l ListNode) Next ListNode {
>>     return l
>> }
>> 
>> type SomeOtherNode struct {
>> }
>> func (l SomeOtherNode) Next SomeOtherNode {
>>     return l
>> }
>> 
>> and so on)
> 
> I'm not sure if I understood the task correctly:
> http://play.golang.org/p/iwWpyluJPP
> 
> -j

I think the question can be better rephrased as follows. If I'm using a package 
with

     type ListNode struct{}
     func (l ListNode) Next() ListNode

and I want to create an interface `Node`, which ListNode implements, how can I 
do so?

And I believe the answer is, "you can't", without creating some sort of wrapper 
struct for ListNode.

--

-- 
Scott Lawrence

go version go1.0.2
Linux jagadai 3.4.7-1-ARCH #1 SMP PREEMPT Sun Jul 29 22:02:56 CEST 2012 x86_64 
GNU/Linux

Jan Mercl | 8 Aug 2012 07:23
Picon

Re: How to satisfy this interface? (fwd)

On Wed, Aug 8, 2012 at 7:10 AM, Scott Lawrence <bytbox@...> wrote:
> I think the question can be better rephrased as follows. If I'm using a
> package with
>
>     type ListNode struct{}
>     func (l ListNode) Next() ListNode
>
> and I want to create an interface `Node`, which ListNode implements, how can
> I do so?

So you are saying that having an interface type I, with method M,
returning type R and having a non-interface type [*]T, having method
M, returning type [*]T the question is how to attach to T another
equally named method M returning R (i.e. [*]T then satisfies I)?

I considered this for a moment, but ruled it out on the basis that I
must have misunderstood the question.

-j

Scott Lawrence | 8 Aug 2012 07:35
Picon

Re: How to satisfy this interface? (fwd)

On Wed, 8 Aug 2012, Jan Mercl wrote:

> On Wed, Aug 8, 2012 at 7:10 AM, Scott Lawrence <bytbox@...> wrote:
>> I think the question can be better rephrased as follows. If I'm using a
>> package with
>>
>>     type ListNode struct{}
>>     func (l ListNode) Next() ListNode
>>
>> and I want to create an interface `Node`, which ListNode implements, how can
>> I do so?
>
> So you are saying that having an interface type I, with method M,
> returning type R and having a non-interface type [*]T, having method
> M, returning type [*]T the question is how to attach to T another
> equally named method M returning R (i.e. [*]T then satisfies I)?

No.

An interface type I with method M returning type I. A concrete type T, method 
'M', returning type T.

More generally: http://play.golang.org/p/_Wxkur9SAq. The assignability rules 
require function arguments and return values to be identical, rather than the 
usual (arguments must be supertypes, return values subtypes).

IIRC, this is because the go compiler has to know at compile time how large 
arguments and return values passed around are going to be. Is there any reason 
the rules can't be relaxed for pointer types?

--

-- 
Scott Lawrence

go version go1.0.2
Linux jagadai 3.4.7-1-ARCH #1 SMP PREEMPT Sun Jul 29 22:02:56 CEST 2012 x86_64 GNU/Linux

Jan Mercl | 8 Aug 2012 08:21
Picon

Re: How to satisfy this interface? (fwd)

On Wed, Aug 8, 2012 at 7:35 AM, Scott Lawrence <bytbox@...> wrote:
> No.
>
> An interface type I with method M returning type I. A concrete type T,
> method 'M', returning type T.

No difference, that's just a special case where R happens to be I. The
properties (== problems) of the more general question still hold.

> More generally: http://play.golang.org/p/_Wxkur9SAq. The assignability rules
> require function arguments and return values to be identical, rather than
> the usual (arguments must be supertypes, return values subtypes).

IMO the problem is simpler. The signature of the function literal
doesn't conform to the declaration of f's (the variable 'f') type. No
supertypes, no subtypes (not even sure what it means in Go, have some
idea what it could perhaps mean for interface type) involved. Correct
is only: http://play.golang.org/p/rHNWODTGov.

> IIRC, this is because the go compiler has to know at compile time how large
> arguments and return values passed around are going to be. Is there any
> reason the rules can't be relaxed for pointer types?

I don't follow. I think you're somehow still overlooking that the
question answers itself immediately - no type can have more than one
method of any given name.

-j


Gmane