Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

faster reflect approach suggestion #53

Open
glycerine opened this issue Dec 21, 2018 · 1 comment
Open

faster reflect approach suggestion #53

glycerine opened this issue Dec 21, 2018 · 1 comment

Comments

@glycerine
Copy link
Contributor

Massimiliano had some good suggestions; quoting his email.

In glycerine/luar/luar.go the func goToLuaFunction() contains:

    t := v.Type()
    nIn := t.NumIn()
    argsT := make([]reflect.Type, nIn)
    for i := range argsT {
            argsT[i] = t.In(i)
    }

    // NB (jea): we wish their was a more efficient way to distinguish
    // methods (with a receiver argument) from functions (no receiver)
    // with reflect. However this is what I could come up with.
    // Better methods welcome, but this appears to work for now.
    //
    fname := getFunctionName(v)
    isMethod := fname == "reflect.methodValueCall"

I think the question whether the reflect.Value 'v' (which contains a
function or method) already includes the receiver or not can be answered
as follows:

it depends on how 'v' was obtained, see my example at

https://play.golang.org/p/QJ-33HOBR3p

  1. if the method was obtained directly from receiver's reflect.Value
    with reflect.Value.Method(int) or reflect.Value.MethodByName(string)
    then the receiver will be already bound

  2. if the method was obtained from from receiver's reflect.Value.Type()
    with reflect.Type.Method(int) or reflect.Value.MethodByName(string)
    (they both return reflect.Method)
    and then extracting the field reflect.Method.Func,
    then the receiver will not be bound

Attempts to distinguish the two cases purely by inspecting the
reflect.Value that contains the method are possible, as you have shown,
but I believe they are both non-portable and fragile.

Regards,

Massimiliano Ghilardi
(cosmos72)

@glycerine
Copy link
Contributor Author

the playground code (in case it disappears):

package main

import (
	"fmt"
	"reflect"
	"time"
)

func main() {
	a := time.Now()
	va := reflect.ValueOf(a)

	// case 1. get method directly from receiver's reflect.Value 'va'
	// => receiver is already bound to va
	method1 := va.MethodByName("After")   // returns a reflect.Value
	type1 := method1.Type()               //
	fmt.Println(type1)                    // func(time.Time) bool
	fmt.Println("NumIn =", type1.NumIn()) // 1, receiver is already bound

	// case 2. get method through receiver's reflect.Type 'va.Type()'
	// => receiver is not bound
	ta := va.Type()                        // time.Time
	method2, _ := ta.MethodByName("After") // returns a reflect.Method
	method2v := method2.Func               // extract the reflect.Value
	type2 := method2v.Type()               //
	fmt.Println(type2)                     // func(time.Time, time.Time) bool
	fmt.Println("NumIn =", type2.NumIn())  // 2, receiver is not bound
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant