Optional Fetcher #291
Replies: 9 comments 22 replies
-
Can you please explain a little bit more? As vm.Fetcher was removed in latest Expr versions. It’s still possible to do the same logic using the ast.Patch functionality. I will write a doc on how to do it. |
Beta Was this translation helpful? Give feedback.
-
type Bar struct{
D int
}
type Foo struct {
A int
B bool
Mp map[string]*Bar // has elements MP1 MP2 MP3 MP4 MP5 MP6 MP1-3 is call heavily and would like to cache it as pointers as below
mp1 *Bar //lower case to avoid export in serialization but cannot be accessed by expr
mp2 *Bar //lower case to avoid export in serialization
mp3 *Bar //lower case to avoid export in serialization
}
FooExample = Foo{A: 1, B: true, Mp: make(map[string]*Bar)}
FooExample.Mp["MP1"]= Bar{}
FooExample.Mp["MP2"]= Bar{}
FooExample.Mp["MP3"]= Bar{}
FooExample.Mp["MP4"]= Bar{}
FooExample.Mp["MP5"]= Bar{}
FooExample.mp1=FooExample.Mp["MP1"] //cache the most used
FooExample.mp2=FooExample.Mp["MP2"] //cache the most used
FooExample.mp3=FooExample.Mp["MP3"] //cache the most used
FooExample.mp1.D // direct and avoids the overhead of a map lookup |
Beta Was this translation helpful? Give feedback.
-
Expose MP1 and no map lookup will be done. |
Beta Was this translation helpful? Give feedback.
-
I cannot expose it as I don't want MP1-3 added in a gob serialization routine in another process and increase the size of the serialized output with duplicate information. This is why it is lowercase. However it can be accessed by a fetcher. What might be nice is to be able to fetch if fetcher exists/defined else fall though to standard fetch. func (v *Foo) Fetch(i interface{}) interface{} {
var string_i string
if s, ok := i.(string); ok {
string_i = s
} else {
string_i = fmt.Sprint(i)
}
switch string_i {
case "mp1":
return v.mp1
case "mp2":
return v.mp2
case "mp3":
return v.mp3
}
return nil
} |
Beta Was this translation helpful? Give feedback.
-
I see. What about losing a separate structure for Env? |
Beta Was this translation helpful? Give feedback.
-
I don't understand the above suggestion. But if you mean use a mostly duplicate structure in Env .. then that would mean duplicated effort and size for the object that is very large in size and complexity. It would require a great deal of coordination to keep them in sync and introduce error and performance overhead. Adding an optional fetcher within the new optimized paradigm would help immensely to do some optimization tricks for the end user. And I don't mean just this example. Case/Switch is cheap especially if you have nested structs with their own fetchers. What would be nice is a combo fetch from fetcher when it is defined and a fall through to standard processing when it is not defined or when the fetcher returns nil. It would afford great latitude for the end user to optimize according to his needs. |
Beta Was this translation helpful? Give feedback.
-
Something like this:
And use ast.Patcher to convert this
to this
|
Beta Was this translation helpful? Give feedback.
-
I would benefit from a hybrid fetcher functionality as: func Fetch(from, i interface{}) interface{} {
if fetcher, ok := from.(Fetcher); ok {
value := fetcher.Fetch(i)
if value != nil {
return value
}
}
// from here
// fall through to standard processing
} Same for: func FetchField(from interface{}, field *Field) interface{} {
for i, x := range field.Path{
// traverse path using fetcher(s) where fetchers are defined
// else use standard offset index processing
}
}
} |
Beta Was this translation helpful? Give feedback.
-
runtime.go type Fetcher interface {
Fetch(interface{}) interface{}
}
func FetchFetcher(from, i interface{}) interface{} {
value:=from.(Fetcher).Fetch(i) //bareback, as its been vetted to have a fetcher at compile time.
if value != nil {
return value
}
panic(fmt.Sprintf("cannot fetch %v from %T", i, from))
//return nil
} vm.go: case OpFetchFetcher:
b := vm.pop()
a := vm.pop()
vm.push(runtime.FetchFetcher(a, b)) |
Beta Was this translation helpful? Give feedback.
-
In some circumstances with certain structs and as needed, would it be possible to create provisions to use fetcher?
Beta Was this translation helpful? Give feedback.
All reactions