Page 1 of 1

Function dispatch or callback list

Posted: Mon Mar 22, 2010 10:52 pm
by Tim Johnson
In python I'm used to doing something like this:

Code: Select all

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

Code: Select all

(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

Re: Function dispatch or callback list

Posted: Mon Mar 22, 2010 11:46 pm
by Sammo
In 'funcs' you are storing the names of functions 'do-int' and 'do-text' but not the functions themselves. Writing it slightly differently,

Code: Select all

(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:

Code: Select all

((lookup "text" funcs) "one" "two")
or, perhaps more elegantly:

Code: Select all

(define (f key) (lookup key funcs))

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

Re: Function dispatch or callback list

Posted: Mon Mar 22, 2010 11:58 pm
by Tim Johnson
Hey, I like your approach. And taking it one step further using 'fn:

Code: Select all

(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

Re: Function dispatch or callback list

Posted: Tue Mar 23, 2010 11:11 pm
by Tim Johnson
And one more step, factoring out 'list calls by using eval in the dispatcher:

Code: Select all

(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:

Code: Select all

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

Re: Function dispatch or callback list

Posted: Wed Mar 24, 2010 12:07 am
by Lutz
Here is another solution using a hash tree to hold the lambda fuctions:

Code: Select all

 ; 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:

Code: Select all

hello from int:99
99
hello from text:abc
"abc"

Re: Function dispatch or callback list

Posted: Wed Mar 24, 2010 1:04 am
by Tim Johnson
I think that your method will make modification easier also.
Thanks very much Lutz.
I hadn't even considered hashes.