Function dispatch or callback list

Started by Tim Johnson, March 22, 2010, 03:52:31 PM

Previous topic - Next topic

Tim Johnson

In python I'm used to doing something like this:

funcs = {"one":func1,"two":func2} ## etc
## Called as:
funcs[task](arg1 arg2)

I did this in newlisp:

(set 'funcs '(("int" do-int)("text" do-text)))
(define (do-int arg1 arg2)
(println "DO-INT - arg1: " arg1 " arg2: " arg2) )
(define (do-text arg1 arg2)
(println "DO-TEXT - arg1: " arg1 " arg2: " arg2))
## Function call:
(set 'arglst '("one" "two"))
(apply (lookup "text" funcs) arglst)
## => DO-TEXT - arg1: one arg2: two

If anyone thinks there is a better and more idiomatic way to do this, I would welcome comments.

thanks

tim
Programmer since 1987. Unix environment.

Sammo

#1
In 'funcs' you are storing the names of functions 'do-int' and 'do-text' but not the functions themselves. Writing it slightly differently,
(define (do-int arg1 arg2)
   (println "DO-INT - arg1: " arg1 " arg2: " arg2) )

(define (do-text arg1 arg2)
   (println "DO-TEXT - arg1: " arg1 " arg2: " arg2) )

(set 'funcs
(list
(list "int" do-int)
(list "text" do-text) ))

you can code the following:

((lookup "text" funcs) "one" "two")

or, perhaps more elegantly:
(define (f key) (lookup key funcs))

((f "text") "one" "two")

Tim Johnson

#2
Hey, I like your approach. And taking it one step further using 'fn:

(set 'funcs
   (list
      (list "int" (fn(arg1 arg2)(println "DO-INT - arg1: " arg1 " arg2: " arg2)))
      (list "text" (fn(arg1 arg2)(println "DO-TEXT - arg1: " arg1 " arg2: " arg2)))))
(define (f key) (lookup key funcs))
((f "text") "one" "two")

Elegant indeed.

Thank you

tim
Programmer since 1987. Unix environment.

Tim Johnson

#3
And one more step, factoring out 'list calls by using eval in the dispatcher:
(set 'callback-list
'(("int" (fn(arg1 arg2)
                      (println "heellllooo from the 'int handler")
                      (println arg1 " " arg2)))
          ("text" (fn(arg1 arg2)
                        (println "heellllooo from the 'text handler")
                         (println arg1 " " arg2)))))
(define (dispatcher key params)
(apply (eval(lookup key callback-list)) params))
(dispatcher "int" '("one" "two"))
(dispatcher "text" '("three" "four")

Results:

heellllooo from the 'int handler
one two
heellllooo from the 'text handler
three four

Next step: Compose an anonymous function and either replace or add to

the callback list.

Cheers

tim
Programmer since 1987. Unix environment.

Lutz

#4
Here is another solution using a hash tree to hold the lambda fuctions:


; create a hash
(define Func:Func)

; assign lambda expressions
(Func "int" (fn (x) (println "hello from int:" x)))
(Func "text" (fn (x) (println "hello from text:" x)))

; excute functions
((Func "int") 99)
((Func "text") "abc")

creates this output and return values:
hello from int:99
99
hello from text:abc
"abc"

Tim Johnson

#5
I think that your method will make modification easier also.

Thanks very much Lutz.

I hadn't even considered hashes.
Programmer since 1987. Unix environment.