


; The problem that could be solved using metaprogramming
; techniques was discussed today on Newlisp forum. Programmer
; newdep proposed integration of unary predicates (the
; functions accepting only one argument and returning true or
; false) and "if" primitive. Instead of, for example, printing
;
; (if (integer? x) (print "integer!") (print "isn't integer"))
;
; newdep thought about following:
;
; (if-integer x (print "integer!) (print "isn't integer"))
;
; In further discussion it was noted that such macro would be
; smarter, but less general. Nevertheless, programmer cormullion
; suggested simple macro to accomplish that:
(define-macro (if-integer)
(if (integer? (eval (args 0)))
(eval (args 1))
(eval (args 2))))
(if-integer 34.5 (println "yes") (println "no")) ;--> "no"; As this is routine operation, it can be used as good example
; of the techniqe that allows one to define lot of macros, related
; to all already defined predicates similar to if.
;
; It is already adressed in several posts, but this time, we
; have example of the code that could be processed easier
; in the form of a string, than in the form of s-expression.
; Usually, eval is better than eval-string, and McCarthy actually
; attributed relative success of Lisp to s-expressions, being simpler
; for metaprogramming, compared with normal strings as in POP
; for example.
; We'll first define helper function - almost the metapredicate:
; predicate predicate? Accepting symbol as argument, predicate?
; will check whether symbol ends with "?". Also, the predicate
; must be different than symbol '? itself which serves other
; purposes.
(define (predicate? i)
(and (ends-with (string i) "?")
(!= i '?))); Now we should loop through all predicates and do what cormullion
; done for integer. First, using strings and eval-string:
(dolist(i (symbols))
(when (predicate? i)
(eval-string
(replace "integer"
(copy "(define-macro (if-integer)
(if (integer? (eval (args 0)))
(eval (args 1))
(eval (args 2))))")
(append (chop (string i)))))))
(if-zero 0 (println "yes") (println "no")) ;--> "yes"; Then using s-expressions and eval
(dolist(i (symbols))
(when (predicate? i) ; for example, i=positive?
(set (sym (append "if-" (chop (string i)))) ; positive?->if-positive
(expand (lambda-macro()
(if (i (eval (args 0)))
(eval (args 1))
(eval (args 2))))
'i))))
(if-zero 34 (println "yes") (println "no")) ;--> "no"
---
No comments:
Post a Comment