-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdynamic.lisp
45 lines (36 loc) · 1.4 KB
/
dynamic.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
;;; dynamic.lisp - Execute code by name, via introspection.
;;
;; I'm not sure whether to be pleased with this or not.
;;
;; Given the (string) name of a function to be called, and some
;; arguments .. call it.
;;
;; (env) returns a lists of hashes, so we can find the function with
;; a given name via `filter`. Assuming only one response then we're
;; able to find it by name, and execute it.
;;
(set! call-by-name
(fn* (name:string &args)
(let* (out nil ; out is the result of the filter
nm nil ; nm is the name of the result == name
fn nil) ; fn is the function of the result
;; find the entry in the list with the right name
(set! out (filter (env) (lambda (x) (eq (get x :name) name))))
;; If we have a list of arguments, which we will, then
;; take the first one.
(if (list? args)
(set! args (car args)))
;; there should be only one matching entry
(if (= (length out) 1)
(do
(set! nm (get (car out) :name)) ;; nm == name
(set! fn (get (car out) :value)) ;; fn is the function to call
(if fn (fn args))))))) ;; if we got it, invoke it
;; Print a string
(call-by-name "print" "Hello, world!")
;; Get an environmental variable
(print (call-by-name "getenv" "HOME"))
;; Call print with no arguments
(call-by-name "print")
;; The other way to do dynamic calls
(eval "(print (+ 34 43))")