Function dispatch or callback list

Q&A's, tips, howto's
Locked
Tim Johnson
Posts: 253
Joined: Thu Oct 07, 2004 7:21 pm
Location: Palmer Alaska USA

Function dispatch or callback list

Post 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
Programmer since 1987. Unix environment.

Sammo
Posts: 180
Joined: Sat Dec 06, 2003 6:11 pm
Location: Loveland, Colorado USA

Re: Function dispatch or callback list

Post 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")

Tim Johnson
Posts: 253
Joined: Thu Oct 07, 2004 7:21 pm
Location: Palmer Alaska USA

Re: Function dispatch or callback list

Post 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
Programmer since 1987. Unix environment.

Tim Johnson
Posts: 253
Joined: Thu Oct 07, 2004 7:21 pm
Location: Palmer Alaska USA

Re: Function dispatch or callback list

Post 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
Programmer since 1987. Unix environment.

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Re: Function dispatch or callback list

Post 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"

Tim Johnson
Posts: 253
Joined: Thu Oct 07, 2004 7:21 pm
Location: Palmer Alaska USA

Re: Function dispatch or callback list

Post by Tim Johnson »

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.

Locked