Is it legal to modify a list created using quasiquote? - scheme

From my understanding, it is not legal to modify a list created using quote:
(let ((numbers '(3 2 1)))
(set-car! numbers 99) ; Illegal.
numbers)
What about lists created using quasiquote? Is it legal to modify lists created using quasiquote?
(let ((numbers `(3 2 1)))
(set-car! numbers 99) ; Legal?
numbers)
(let ((numbers `(,(+ 1 2) 2 1)))
(set-car! numbers 99) ; Legal?
numbers)

The short answer is no, this isn't "legal", and certainly this should never be done in a program that aims to be portable. R6RS and R7RS have almost identical language around this, so I'll just quote from R6RS, Section 11.17 Quasiquotation:
A quasiquote expression may return either fresh, mutable objects or literal structure for any structure that is constructed at run time during the evaluation of the expression. Portions that do not need to be rebuilt are always literal.
Section 4.2.8 of R7RS has the same language, except that it says "newly allocated" instead of "fresh".
Since it is an error to attempt to modify literals in Scheme, it is an error to modify the result of a quasiquote form. This is something that you may seem get away with sometimes, but it will bite you sooner or later. The real catch here is that "portions that do not need to be rebuilt are always literal". Other portions may or may not be literal.
More specifically for OP posted code, `(3 2 1) is guaranteed to evaluate to a list literal by the semantics of quasiquote described in Section 11.17 of R6RS:
Semantics: If no unquote or unquote-splicing forms appear within the <qq template>, the result of evaluating (quasiquote <qq template>) is equivalent to the result of evaluating (quote <qq template>).
R7RS contains similar language in Section 4.2.8. Since (quote (3 2 1)) creates a list literal, the expression `(3 2 1) must also evaluate to a list literal.
On the other hand, OP code `(,(+ 1 2) 2 1) must evaluate (+ 1 2) and insert that result into the resulting structure. In this case, unquote is used via the , operator, so the resulting list structure may or may not be a list literal.
To take one more example, consider the quasiquoted expression `(,(+ 1 2) (2 1)). Here the main result is a list structure which may or may not be a list literal, but the element (2 1) of the resulting structure is guaranteed to be a list literal since it does not need to be rebuilt in the construction of the final result.

Related

Duplicate lists when defining a list of lists in Common Lisp

I am defining a variable as a list containing lists of symbols:
(defparameter *var* '((a a a) (a x a) (a a a)))
When I try to change one of the elements with setf...
(setf (caar *var*) 'c)
... both the first and the last lists are updated.
> *var*
; ((c a a) (a x a) (c a a))
I noticed that when I evaluate the defparameter in the REPL, the setf command works as expected. This makes me think that the unexpected behaviour is related to the compilation process.
Questions:
What is happening and why?
What would be the canonical way of defining a list of fresh lists containing the same symbols in defparameter?
I am using SBCL.
Edit: My question is not similar to this question, because I am not asking how to copy lists so that they do not share structure, but rather why when compiling a defparameter lists with similar elements appear to share structure and how to define them so they do not.
This is a frequently asked question.
Why does SBCL show this implementation dependent behavior?
Try after loading the compiled file (use COMPILE-FILE to compile it):
* (eq (first *var*) (third *var*))
T
* *var*
((A A A) (A X A) (A A A))
* (setf *print-circle* t)
T
* *var*
(#1=(A A A) (A X A) #1#)
*
Above shows that the first and third sublists are the same.
Running it in the REPL is left as an exercise. It may show different results.
In ANSI Common Lisp the File Compiler is allowed to coalesce similar list data. (a a a) and (a a a) are similar. This may save memory space in a compiled program. Not every Common Lisp implementation does that, but SBCL does it. Remember, when the book Common Lisp the Language, 1st edition was published in 1984, the first Apple Macintosh had just 128KB RAM.
Solution: use COPY-TREE:
To create a fresh & non coalesced copy of the nested list use the function COPY-TREE. Fresh means that it is not literal data and thus one is allowed to modify it. COPY-TREE copies all levels of a cons tree, COPY-LIST only copies the top list. Since your data is nested, we need COPY-TREE:
(defparameter *var*
(copy-tree '((a a a) (a x a) (a a a))))
When you execute:
(setf (caar *var*) 'c)
You are relying on undefined behavior, because you are mutating a literal, constant value. This is explained in the specification of QUOTE but the same applies to all literal values:
The consequences are undefined if literal objects (including quoted objects) are destructively modified.
More generally you have to take care of ownership when deciding if you have the right to mutate or not a list (or any object). If you know that a list was just freshly consed, you can mutate it but sometimes the list is directly given to you and you should refrain from touching it. This is the case for example for &rest lists (see APPLY):
conforming programs must neither rely on the list structure of a rest list to be freshly consed
You can often avoid mutations by consing element in front of an existing list (if the list is supposed to be a property list (plist) or an association list (alist)). For example in case your function accepts a keyword argument named a:
(defun foo (&key a) (list a))
Then you can call it with as many :a as you want, only the first is taken into account:
(foo :a 3 :a 2 :a 1)
=> (3)
(apply 'foo (list :a 3 :a 2 :a 1))
=> (3)
But in cases where you do want to change the list significantly, you must use functions that produce a fresh copy (like remove or copy-list).

With applicative order, what order are the arguments evaluated? Left to right or right to left?

In SICP part 1.1.5 The Substitution Model for Procedure Application I am curious about the applicative order of evaluation.
I understand that applicative order evaluates the arguments before applying the outer procedure.
My question is what order does it go through the arguments?
For example,
(+ (+ 2 1) (/ 10 2))
Will (+ 2 1) or (/ 10 2) get evalutated first?
I assume that you are still on chapter 1 of the book. Rest assured that the rest of the book will explain this to you in greater detail. For now, you may be interested in this footnote from section 3.2.1 The Rules for Evaluation:
... this order [left to right or right to left] should always be considered to be an implementation detail, and one should never write programs that depend on some particular order. For instance, a sophisticated compiler might optimize a program by varying the order in which subexpressions are evaluated.
Later chapters discuss this question is increasing detail. For example:
Exercise 3.8: "Define a simple procedure f such that evaluating (+ (f 0) (f 1)) will return 0 if the arguments to + are evaluated from left to right but will return 1 if the arguments are evaluated from right to left"
Exercise 4.1 - Change the order of evaluation in the metacircular evaluator.
Section 5.4.1 The Core of the Explicit-Control Evaluator (subsection Evaluating procedure applications) - Shows how procedure application can be implemented in an explicit control evaluator. Here you can clearly see how the details of the argument-evaluation loop determine the evaluation order.
In your specific example, x is evaluated before y since the two define are evaluated in sequence.
In a function call, like: (+ (+ 2 3) (- 4 5)) the order of the evaluation of (+ 2 3) and (- 4 5) is unspecified in Scheme, as from the other answer. while in other lisp languages, like in Common Lisp, is from left to right.
It is not specified.
In subsection procedure calls, you can find the very specification.
When a procedure call is evaluated, the operator and operand expressions are evaluated (in an unspecified order) and the resulting procedure is passed the resulting arguments.

Scheme : How to quote result of function call?

Is it possible to quote result of function call?
For example
(quoteresult (+ 1 1)) => '2
At first blush, your question doesn’t really make any sense. “Quoting” is a thing that can be performed on datums in a piece of source code. “Quoting” a runtime value is at best a no-op and at worst nonsensical.
The example in your question illustrates why it doesn’t make any sense. Your so-called quoteresult form would evaluate (+ 1 1) to produce '2, but '2 evaluates to 2, the same thing (+ 1 1) evaluates to. How would the result of quoteresult ever be different from ordinary evaluation?
If, however, you want to actually produce a quote expression to be handed off to some use of dynamic evaluation (with the usual disclaimer that that is probably a bad idea), then you need only generate a list of two elements: the symbol quote and your function’s result. If that’s the case, you can implement quoteresult quite simply:
(define (quoteresult x)
(list 'quote x))
This is, however, of limited usefulness for most programs.
For more information on what quoting is and how it works, see What is the difference between quote and list?.

Why do they quote empty lists in Scheme?

I'm going through this Scheme tutorial and in section 3 (Making Lists) the guy says you should write '() to represent an empty list. But for every test I've wrote seems that it has the very same effect as using just ().
Also, as far as I understand, the quote means the interpreter won't evaluate the expression, but seems that the interpreter knows what's after the ' symbol, because doing this (cons 1 '()) yields (1), while doing this (cons 1 'abc) yields (1 . abc), so it knows '() is an empty list but 'abc is not.
Some Scheme implementations permit bare () as a synonym for '(), but only the quoted form is standard.
As for your second question: consider
(define abc '(1 2 3))
(define def '(1 2 3))
(cons 0 'abc)
(cons 0 'def)
(cons 0 abc)
(cons 0 def)
In the first two expressions, abc and def are not evaluated, so they stay symbols. In the latter two, they are evaluated to the objects they stand for, which are both equal to the list (1 2 3).
TL;DR: To make sure your applications work as as designed you should quote the empty list since it's unsure if it will work otherwise. see the long answer below.
As for how Scheme works for quoted values, quoting '(+ 3 4 5) makes an expression a constant that is not to be evaluated. It much like making a string with code in it, like "if( a == 0 ) return 4;" in Java or C. The difference is that a quoted expression are structured data rather than byte sequences.
(cons 1 'abc) and (cons 1 '()) does the same. A cons has two placeholders for values and those two expressions sets two values in the exact same manner. It's only display (and the repl) that knows that a list that ends with () should display differently and not (1 . ()) like it actually is stored.
The long answer about the need to quote the empty list
It all boils down to the standard you're using. Most implementations today are R5RS and it requires the empty list be quoted since the empty list is not an expression. Implementations might still allow it though since it won't interfere with a proper Scheme application. Heres a quote from the R5RS report:
Note: In many dialects of Lisp, the empty combination, (), is a
legitimate expression. In Scheme, combinations must have at least one
subexpression, so () is not a syntactically valid expression.
This actually happened in R3RS (under Procedure calls) so it's been around for a while. When looking for it in R6RS however it seems to have disappeared from the section making me think they have reverted it so that it would be self evaluating. However, I cannot find it in the language changes part.
When looking at the R7RS draft (NB: PDF), the part from R5RS is back so I guess this was an error in the R6RS report. This might be the reason racket (and probably other implementors) allow () as an expression in R6RS to be sure it will work even when the report is ambiguous about it.

Self-referential data structures in Lisp/Scheme

Is there a way to construct a self-referential data structure (say a graph with cycles) in lisp or scheme? I'd never thought about it before, but playing around I can find no straightforward way to make one due to the lack of a way to make destructive modification. Is this just an essential flaw of functional languages, and if so, what about lazy functional languages like haskell?
In Common Lisp you can modify list contents, array contents, slots of CLOS instances, etc.
Common Lisp also allows to read and write circular data structures. Use
? (setf *print-circle* t)
T
; a list of two symbols: (foo bar)
? (defvar *ex1* (list 'foo 'bar))
*EX1*
; now let the first list element point to the list,
; Common Lisp prints the circular list
? (setf (first *ex1*) *ex1*)
#1=(#1# BAR)
; one can also read such a list
? '#1=(#1# BAR)
#1=(#1# BAR)
; What is the first element? The list itself
? (first '#1=(#1# BAR))
#1=(#1# BAR)
?
So-called pure Functional Programming Languages don't allow side-effects. Most Lisp dialects are not pure. They allow side-effects and they allow to modify data-structures.
See Lisp introduction books for more on that.
In Scheme, you can do it easily with set!, set-car!, and set-cdr! (and anything else ending in a bang ('!'), which indicates modification):
(let ((x '(1 2 3)))
(set-car! x x)
; x is now the list (x 2 3), with the first element referring to itself
)
Common Lisp supports modification of data structures with setf.
You can build a circular data structure in Haskell by tying the knot.
You don't need `destructive modification' to construct self-referential data structures; e.g., in Common Lisp, '#1=(#1#) is a cons-cell that contains itself.
Scheme and Lisp are capable of making destructive modifications: you can construct the circular cons above alternatively like this:
(let ((x (cons nil nil)))
(rplaca x x) x)
Can you let us know what material you're using while learning Lisp/Scheme? I'm compiling a target list for our black helicopters; this spreading of misinformation about Lisp and Scheme has to be stopped.
Yes, and they can be useful. One of my college professors created a Scheme type he called Medusa Numbers. They were arbitrary precision floating point numbers that could include repeating decimals. He had a function:
(create-medusa numerator denominator) ; or some such
which created the Medusa Number that represented the rational. As a result:
(define one-third (create-medusa 1 3))
one-third => ; scheme hangs - when you look at a medusa number you turn to stone
(add-medusa one-third (add-medusa one-third one-third)) => 1
as said before, this is done with judicious application of set-car! and set-cdr!
Not only is it possible, it's pretty central to the Common Lisp Object System: standard-class is an instance of itself!
I upvoted the obvious Scheme techniques; this answer addresses only Haskell.
In Haskell you can do this purely functionally using let, which is considered good style. One nice example is regexp-to-NFA conversion. You can also do it imperatively using IORefs, which is considered poor style as it forces all your code into the IO monad.
In general Haskell's lazy evaluation lends itself to lovely functional implementations of both cyclic and infinite data structures. In any complex let binding, all things bound may be used in all definitions. For example translating a particular finite-state machine into Haskell is a snap, no matter how many cycles it may have.
CLOS example:
(defclass node ()
((child :accessor node-child :initarg :child)))
(defun make-node-cycle ()
(let* ((node1 (make-instance 'node))
(node2 (make-instance 'node :child node1)))
(setf (node-child node1) node2)))
Tying the Knot (circular data structures in Haskell) on StackOverflow
See also the Haskell Wiki page: Tying the Knot
Hmm, self referential data structures in Lisp/Scheme, and SICP streams are not mentioned? Well, to summarize, streams == lazily evaluated list. It might be exactly the kind of self reference you've intended, but it's a kind of self reference.
So, cons-stream in SICP is a syntax that delays evaluating its arguments. (cons-stream a b) will return immediately without evaluating a or b, and only evaluates a or b when you invoke car-stream or cdr-stream
From SICP, http://mitpress.mit.edu/sicp/full-text/sicp/book/node71.html:
>
(define fibs
(cons-stream 0
(cons-stream 1
(add-streams (stream-cdr fibs)
fibs))))
This definition says that fibs is a
stream beginning with 0 and 1, such
that the rest of the stream can be
generated by adding fibs to itself
shifted by one place:
In this case, 'fibs' is assigned an object whose value is defined lazily in terms of 'fibs'
Almost forgot to mention, lazy streams live on in the commonly available libraries SRFI-40 or SRFI-41. One of these two should be available in most popular Schemes, I think
I stumbled upon this question while searching for "CIRCULAR LISTS LISP SCHEME".
This is how I can make one (in STk Scheme):
First, make a list
(define a '(1 2 3))
At this point, STk thinks a is a list.
(list? a)
> #t
Next, go to the last element (the 3 in this case) and replace the cdr which currently contains nil with a pointer to itself.
(set-cdr! (cdr ( cdr a)) a)
Now, STk thinks a is not a list.
(list? a)
> #f
(How does it work this out?)
Now if you print a you will find an infinitely long list of (1 2 3 1 2 3 1 2 ... and you will need to kill the program. In Stk you can control-z or control-\ to quit.
But what are circular-lists good for?
I can think of obscure examples to do with modulo arithmetic such as a circular list of the days of the week (M T W T F S S M T W ...), or a circular list of integers represented by 3 bits (0 1 2 3 4 5 6 7 0 1 2 3 4 5 ..).
Are there any real-world examples?

Resources