; I'm trying to "embed" blocks into functions or macros, they
; can be useful for calls similar to
;
; (help function)
; (test f)
;
; etc. There are lot of ways it can be done, for example, using
; contexts. Or closures where available. Or hash tables containing
; functions for tests and help. But i tried this one.
;---------------------------------------------------------------
; I want to use "function" and "macro" as keywords
; instead of "lambda" and "lambda-macro"
(set 'function
(lambda-macro()
(eval (append '(lambda) (args)))))
(set 'macro
(lambda-macro()
(eval (append '(lambda-macro) (args)))))
; Tests: later
;---------------------------------------------------------------
; One macro useful for printing. I learnt that I almost always
; use output in this form. In the same time, test for "macro"
(set 'expression-and-value
(macro(x)
(list '-> x (eval x))))
; Tests:
(println expression-and-value)
(println (expression-and-value (+ 3 3)))
; Results:
;(lambda-macro (x) (list '-> x (eval x)))
;(-> (+ 3 3) 6)
;---------------------------------------------------------------
; As expression-and-value is used almost exclusively in print
; and it is frequently used, it justifies definition of one
; special print functions, with a very short name.
; I'll use this name: §
(set '§ (macro()
(doargs(x)
(println (eval (list 'expression-and-value x))))))
; Test (it is enough to test §)
(set 'z 1)
(§ z (sin z) (+ z 4))
; Result:
;(-> z 1)
;(-> (sin z) 0.8414709848);
;(-> (+ z 4) 5)
;---------------------------------------------------------------
; I define block as non-empty list. Intention is to make
; generalization of begin-block. Following functions are very
; simple and they do not require any comments.
(set 'block?
(function(candidate)
(if (list? candidate)
(not (empty? candidate)))))
; Tests:
(§ (block? '(hello-world (println "hello, world"))))
(§ (block? '()))
(§ (block? 3))
(§ (block? '(nil print)))
; Results:
;(-> (block? '(hello-world (println "hello, world"))) true)
;(-> (block? '()) nil)
;(-> (block? 3) nil)
;(-> (block? '(nil print)) true)
;---------------------------------------------------------------
(set 'get-block-name
(function(some-block)
(if (not (block? some-block))
(throw-error (list "get-block-name applied on non-block"
some-block))
(first some-block))))
;Tests
(§ (get-block-name '(hello (println "hello"))))
;(§ (get-block-name '()))
;(§ (get-block-name 3))
; Results:
;(-> (get-block-name '(hello (println "hello"))) hello)
; other two really return excpected error
;---------------------------------------------------------------
(set 'quoted-block?
(function(candidate)
(if (quote? candidate)
(block? (eval candidate)))))
; Tests:
(§ (quoted-block? ''(hello (println "hello!"))))
(§ (quoted-block? ''()))
(§ (quoted-block? '3))
(§ (quoted-block? ''(nil print)))
; Results:
;(-> (quoted-block? ''(hello (println "hello!"))) true)
;(-> (quoted-block? ''()) nil)
;(-> (quoted-block? '3) nil)
;(-> (quoted-block? ''(nil print)) true)
;---------------------------------------------------------------
(set 'begin-block-from-any-block
(function(some-block)
(append '(begin)
(rest some-block))))
; Test:
(§ (begin-block-from-any-block
'(hello (println "Hello!"))))
; Result: works OK
;---------------------------------------------------------------
(set 'get-block-from-list-containing-quoted-blocks
(function(block-name list-containing-quoted-blocks)
(catch (dolist (i list-containing-quoted-blocks)
(if (and (quoted-block? i)
(= block-name
(get-block-name (eval i))))
(throw (eval i)))))))
; Tests:
(§ (get-block-from-list-containing-quoted-blocks
'test
(list ''(wrong) '(test) 0 ''(test) '(false))))
(§ (get-block-from-list-containing-quoted-blocks
'test
(list '(wrong) '(right) 0 '(false))))
(§ (get-block-from-list-containing-quoted-blocks
'test
(list)))
(§ (get-block-from-list-containing-quoted-blocks
'test
'()))
; Results: everything works OK
;---------------------------------------------------------------
(set 'evaluate-block-from-list-containing-quoted-blocks
(function (block-name list-containing-quoted-blocks)
(eval (begin-block-from-any-block
(get-block-from-list-containing-quoted-blocks
block-name
list-containing-quoted-blocks)))))
;---------------------------------------------------------------
; OK, everything is ready for a final test.
; I'll define one cute function, "integer-quote" with two cute
; blocks, "help" and "test," and see what happens.
(set 'integer-quote
(macro(i expr)
'(help
(println "\nInteger-guote help:")
(println " Syntax: (integer-quote <integer> <expression>)")
(println " Example: " (expression-and-value (integer-quote 2 x)))
(println " Example: " (expression-and-value (integer-quote -3 x)))
(println " Example: " (expression-and-value (integer-quote 0 x)))
(println "End of integer-quote help.\n"))
'(test
(println "\nInteger-quote test:")
(if (= (integer-quote 2 x) '(quote (quote x)))
(println " First test passed.")
(println " First test failed."))
(if (= (integer-quote -3 x) '(eval (eval (eval x))))
(println " Second test passed.")
(println " Second test failed."))
(if (= (integer-quote 0 x) 'x)
(println " Third test passed.")
(println " Third test failed."))
(println "End of quote-eval test.\n"))
(cond
((= i 0) expr)
((> i 0) (eval (list 'integer-quote
(- i 1)
(list 'quote expr))))
((< i 0) (eval (list 'integer-quote
(+ i 1)
(list 'eval expr)))))))
;---------------------------------------------------------------
; Tests
(println "\n\n\nOK, let me see how it works.")
(evaluate-block-from-list-containing-quoted-blocks 'help integer-quote)
(evaluate-block-from-list-containing-quoted-blocks 'test integer-quote)
(§ (integer-quote -7 (i-o-lets-go!)))
;Results
;Integer-guote help:
; Syntax: (integer-quote <integer> <expression>)
; Example: (-> (integer-quote 2 x) (quote (quote x)))
; Example: (-> (integer-quote -3 x) (eval (eval (eval x))))
; Example: (-> (integer-quote 0 x) x)
;End of integer-quote help.
;Integer-quote test:
; First test passed.
; Second test passed.
; Third test passed.
;End of quote-eval test.
;(-> (integer-quote -7 (i-o-lets-go!))
;(eval (eval (eval (eval (eval (eval (eval (i-o-lets-go!)))))))))
;Everything works fine.
;Sure, i can use shorter names.
Embedding Blocks into Functions.
Subscribe to:
Post Comments (Atom)
No comments:
New comments are not allowed.