FAQ
Hi,

with the new MakeFunc, it is possible to make generic functions
and "attach" them to a struct, e.g.


      type S struct { F func(int,int) (int, int) }
      func Assign(ptr interface{}, field string, generic func(in
[]reflect.Value) []reflect.Value){
           fv := reflect.ValueOf(ptr).Elem()
           p := fv.FieldByName(field)
           v := reflect.MakeFunc(p.Type(), generic)
           p.Set(v)
      }

      func Swap(in []reflect.Value) []reflect.Value { return
[]reflect.Value{in[1],in[0]} }

      func main() {
           s := &S{}
           Assign(s, "F", Swap)
           fmt.Println(s.F(2,1))
      }

From the outside it looks as if s.F() was a method call.
However, it does not fullfill an interface, e.g.


      type I interface {
           F(int, int) (int, int)
      }


      func main() {
           s := &S{}
           Assign(s, "F", Swap)
           fmt.Println(s.F(2,1))
           var i I
           i = s
      }

results in:

S.F is a field, not a method
cannot use s (type *S) as type I in assignment:
  *S does not implement I (missing F method)

(see http://play.golang.org/p/ROYBLxr7Qv)

Now the question to the language implementors:
--------------------------------------------------------------------

Would it require a major effort to allow fields of structs that are
functions to
fullfill an interface that requires a method with the same name and
signature?

------------------------------------------------------------------------------------------------------

That would be a very powerful combination. Even the struct itself could be
passed
in via closure, e.g.

      func AddX(i interface{}) func (in []reflect.Value) []reflect.Value {
           return func (in []reflect.Value) []reflect.Value {
                v := in[0].Int() +
reflect.ValueOf(i).Elem().FieldByName("X").Int()
                return []reflect.Value{reflect.ValueOf(v)}
           }
      }

      type S1 struct {
           Add func(int) (int64)
           X int
      }

      func main() {
           s := &S1{X: 2}
           Assign(s, "Add", AddX(s))
           fmt.Println(s.Add(3))
      }

(see http://play.golang.org/p/Q3P1vDSAzl)

Regards

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

Search Discussions

  • Kyle Lemons at May 24, 2013 at 11:50 pm
    That is an interesting question, and one I've pondered on and off.

    I can think of two implementation approaches:

    (1)
    Give every struct value its own method table. When there is a func field,
    it is added to the method table but the field points to the empty space in
    the table. Assigning to the field updates the method table.

    This is a radical departure from the way things work now, where structs are
    only as big as the values inside them. The changes required would be
    widespread and invasive.

    (2)
    Generate a wrapper method with a mangled name that calls the function.
      When checking a type for interface compliance and a function is missing,
    look for its mangled name as well.

    This is also a pretty major departure, and it would slow down every
    negative interface check. The changes would be reasonably focused, but
    still pretty hacky.


    It's possible that there are more ways, but neither of these get me
    excited. You can accomplish the moral equivalent of #2 by making your own
    wrapper.

    On Fri, May 24, 2013 at 4:42 PM, meta keule wrote:

    Hi,

    with the new MakeFunc, it is possible to make generic functions
    and "attach" them to a struct, e.g.


    type S struct { F func(int,int) (int, int) }
    func Assign(ptr interface{}, field string, generic func(in
    []reflect.Value) []reflect.Value){
    fv := reflect.ValueOf(ptr).Elem()
    p := fv.FieldByName(field)
    v := reflect.MakeFunc(p.Type(), generic)
    p.Set(v)
    }

    func Swap(in []reflect.Value) []reflect.Value { return
    []reflect.Value{in[1],in[0]} }

    func main() {
    s := &S{}
    Assign(s, "F", Swap)
    fmt.Println(s.F(2,1))
    }

    From the outside it looks as if s.F() was a method call.
    However, it does not fullfill an interface, e.g.


    type I interface {
    F(int, int) (int, int)
    }


    func main() {
    s := &S{}
    Assign(s, "F", Swap)
    fmt.Println(s.F(2,1))
    var i I
    i = s
    }

    results in:

    S.F is a field, not a method
    cannot use s (type *S) as type I in assignment:
    *S does not implement I (missing F method)

    (see http://play.golang.org/p/ROYBLxr7Qv)

    Now the question to the language implementors:
    --------------------------------------------------------------------

    Would it require a major effort to allow fields of structs that are
    functions to
    fullfill an interface that requires a method with the same name and
    signature?


    ------------------------------------------------------------------------------------------------------

    That would be a very powerful combination. Even the struct itself could be
    passed
    in via closure, e.g.

    func AddX(i interface{}) func (in []reflect.Value) []reflect.Value {
    return func (in []reflect.Value) []reflect.Value {
    v := in[0].Int() +
    reflect.ValueOf(i).Elem().FieldByName("X").Int()
    return []reflect.Value{reflect.ValueOf(v)}
    }
    }

    type S1 struct {
    Add func(int) (int64)
    X int
    }

    func main() {
    s := &S1{X: 2}
    Assign(s, "Add", AddX(s))
    fmt.Println(s.Add(3))
    }

    (see http://play.golang.org/p/Q3P1vDSAzl)

    Regards

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

    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Meta keule at May 25, 2013 at 12:19 am
    Why not change the internal representation of the names of the struct
    fields and make a real method for every field that has
    a function as value (with the same signature) and that calls the function
    in the struct field.

    E.g.

    a struct field would now internally be presented with an @ at the end.
    So the parser finds

    S.Name or S.Name = ....

    and replaces it with

    S.Name@ and S.Name@ = ....

    (since @ is not allowed in fieldnames there is no conflict).

    Method calls on the other hand stay unaffected.

    This way we should only have a little more work on the build of the
    libraries but no runtime delay since
    the 1:1 method to field function call could be optimized away (I guess).

    Am Samstag, 25. Mai 2013 01:50:28 UTC+2 schrieb Kyle Lemons:
    That is an interesting question, and one I've pondered on and off.

    I can think of two implementation approaches:

    (1)
    Give every struct value its own method table. When there is a func field,
    it is added to the method table but the field points to the empty space in
    the table. Assigning to the field updates the method table.

    This is a radical departure from the way things work now, where structs
    are only as big as the values inside them. The changes required would be
    widespread and invasive.

    (2)
    Generate a wrapper method with a mangled name that calls the function.
    When checking a type for interface compliance and a function is missing,
    look for its mangled name as well.

    This is also a pretty major departure, and it would slow down every
    negative interface check. The changes would be reasonably focused, but
    still pretty hacky.


    It's possible that there are more ways, but neither of these get me
    excited. You can accomplish the moral equivalent of #2 by making your own
    wrapper.


    On Fri, May 24, 2013 at 4:42 PM, meta keule <marcre...@googlemail.com<javascript:>
    wrote:
    Hi,

    with the new MakeFunc, it is possible to make generic functions
    and "attach" them to a struct, e.g.


    type S struct { F func(int,int) (int, int) }
    func Assign(ptr interface{}, field string, generic func(in
    []reflect.Value) []reflect.Value){
    fv := reflect.ValueOf(ptr).Elem()
    p := fv.FieldByName(field)
    v := reflect.MakeFunc(p.Type(), generic)
    p.Set(v)
    }

    func Swap(in []reflect.Value) []reflect.Value { return
    []reflect.Value{in[1],in[0]} }

    func main() {
    s := &S{}
    Assign(s, "F", Swap)
    fmt.Println(s.F(2,1))
    }

    From the outside it looks as if s.F() was a method call.
    However, it does not fullfill an interface, e.g.


    type I interface {
    F(int, int) (int, int)
    }


    func main() {
    s := &S{}
    Assign(s, "F", Swap)
    fmt.Println(s.F(2,1))
    var i I
    i = s
    }

    results in:

    S.F is a field, not a method
    cannot use s (type *S) as type I in assignment:
    *S does not implement I (missing F method)

    (see http://play.golang.org/p/ROYBLxr7Qv)

    Now the question to the language implementors:
    --------------------------------------------------------------------

    Would it require a major effort to allow fields of structs that are
    functions to
    fullfill an interface that requires a method with the same name and
    signature?


    ------------------------------------------------------------------------------------------------------

    That would be a very powerful combination. Even the struct itself could
    be passed
    in via closure, e.g.

    func AddX(i interface{}) func (in []reflect.Value) []reflect.Value
    {
    return func (in []reflect.Value) []reflect.Value {
    v := in[0].Int() +
    reflect.ValueOf(i).Elem().FieldByName("X").Int()
    return []reflect.Value{reflect.ValueOf(v)}
    }
    }

    type S1 struct {
    Add func(int) (int64)
    X int
    }

    func main() {
    s := &S1{X: 2}
    Assign(s, "Add", AddX(s))
    fmt.Println(s.Add(3))
    }

    (see http://play.golang.org/p/Q3P1vDSAzl)

    Regards

    --
    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...@googlegroups.com <javascript:>.
    For more options, visit https://groups.google.com/groups/opt_out.

    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Kyle Lemons at May 25, 2013 at 1:24 am
    That's just a variation on suggestion (2), except you're mangling the field
    names and making the symbol table and the debug experience more "weird."
      You still need to generate a wrapper function for all func fields. Again,
    I don't see what the benefit is over just writing the wrappers yourself;
    it's nice and explicit and everyone can tell what's going on.

    On Fri, May 24, 2013 at 5:19 PM, meta keule wrote:

    Why not change the internal representation of the names of the struct
    fields and make a real method for every field that has
    a function as value (with the same signature) and that calls the function
    in the struct field.

    E.g.

    a struct field would now internally be presented with an @ at the end.
    So the parser finds

    S.Name or S.Name = ....

    and replaces it with

    S.Name@ and S.Name@ = ....

    (since @ is not allowed in fieldnames there is no conflict).

    Method calls on the other hand stay unaffected.

    This way we should only have a little more work on the build of the
    libraries but no runtime delay since
    the 1:1 method to field function call could be optimized away (I guess).

    Am Samstag, 25. Mai 2013 01:50:28 UTC+2 schrieb Kyle Lemons:
    That is an interesting question, and one I've pondered on and off.

    I can think of two implementation approaches:

    (1)
    Give every struct value its own method table. When there is a func
    field, it is added to the method table but the field points to the empty
    space in the table. Assigning to the field updates the method table.

    This is a radical departure from the way things work now, where structs
    are only as big as the values inside them. The changes required would be
    widespread and invasive.

    (2)
    Generate a wrapper method with a mangled name that calls the function.
    When checking a type for interface compliance and a function is missing,
    look for its mangled name as well.

    This is also a pretty major departure, and it would slow down every
    negative interface check. The changes would be reasonably focused, but
    still pretty hacky.


    It's possible that there are more ways, but neither of these get me
    excited. You can accomplish the moral equivalent of #2 by making your own
    wrapper.

    On Fri, May 24, 2013 at 4:42 PM, meta keule wrote:

    Hi,

    with the new MakeFunc, it is possible to make generic functions
    and "attach" them to a struct, e.g.


    type S struct { F func(int,int) (int, int) }
    func Assign(ptr interface{}, field string, generic func(in
    []reflect.Value) []reflect.Value){
    fv := reflect.ValueOf(ptr).Elem()
    p := fv.FieldByName(field)
    v := reflect.MakeFunc(p.Type(), generic)
    p.Set(v)
    }

    func Swap(in []reflect.Value) []reflect.Value { return
    []reflect.Value{in[1],in[0]} }

    func main() {
    s := &S{}
    Assign(s, "F", Swap)
    fmt.Println(s.F(2,1))
    }

    From the outside it looks as if s.F() was a method call.
    However, it does not fullfill an interface, e.g.


    type I interface {
    F(int, int) (int, int)
    }


    func main() {
    s := &S{}
    Assign(s, "F", Swap)
    fmt.Println(s.F(2,1))
    var i I
    i = s
    }

    results in:

    S.F is a field, not a method
    cannot use s (type *S) as type I in assignment:
    *S does not implement I (missing F method)

    (see http://play.golang.org/p/**ROYBLxr7Qv<http://play.golang.org/p/ROYBLxr7Qv>
    )

    Now the question to the language implementors:
    ------------------------------**------------------------------**--------

    Would it require a major effort to allow fields of structs that are
    functions to
    fullfill an interface that requires a method with the same name and
    signature?

    ------------------------------**------------------------------**
    ------------------------------**------------

    That would be a very powerful combination. Even the struct itself could
    be passed
    in via closure, e.g.

    func AddX(i interface{}) func (in []reflect.Value) []reflect.Value
    {
    return func (in []reflect.Value) []reflect.Value {
    v := in[0].Int() + reflect.ValueOf(i).Elem().**
    FieldByName("X").Int()
    return []reflect.Value{reflect.**ValueOf(v)}
    }
    }

    type S1 struct {
    Add func(int) (int64)
    X int
    }

    func main() {
    s := &S1{X: 2}
    Assign(s, "Add", AddX(s))
    fmt.Println(s.Add(3))
    }

    (see http://play.golang.org/p/**Q3P1vDSAzl<http://play.golang.org/p/Q3P1vDSAzl>
    )

    Regards

    --
    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...@**googlegroups.com.

    For more options, visit https://groups.google.com/**groups/opt_out<https://groups.google.com/groups/opt_out>
    .

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

    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Meta keule at May 25, 2013 at 8:37 am
    Well, it is really just for struct fields and it could be well documented.
    On the other hand, the current behaviour is much less
    obvious, since it is inconsistent (I can call it like a method, but it is
    none) and it is weird, if someone sees method usage in
    code, try to wrap it in an interface and... bam! Also it requires deeply
    understanding of the language in order to understand, why
    it does not work. To expect that understanding from a person who is
    debugging is more appropriate, since
    a programming languag is an interface to a programmer and the deeper you
    dig, the more you need to know.

    The difference to suggestion (2) is that this mangling has to be done only
    once for each struct and at compile time and
    not again if you import a package.

    Am Samstag, 25. Mai 2013 03:24:32 UTC+2 schrieb Kyle Lemons:
    That's just a variation on suggestion (2), except you're mangling the
    field names and making the symbol table and the debug experience more
    "weird." You still need to generate a wrapper function for all func
    fields. Again, I don't see what the benefit is over just writing the
    wrappers yourself; it's nice and explicit and everyone can tell what's
    going on.


    On Fri, May 24, 2013 at 5:19 PM, meta keule <marcre...@googlemail.com<javascript:>
    wrote:
    Why not change the internal representation of the names of the struct
    fields and make a real method for every field that has
    a function as value (with the same signature) and that calls the function
    in the struct field.

    E.g.

    a struct field would now internally be presented with an @ at the end.
    So the parser finds

    S.Name or S.Name = ....

    and replaces it with

    S.Name@ and S.Name@ = ....

    (since @ is not allowed in fieldnames there is no conflict).

    Method calls on the other hand stay unaffected.

    This way we should only have a little more work on the build of the
    libraries but no runtime delay since
    the 1:1 method to field function call could be optimized away (I guess).

    Am Samstag, 25. Mai 2013 01:50:28 UTC+2 schrieb Kyle Lemons:
    That is an interesting question, and one I've pondered on and off.

    I can think of two implementation approaches:

    (1)
    Give every struct value its own method table. When there is a func
    field, it is added to the method table but the field points to the empty
    space in the table. Assigning to the field updates the method table.

    This is a radical departure from the way things work now, where structs
    are only as big as the values inside them. The changes required would be
    widespread and invasive.

    (2)
    Generate a wrapper method with a mangled name that calls the function.
    When checking a type for interface compliance and a function is missing,
    look for its mangled name as well.

    This is also a pretty major departure, and it would slow down every
    negative interface check. The changes would be reasonably focused, but
    still pretty hacky.


    It's possible that there are more ways, but neither of these get me
    excited. You can accomplish the moral equivalent of #2 by making your own
    wrapper.

    On Fri, May 24, 2013 at 4:42 PM, meta keule wrote:

    Hi,

    with the new MakeFunc, it is possible to make generic functions
    and "attach" them to a struct, e.g.


    type S struct { F func(int,int) (int, int) }
    func Assign(ptr interface{}, field string, generic func(in
    []reflect.Value) []reflect.Value){
    fv := reflect.ValueOf(ptr).Elem()
    p := fv.FieldByName(field)
    v := reflect.MakeFunc(p.Type(), generic)
    p.Set(v)
    }

    func Swap(in []reflect.Value) []reflect.Value { return
    []reflect.Value{in[1],in[0]} }

    func main() {
    s := &S{}
    Assign(s, "F", Swap)
    fmt.Println(s.F(2,1))
    }

    From the outside it looks as if s.F() was a method call.
    However, it does not fullfill an interface, e.g.


    type I interface {
    F(int, int) (int, int)
    }


    func main() {
    s := &S{}
    Assign(s, "F", Swap)
    fmt.Println(s.F(2,1))
    var i I
    i = s
    }

    results in:

    S.F is a field, not a method
    cannot use s (type *S) as type I in assignment:
    *S does not implement I (missing F method)

    (see http://play.golang.org/p/**ROYBLxr7Qv<http://play.golang.org/p/ROYBLxr7Qv>
    )

    Now the question to the language implementors:
    ------------------------------**------------------------------**
    --------

    Would it require a major effort to allow fields of structs that are
    functions to
    fullfill an interface that requires a method with the same name and
    signature?

    ------------------------------**------------------------------**
    ------------------------------**------------

    That would be a very powerful combination. Even the struct itself could
    be passed
    in via closure, e.g.

    func AddX(i interface{}) func (in []reflect.Value)
    []reflect.Value {
    return func (in []reflect.Value) []reflect.Value {
    v := in[0].Int() + reflect.ValueOf(i).Elem().**
    FieldByName("X").Int()
    return []reflect.Value{reflect.**ValueOf(v)}
    }
    }

    type S1 struct {
    Add func(int) (int64)
    X int
    }

    func main() {
    s := &S1{X: 2}
    Assign(s, "Add", AddX(s))
    fmt.Println(s.Add(3))
    }

    (see http://play.golang.org/p/**Q3P1vDSAzl<http://play.golang.org/p/Q3P1vDSAzl>
    )

    Regards

    --
    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...@**googlegroups.com.

    For more options, visit https://groups.google.com/**groups/opt_out<https://groups.google.com/groups/opt_out>
    .

    --
    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...@googlegroups.com <javascript:>.
    For more options, visit https://groups.google.com/groups/opt_out.

    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Ian Lance Taylor at May 25, 2013 at 5:03 am

    On Fri, May 24, 2013 at 4:42 PM, meta keule wrote:
    with the new MakeFunc, it is possible to make generic functions
    and "attach" them to a struct, e.g.


    type S struct { F func(int,int) (int, int) }
    func Assign(ptr interface{}, field string, generic func(in
    []reflect.Value) []reflect.Value){
    fv := reflect.ValueOf(ptr).Elem()
    p := fv.FieldByName(field)
    v := reflect.MakeFunc(p.Type(), generic)
    p.Set(v)
    }

    func Swap(in []reflect.Value) []reflect.Value { return
    []reflect.Value{in[1],in[0]} }

    func main() {
    s := &S{}
    Assign(s, "F", Swap)
    fmt.Println(s.F(2,1))
    }

    From the outside it looks as if s.F() was a method call.
    However, it does not fullfill an interface, e.g.


    type I interface {
    F(int, int) (int, int)
    }


    func main() {
    s := &S{}
    Assign(s, "F", Swap)
    fmt.Println(s.F(2,1))
    var i I
    i = s
    }

    results in:

    S.F is a field, not a method
    cannot use s (type *S) as type I in assignment:
    *S does not implement I (missing F method)

    (see http://play.golang.org/p/ROYBLxr7Qv)

    Now the question to the language implementors:
    --------------------------------------------------------------------

    Would it require a major effort to allow fields of structs that are
    functions to
    fullfill an interface that requires a method with the same name and
    signature?

    ------------------------------------------------------------------------------------------------------
    It's interesting, but, it seems to me that you could write

    type S struct { F1 func(int,int) (int, int) }
    func (s S) F(a, b int) (int, int) { return s.F1(a, b) }

    and then proceed just as you outline. That is, your proposal saves
    writing one boilerplate method. Boilerplate is not good, but on the
    other hand this doesn't seem like a technique that will be widely
    used.

    Ian

    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Meta keule at May 25, 2013 at 8:28 am
    Clearly is is a matter of comfort.
    If you want to write a library that predefines some generic functions and
    consumes them via interface,
    it is a matter of requiring every instance to have the double effort for no
    matter, but a weird limitation of the language.

    Am Samstag, 25. Mai 2013 07:03:37 UTC+2 schrieb Ian Lance Taylor:
    On Fri, May 24, 2013 at 4:42 PM, meta keule wrote:

    with the new MakeFunc, it is possible to make generic functions
    and "attach" them to a struct, e.g.


    type S struct { F func(int,int) (int, int) }
    func Assign(ptr interface{}, field string, generic func(in
    []reflect.Value) []reflect.Value){
    fv := reflect.ValueOf(ptr).Elem()
    p := fv.FieldByName(field)
    v := reflect.MakeFunc(p.Type(), generic)
    p.Set(v)
    }

    func Swap(in []reflect.Value) []reflect.Value { return
    []reflect.Value{in[1],in[0]} }

    func main() {
    s := &S{}
    Assign(s, "F", Swap)
    fmt.Println(s.F(2,1))
    }

    From the outside it looks as if s.F() was a method call.
    However, it does not fullfill an interface, e.g.


    type I interface {
    F(int, int) (int, int)
    }


    func main() {
    s := &S{}
    Assign(s, "F", Swap)
    fmt.Println(s.F(2,1))
    var i I
    i = s
    }

    results in:

    S.F is a field, not a method
    cannot use s (type *S) as type I in assignment:
    *S does not implement I (missing F method)

    (see http://play.golang.org/p/ROYBLxr7Qv)

    Now the question to the language implementors:
    --------------------------------------------------------------------

    Would it require a major effort to allow fields of structs that are
    functions to
    fullfill an interface that requires a method with the same name and
    signature?
    ------------------------------------------------------------------------------------------------------


    It's interesting, but, it seems to me that you could write

    type S struct { F1 func(int,int) (int, int) }
    func (s S) F(a, b int) (int, int) { return s.F1(a, b) }

    and then proceed just as you outline. That is, your proposal saves
    writing one boilerplate method. Boilerplate is not good, but on the
    other hand this doesn't seem like a technique that will be widely
    used.

    Ian
    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Carlos Castillo at May 26, 2013 at 1:52 am
    I find your definition of comfort somewhat suspicious.

    In your orignal post you have a monstrosity of a function (AddX) which uses
    a heavy amount of reflection to create a function to process an arbitrary
    struct, pull out it's first field (assuming that what you want is there),
    assume it's an integer (runtime panic otherwise), pull out the second
    argument (an integer) add them up (result is now int64 because
    reflect.Value.Int() always returns int64), and return the result as a
    reflect.Value. In the playground code, you then convert the generated
    function into an appropriate type using reflect.MakeFunc to attach it to
    the object. Only now does your feature come into play, saving the need to
    type a one line method definition.

    Your solution is slower, more brittle, and less type-safe then
    http://play.golang.org/p/9obIw9R1B2, where I only need additionally a
    single line method to add a new field/method, and a simple anonymous
    function to implement it.

    I see little benefit to the reflective code in AddX, other then it can be
    applied to any struct with the first field being an int type instead of
    having one line of "boilerplate" that allows the field function to be much
    simpler, and can use any field of the struct (by name, so it can be moved
    in the struct), with the correct and exact type.

    Also, your example seems to make the dangerous assumption that a field of
    type func(x int) int64 is actually supposed to be assigned a func(s S1, x
    int) int64 (or a func(s *S1, x int) int64.) I know that this is to pass the
    receiver as part of the method call, but many people might not realize
    this, and get new (possibly quite obscure) errors. Resolving this 3 to 1
    mapping (two method signatures, and the straight function one), seems like
    a much bigger problem and far more programmer headaches than the initial
    problem that val.Field() is not a method call despite looking like one, and
    is spelled out in the package documentation.
    On Saturday, May 25, 2013 1:28:16 AM UTC-7, meta keule wrote:

    Clearly is is a matter of comfort.
    If you want to write a library that predefines some generic functions and
    consumes them via interface,
    it is a matter of requiring every instance to have the double effort for
    no matter, but a weird limitation of the language.

    Am Samstag, 25. Mai 2013 07:03:37 UTC+2 schrieb Ian Lance Taylor:
    On Fri, May 24, 2013 at 4:42 PM, meta keule <marcre...@googlemail.com>
    wrote:
    with the new MakeFunc, it is possible to make generic functions
    and "attach" them to a struct, e.g.


    type S struct { F func(int,int) (int, int) }
    func Assign(ptr interface{}, field string, generic func(in
    []reflect.Value) []reflect.Value){
    fv := reflect.ValueOf(ptr).Elem()
    p := fv.FieldByName(field)
    v := reflect.MakeFunc(p.Type(), generic)
    p.Set(v)
    }

    func Swap(in []reflect.Value) []reflect.Value { return
    []reflect.Value{in[1],in[0]} }

    func main() {
    s := &S{}
    Assign(s, "F", Swap)
    fmt.Println(s.F(2,1))
    }

    From the outside it looks as if s.F() was a method call.
    However, it does not fullfill an interface, e.g.


    type I interface {
    F(int, int) (int, int)
    }


    func main() {
    s := &S{}
    Assign(s, "F", Swap)
    fmt.Println(s.F(2,1))
    var i I
    i = s
    }

    results in:

    S.F is a field, not a method
    cannot use s (type *S) as type I in assignment:
    *S does not implement I (missing F method)

    (see http://play.golang.org/p/ROYBLxr7Qv)

    Now the question to the language implementors:
    --------------------------------------------------------------------

    Would it require a major effort to allow fields of structs that are
    functions to
    fullfill an interface that requires a method with the same name and
    signature?
    ------------------------------------------------------------------------------------------------------


    It's interesting, but, it seems to me that you could write

    type S struct { F1 func(int,int) (int, int) }
    func (s S) F(a, b int) (int, int) { return s.F1(a, b) }

    and then proceed just as you outline. That is, your proposal saves
    writing one boilerplate method. Boilerplate is not good, but on the
    other hand this doesn't seem like a technique that will be widely
    used.

    Ian
    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Meta keule at May 27, 2013 at 10:08 am
    I posted a somewhat lengthy reply which somehow got lost when posting
    (maybe its just Chromium).

    Instead now the short version:

    Imagine, the different parts of my code being implemented by different
    persons with different knowledge.
    At the end of the chain are the library users, that get WTFs if they can't
    make use of the libraries
    of others in their own interfaces. (50 libraries x 1000 users....)

    Also if the library programmers didn't care about the constructed struct
    instances being us in interfaces,
    if they latter get a feature request to enable them, it will break
    everybody's code.

    For the performance:

    It is reasonable to prefer rapid development to performance in some
    circumstances (e.g. prototyping).
    Especially, if you can replace the slowest parts later on, because you use
    interfaces.

    Am Sonntag, 26. Mai 2013 03:52:33 UTC+2 schrieb Carlos Castillo:
    I find your definition of comfort somewhat suspicious.

    In your orignal post you have a monstrosity of a function (AddX) which
    uses a heavy amount of reflection to create a function to process an
    arbitrary struct, pull out it's first field (assuming that what you want is
    there), assume it's an integer (runtime panic otherwise), pull out the
    second argument (an integer) add them up (result is now int64 because
    reflect.Value.Int() always returns int64), and return the result as a
    reflect.Value. In the playground code, you then convert the generated
    function into an appropriate type using reflect.MakeFunc to attach it to
    the object. Only now does your feature come into play, saving the need to
    type a one line method definition.

    Your solution is slower, more brittle, and less type-safe then
    http://play.golang.org/p/9obIw9R1B2, where I only need additionally a
    single line method to add a new field/method, and a simple anonymous
    function to implement it.

    I see little benefit to the reflective code in AddX, other then it can be
    applied to any struct with the first field being an int type instead of
    having one line of "boilerplate" that allows the field function to be much
    simpler, and can use any field of the struct (by name, so it can be moved
    in the struct), with the correct and exact type.

    Also, your example seems to make the dangerous assumption that a field of
    type func(x int) int64 is actually supposed to be assigned a func(s S1, x
    int) int64 (or a func(s *S1, x int) int64.) I know that this is to pass the
    receiver as part of the method call, but many people might not realize
    this, and get new (possibly quite obscure) errors. Resolving this 3 to 1
    mapping (two method signatures, and the straight function one), seems like
    a much bigger problem and far more programmer headaches than the initial
    problem that val.Field() is not a method call despite looking like one, and
    is spelled out in the package documentation.
    On Saturday, May 25, 2013 1:28:16 AM UTC-7, meta keule wrote:

    Clearly is is a matter of comfort.
    If you want to write a library that predefines some generic functions and
    consumes them via interface,
    it is a matter of requiring every instance to have the double effort for
    no matter, but a weird limitation of the language.

    Am Samstag, 25. Mai 2013 07:03:37 UTC+2 schrieb Ian Lance Taylor:
    On Fri, May 24, 2013 at 4:42 PM, meta keule <marcre...@googlemail.com>
    wrote:
    with the new MakeFunc, it is possible to make generic functions
    and "attach" them to a struct, e.g.


    type S struct { F func(int,int) (int, int) }
    func Assign(ptr interface{}, field string, generic func(in
    []reflect.Value) []reflect.Value){
    fv := reflect.ValueOf(ptr).Elem()
    p := fv.FieldByName(field)
    v := reflect.MakeFunc(p.Type(), generic)
    p.Set(v)
    }

    func Swap(in []reflect.Value) []reflect.Value { return
    []reflect.Value{in[1],in[0]} }

    func main() {
    s := &S{}
    Assign(s, "F", Swap)
    fmt.Println(s.F(2,1))
    }

    From the outside it looks as if s.F() was a method call.
    However, it does not fullfill an interface, e.g.


    type I interface {
    F(int, int) (int, int)
    }


    func main() {
    s := &S{}
    Assign(s, "F", Swap)
    fmt.Println(s.F(2,1))
    var i I
    i = s
    }

    results in:

    S.F is a field, not a method
    cannot use s (type *S) as type I in assignment:
    *S does not implement I (missing F method)

    (see http://play.golang.org/p/ROYBLxr7Qv)

    Now the question to the language implementors:
    --------------------------------------------------------------------

    Would it require a major effort to allow fields of structs that are
    functions to
    fullfill an interface that requires a method with the same name and
    signature?
    ------------------------------------------------------------------------------------------------------


    It's interesting, but, it seems to me that you could write

    type S struct { F1 func(int,int) (int, int) }
    func (s S) F(a, b int) (int, int) { return s.F1(a, b) }

    and then proceed just as you outline. That is, your proposal saves
    writing one boilerplate method. Boilerplate is not good, but on the
    other hand this doesn't seem like a technique that will be widely
    used.

    Ian
    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Meta keule at May 27, 2013 at 12:14 pm
    It could help in lots of cases where "generics" are requested.
    Since they are requested very often on this list, I suppose
    it would be used.

    From the perspective of a library user it would make no difference,
    but
    it would allow library writers to write powerful generic functions and
    reuse
    them everywhere.

    It would come at a performance loss, but with usage of interfaces the
    worst
    points could be optimized and replaced.
    On 25 Mai, 07:03, Ian Lance Taylor wrote:
    On Fri, May 24, 2013 at 4:42 PM, meta keule wrote:

    with the new MakeFunc, it is possible to make generic functions
    and "attach" them to a struct, e.g.
    type S struct { F func(int,int) (int, int) }
    func Assign(ptr interface{}, field string, generic func(in
    []reflect.Value) []reflect.Value){
    fv :=  reflect.ValueOf(ptr).Elem()
    p := fv.FieldByName(field)
    v := reflect.MakeFunc(p.Type(), generic)
    p.Set(v)
    }
    func Swap(in []reflect.Value) []reflect.Value { return
    []reflect.Value{in[1],in[0]} }
    func main() {
    s := &S{}
    Assign(s, "F", Swap)
    fmt.Println(s.F(2,1))
    }
    From the outside it looks as if s.F() was a method call.
    However, it does not fullfill an interface, e.g.
    type I interface {
    F(int, int) (int, int)
    }
    func main() {
    s := &S{}
    Assign(s, "F", Swap)
    fmt.Println(s.F(2,1))
    var i I
    i = s
    }
    results in:
    S.F is a field, not a method
    cannot use s (type *S) as type I in assignment:
    *S does not implement I (missing F method)
    (see  http://play.golang.org/p/ROYBLxr7Qv)
    Now the question to the language implementors:
    --------------------------------------------------------------------
    Would it require a major effort to allow fields of structs that are
    functions to
    fullfill an interface that requires a method with the same name and
    signature?
    --------------------------------------------------------------------------- ---------------------------
    It's interesting, but, it seems to me that you could write

    type S struct { F1 func(int,int) (int, int) }
    func (s S) F(a, b int) (int, int) { return s.F1(a, b) }

    and then proceed just as you outline.  That is, your proposal saves
    writing one boilerplate method.  Boilerplate is not good, but on the
    other hand this doesn't seem like a technique that will be widely
    used.

    Ian
    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupgolang-nuts @
categoriesgo
postedMay 24, '13 at 11:42p
activeMay 27, '13 at 12:14p
posts10
users4
websitegolang.org

People

Translate

site design / logo © 2021 Grokbase