There is destructuring-bind but it seems there is no destructuring-setq. Is it possible to define it using destructuring-bind?
(let (a b c d)
(destructuring-setq ((a b) (c d)) '((1 2) (3 4)))
`(,b ,d))
(destructuring-bind
((a b) (c d)) '((1 2) (3 4))
`(,b ,d))
This would be a highly nontrivial endeavor.
What you would have to do is write a lambda-list analyzer which would
Find all variables to be bound
Replace them with gensyms (or use copy-symbol for total unreadability of the macroexpansion :-) and keep a map from the old symbols to the new ones.
Return something like
(destructuring-bind (new-lambda-list)
expression
(setq old-var-1 new-gensym-1 ...))
The analyser is present in any Common Lisp implementation (see, e.g., the link above) and it is not simple.
I suggest that you ask yourself whether destructuring-bind is really not enough.
Related
I am playing around with Common Lisp and just realized that
(type-of (cons 1 2)) is CONS
and
(type-of (list 1 2)) is also CONS
However the two are clearly not the same because all "proper" lists, must be conses with second element being a list.
That said, when there are only two elements, the second element is 2, and first element is 1, neither is a list, but the construct is also still called a cons.
This gets even more confusing since
(print (list (cons 1 2) 3)) ; this is a ((1 . 2) 3), an improper list, but still cons
(print (cons 1 (list 2 3))) ; this is a (1 2 3), a proper list, but still cons
(cons 1 (cons 2 3)) ; is not a proper list, but is a (1 2 . 3), but still cons...
All are cons, but why isn't (list 1 2) a list? It can't be a cons because cons and list must be different types in order to be told apart in the algorithm for determining whether or not it is a proper list (and in turn, (equal (list 1 2) (cons 1 2)) should be true; without this discrimination, there should be no difference between a cons and a list, there would just be a cons.
Can somebody please help me understand why it says that (type-of (list 1 2)) is cons, even though it is clearly a list (otherwise it would be an improper list to my understanding).
Proper and improper lists are not defined at the type level. This would require recursive type definitions which is only possible to do with Lisp with a satisfies type, and in that case type-of would still not return a type-specifier as complex:
b. the type returned does not involve and, eql,
member, not, or, satisfies or values.
The list type could be defined as (or cons null):
The types cons and null form an exhaustive partition of the type list.
That means that nil is a list, and any cons cell is a list. See also the definition of listp.
In other words:
(typep '(a b c) 'cons)
=> T
But also:
(typep '(a b c) 'list)
=> T
And of course this is true for any supertype:
(typep '(a b c) 'sequence)
=> T
(typep '(a b c) 't)
=> T
The type-of function returns the most basic type, i.e. cons, which can be thought of as the type for which no other subtype satisfy typep (but read the specification which gives the actual definition).
Remarks
Just to clarify:
(cons 1 2)
... is a list, but it cannot be passed to functions that expect proper lists like map, etc. This is checked at runtime and generally, there is no confusion because the cases where one use improper lists are actually quite rare (when you treat cons cells as trees, for example). Likewise, circular lists require special treatment.
In order to check if a list is proper or not, you only need to check whether the last cons has a nil or not as its cdr.
Also, I saw that you wrote:
((1 . 2) 3) ; [...] an improper list
What you have here is a proper-list of two elements where the first one is an improper list, a.k.a. a dotted-list.
#coredump's answer is the correct one, but it's perhaps useful to see pragmatic reasons why it's correct.
Firstly, it's quite desirable that typechecks are quick. So if I say (typep x 'list), I'd like it not to have to go away for a long time to do the check.
Well, consider what a proper list checker has to look like. Something like this, perhaps:
(defun proper-list-p (x)
(typecase x
(null t)
(cons (proper-list-p (rest x)))
(t nil)))
For any good CL compiler this is a loop (and it can obviously be rewritten as an explicit loop if you might need to deal with rudimentary compilers). But it's a loop which is as long as the list you are checking, and this fails the 'typechecks should be quick' test.
In fact it fails a more serious test: typechecks should terminate. Consider a call like (proper-list-p #1=(1 . #1#)). Oops. So we need something like this, perhaps:
(defun proper-list-p (x)
(labels ((plp (thing seen)
(typecase thing
(null (values t nil))
(cons
(if (member thing seen)
(values nil t) ;or t t?
(plp (rest thing)
(cons thing seen))))
(t (values nil nil)))))
(plp x '())))
Well, this will terminate (and tell you whether the list is circular):
> (proper-list-p '#1=(1 . #1#))
nil
t
(This version considers circular lists not to be proper: I think the other decision is less useful but perhaps equally justified in some theoretical sense.)
But this is now quadratic in the length of the list. This can be made better by using a hashtable in the obvious way, but then the implementation is ludicrously consy for small lists (hashtables are big).
Another reason is to consider the difference between representational type and intentional type: the representational type of something tells you how it is implemented, while the intentional type tells you what it logically is. And it's easy to see that, in a lisp with mutable data structures, it is absurdly difficult for the representational type of a (non-null) list to be different than that of a cons. Here's an example of why:
(defun make-list/last (length init)
;; return a list of length LENGTH, with each element being INIT,
;; and its last cons.
(labels ((mlt (n list last)
(cond ((zerop n)
(values list last))
((null last)
(let ((c (cons init nil)))
(mlt (- n 1) c c)))
(t (mlt (- n 1) (cons init list) last)))))
(mlt length '() '())))
(multiple-value-bind (list last) (make-list/last 10 3)
(values
(proper-list-p list)
(progn
(setf (cdr last) t)
(proper-list-p list))
(progn
(setf (cdr (cdr list)) '(2 3))
(proper-list-p list))))
So the result of the last form is t nil t: list is initially a proper list, then it isn't because I fiddled with its final cons, then it is again because I fiddled with some intermediate cons (and now, whatever I do to the cons bound to last will make no difference to that bound to list).
It would be insanely difficult to keep track, in terms of representational type, of whether something is a proper list or not, if you want to use anything that is remotely like linked lists. And type-of, for instance, tells you the representational type of something, which can only be cons (or null for empty lists).
I want to know if these two definitions of nth are equal:
I. is defined as macro:
(defmacro -nth (n lst)
(defun f (n1 lst1)
(cond ((eql n1 0) lst1)
(t `(cdr ,(f (- n1 1) lst1)))))
`(car ,(f n lst)))
II. is defined as a bunch of functions:
(defun f (n lst)
(cond ((eql n 0) lst)
(t `(cdr ,(f (- n 1) lst)))))
(defun f1 (n lst)
`(car ,(f n `',lst)))
(defun --nth (n lst)
(eval (f1 n lst)))
Am i get the right idea? Is macro definition is evaluating of expression, constructed in its body?
OK, let start from the beginning.
Macro is used to create new forms that usually depend on macro's input. Before code is complied or evaluated, macro has to be expanded. Expansion of a macro is a process that takes place before evaluation of form where it is used. Result of such expansion is usually a lisp form.
So inside a macro here are a several levels of code.
Not quoted code will be evaluated during macroexpansion (not at run-time!), in your example you define function f when macro is expanded (for what?);
Next here is quoted (with usual quote or backquote or even nested backquotes) code that will become part of macroexpansion result (in its literal form); you can control what part of code will be evaluated during macroexpansion and what will stay intact (quoted, partially or completely). This allows one to construct anything before it will be executed.
Another feature of macro is that it does not evaluate its parameters before expansion, while function does. To give you picture of what is a macro, see this (just first thing that came to mind):
(defmacro aif (test then &optional else)
`(let ((it ,test))
(if it ,then ,else)))
You can use it like this:
CL-USER> (defparameter *x* '((a . 1) (b . 2) (c . 3) (d . 4)))
*X*
CL-USER> (aif (find 'c *x* :key #'car) (1+ (cdr it)) 0)
4
This macro creates useful lexical binding, capturing variable it. After checking of a condition, you don't have to recalculate result, it's accessible in forms 'then' and 'else'. It's impossible to do with just a function, it has introduced new control construction in language. But macro is not just about creating lexical environments.
Macro is a powerful tool. It's impossible to fully describe what you can do with it, because you can do everything. But nth is not something you need a macro for. To construct a clone of nth you can try to write a recursive function.
It's important to note that LISP macro is most powerful thing in the programming world and LISP is the only language that has this power ;-)
To inspire you, I would recommend this article: http://www.paulgraham.com/avg.html
To master macro, begin with something like this:
http://www.gigamonkeys.com/book/macros-defining-your-own.html
Then may be Paul Graham's "On Lisp", then "Let Over Lambda".
There is no need for either a macro nor eval to make abstractions to get the nth element of a list. Your macro -nth doesn't even work unless the index is literal number. try this:
(defparameter test-list '(9 8 7 6 5 4 3 2 1 0))
(defparameter index 3)
(nth index test-list) ; ==> 6 (this is the LISP provided nth)
(-nth index test-list) ; ==> ERROR: index is not a number
A typical recursive solution of nth:
(defun nth2 (index list)
(if (<= index 0)
(car list)
(nth2 (1- index) (cdr list))))
(nth2 index test-list) ; ==> 6
A typical loop version
(defun nth3 (index list)
(loop :for e :in list
:for i :from index :downto 0
:when (= i 0) :return e))
(nth3 index test-list) ; ==> 6
Usually a macro is something you use when you see your are repeating yourself too much and there is no way to abstract your code further with functions. You may make a macro that saves you the time to write boilerplate code. Of course there is a trade off of not being standard code so you usually write the macro after a couple of times have written the boilerplate.
eval should never be used unless you really have to. Usually you can get by with funcall and apply. eval works only in the global scope so you loose closure variables.
I am trying to solve the last part of question 4.4 of the Structure and Interpretation of computer programming; the task is to implement or as a syntactic transformation. Only elementary syntactic forms are defined; quote, if, begin, cond, define, apply and lambda.
(or a b ... c) is equal to the first true value or false if no value is true.
The way I want to approach it is to transform for example (or a b c) into
(if a a (if b b (if c c false)))
the problem with this is that a, b, and c would be evaluated twice, which could give incorrect results if any of them had side-effects. So I want something like a let
(let ((syma a))
(if syma syma (let ((symb b))
(if symb symb (let ((symc c))
(if (symc symc false)) )) )) )
and this in turn could be implemented via lambda as in Exercise 4.6. The problem now is determining symbols syma, symb and symc; if for example the expression b contains a reference to the variable syma, then the let will destroy the binding. Thus we must have that syma is a symbol not in b or c.
Now we hit a snag; the only way I can see out of this hole is to have symbols that cannot have been in any expression passed to eval. (This includes symbols that might have been passed in by other syntactic transformations).
However because I don't have direct access to the environment at the expression I'm not sure if there is any reasonable way of producing such symbols; I think Common Lisp has the function gensym for this purpose (which would mean sticking state in the metacircular interpreter, endangering any concurrent use).
Am I missing something? Is there a way to implement or without using gensym? I know that Scheme has it's own hygenic macro system, but I haven't grokked how it works and I'm not sure whether it's got a gensym underneath.
I think what you might want to do here is to transform to a syntactic expansion where the evaluation of the various forms aren't nested. You could do this, e.g., by wrapping each form as a lambda function and then the approach that you're using is fine. E.g., you can do turn something like
(or a b c)
into
(let ((l1 (lambda () a))
(l2 (lambda () b))
(l3 (lambda () c)))
(let ((v1 (l1)))
(if v1 v1
(let ((v2 (l2)))
(if v2 v2
(let ((v3 (l3)))
(if v3 v3
false)))))))
(Actually, the evaluation of the lambda function calls are still nested in the ifs and lets, but the definition of the lambda functions are in a location such that calling them in the nested ifs and lets doesn't cause any difficulty with captured bindings.) This doesn't address the issue of how you get the variables l1–l3 and v1–v3, but that doesn't matter so much, none of them are in scope for the bodies of the lambda functions, so you don't need to worry about whether they appear in the body or not. In fact, you can use the same variable for all the results:
(let ((l1 (lambda () a))
(l2 (lambda () b))
(l3 (lambda () c)))
(let ((v (l1)))
(if v v
(let ((v (l2)))
(if v v
(let ((v (l3)))
(if v v
false)))))))
At this point, you're really just doing loop unrolling of a more general form like:
(define (functional-or . functions)
(if (null? functions)
false
(let ((v ((first functions))))
(if v v
(functional-or (rest functions))))))
and the expansion of (or a b c) is simply
(functional-or (lambda () a) (lambda () b) (lambda () c))
This approach is also used in an answer to Why (apply and '(1 2 3)) doesn't work while (and 1 2 3) works in R5RS?. And none of this required any GENSYMing!
In SICP you are given two ways of implementing or. One that handles them as special forms which is trivial and one as derived expressions. I'm unsure if they actually thought you would see this as a problem, but you can do it by implementing gensym or altering variable? and how you make derived variables like this:
;; a unique tag to identify special variables
(define id (vector 'id))
;; a way to make such variable
(define (make-var x)
(list id x))
;; redefine variable? to handle macro-variables
(define (variable? exp)
(or (symbol? exp)
(tagged-list? exp id)))
;; makes combinations so that you don't evaluate
;; every part twice in case of side effects (set!)
(define (or->combination terms)
(if (null? terms)
'false
(let ((tmp (make-var 'tmp)))
(list (make-lambda (list tmp)
(list (make-if tmp
tmp
(or->combination (cdr terms)))))
(car terms)))))
;; My original version
;; This might not be good since it uses backquotes not introduced
;; until chapter 5 and uses features from exercise 4.6
;; Though, might be easier to read for some so I'll leave it.
(define (or->combination terms)
(if (null? terms)
'false
(let ((tmp (make-var 'tmp)))
`(let ((,tmp ,(car terms)))
(if ,tmp
,tmp
,(or->combination (cdr terms)))))))
How it works is that make-var creates a new list every time it is called, even with the same argument. Since it has id as it's first element variable? will identify it as a variable. Since it's a list it will only match in variable lookup with eq? if it is the same list, so several nested or->combination tmp-vars will all be seen as different by lookup-variable-value since (eq? (list) (list)) => #f and special variables being lists they will never shadow any symbol in code.
This is influenced by eiod, by Al Petrofsky, which implements syntax-rules in a similar manner. Unless you look at others implementations as spoilers you should give it a read.
As probably all experienced elispers have found at some point, code like is broken:
(let ((a 3)
(b 4)
(c (+ a b)))
c)
One should use the let* form instead when referring to a just-binded variable within the binding clauses.
I just wonder - why is a seemingly wrong behavior the default? Are there any risks on choosing always let* regardless of how is one gonna use it?
Any let* forms can be easily (and mechanically) expressed using let. For example, if we didn't have the let* special form, we could express
(let* ((a 3)
(b 4)
(c (+ a b)))
c)
as:
(let ((a 3))
(let ((b 4))
(let ((c (+ a b)))
c)))
On the other hand, some let forms are quite difficult, if possible at all, to express using let*. The following let form cannot be expressed using let* without introducing an additional temporary variable or esoteric bitwise manipulation.
(let ((x y) (y x)) ; swap x and y
...)
So, in this sense, I think let is more fundamental than let*.
I was taught that the reason is mainly historical, but it might still hold: Since let does parallel assigment, having no data dependencies between the variables might give the compiler flexibility compile for speed or space and compile to something much faster than let*. I don't know how much the elisp compiler uses this.
A bit of googling reveals a similar question for Common Lisp: LET versus LET* in Common Lisp
it is incorrect to do so
(let ((a 10)
(b a)) <- error
b)
it is correct to do so:
(let* ((a 10)
(b a))
b) <- will evaluate to 10.
The error in the first case is due to semantics of let.
let* adds new symbols to the existing environment, evaluating them inside it.
let creates a new environment, evaluating the new symbols in the current envinronemnt, and the new environment will be disponible at the end of the evaluation of all new symbols, to evaluate the code of (let () code ).
let* is syntactic sugar for
(let ((a xxx))
(let ((b a)) ...)
while let is syntactic sugar for
((lambda (a)
...)
val_a)
The second form is much more common, so perhaps they thought to give it a shorter name...
I'm not sure I would call let broken. For instance, you may for whatever reason want to shadow a and b in the enclosed environment, while defining c with respect to the enclosing expression.
(let ((a 11)
(b 12))
(let ((a 3)
(b 4)
(c (+ a b)))
;; do stuff here will shadowed `a' and `b'
c))
> 23
As for risks, I don't know if there are any per se. But why created multiple nested environments when you don't have to? There may be a performance penalty for doing so (I don't have enough experience with elisp to say).
I'm writing a Lisp (code at GitHub) and I want to implement local bindings. Currently I have two syntaxes:
(let <var> <val> <expr>)
for binding a single variable or function, and
(with (<var1> <val1> ... <varN> <valN>) <expr>)
to bind multiple values at once.
At present, the bindings are evaluated sequentially, and each new function binding retains a copy of the environment it was defined in, so <var2> can refer to <var1> but not vice-versa.
I would like to modify the code so that when binding multiple values at once you effectively have simultaneous binding. For example, I would like to be able to write (this is a trivial example, but it should illustrate the idea):
(define (h y)
(with ((f x) (if (eq? x 0) #t (g (- x 1)))
(g x) (if (eq? x 0) #f (f (- x 1))))
(f y))
At the moment this code doesn't run - g closes over f, but not the other way around.
Is there a canonical way to implement simultaneous binding in Lisp?
In SICP there's a section on internal definitions which covers this subject. In particular, the exercises 4.16, 4.18, 4.19 tell you how to implement different strategies for achieving simultaneous definitions.
The syntax is a bit different, but the idea in the book boils down to transforming this code:
(lambda <vars>
(define u <e1>)
(define v <e2>)
<e3>)
Into this code:
(lambda <vars>
(let ((u '*unassigned*)
(v '*unassigned*))
(set! u <e1>)
(set! v <e2>)
<e3>))
The same idea applies to your with special form. Take a look at the linked book for more implementation details.
In (with (a (+ 2 2))) we are binding a to the value of the expression (+ 2 2), so a becomes 4. But in (with ((f x) (+ x x))) we are doing something else: we are binding f to a function. This is a syntactic sugar for (with (f (lambda (x) (+ x x)))).
To handle this situation, you have to process the bindings in two passes. First collect all the variables and create the environment which contains all of them. Then evaluate the initializing experssions and store their values in the corresponding variables. The evaluation of these expressions takes place in that environment, so every expression has visibility over all the variables. The initialization is done by assignment. The variables can be initially nil or have some trap value which blows up if they are accessed.