As I mentioned in class, the presence of macros in the lisp family of languages
ID: 3817335 • Letter: A
Question
As I mentioned in class, the presence of macros in the lisp family of languages has led to many subtly-different implementations of the same concept. Just as function definition isn't a fundamental operation (it is composed of definition and lambda), the let mechanism can be constructed from lambda alone. The Clojure code
(let [x 10, y 20] (* x y))
is equivalent to
((fn [x y] (+ x y)) 10 20). Thus, many different implementations exist (In fact, some of the differences in let forms have been cited in the renaming of PLT Scheme to Racket (https://racket-lang.org/new-name.html)
Let's help make schemers more at home in Clojure with a macro that allows scheme-style macros to be used.
Rather than try to support both syntaxes from a single macro, you'll define a new one such that
(let-scm ((x 10) (y 20)) (+ x y))
is the same thing as
(let [x 10 y 20] (+ x y))
For clarity, here is another example that I want you to be sure that you can support.
;; this is just a helper to ensure that the let
;; arguments are only evaluated once
(defn print-and-val [val]
(println "this should only print once")
val)
(let-scm ((x (+ 5 5))
(y (print-and-val 20))
(z 30))
(println "x =" x)
(println "y =" y)
(println "z =" z)
(+ x y z))
Should produce
this should only print once
x = 10
y = 20
z = 30
and
(pprint
(macroexpand-1
'(let-scm ((x (+ 5 5))
(y (print-and-val 20))
(z 30))
(println "x =" x)
(println "y =" y)
(println "z =" z)
(+ x y z))))
should produce
(clojure.core/let
[x (+ 5 5) y (print-and-val 20) z 30]
(println "x =" x)
(println "y =" y)
(println "z =" z)
(+ x y z))
NOTE: you'll only get the namespace on the let if you use syntax-quoting (which is advisable, but not required).
EXTRA NOTE: Your macro needs to be able to handle an arbitrary number of assignments and an arbitrary number of statements in the body. This can be solved in a one or two line macro. That's making use of some built-in higher-order functions. If you implement everything from scratch it will take more of course. But if you find yourself having to write a bunch of code to handle corner cases then you are probably on the wrong track.
Explanation / Answer
(defvar a)
(defvar b)
(defvar c)
(write-line " Enter two numbers : ")
(setf a(read))
(setf b(read))
(sb-thread:make-thread(lambda()(progn(sleep 0)
(setf c(+ a b))
(print "ADDITION : ")
(print c))))
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.