Frame 1:33 - How do we unify two lists? - scheme

I don't think it's been written anywhere how this is supposed to work.
We get:
(run* q
(==
'( ((pea)) pod)
`( ((pea)) ,q)))
In the quasiquote form pea is quoted so remains the symbol and q is unquoted so refers to the variable in run. Then q seemingly becomes pod.
How are these two lists then unified with each other? What's the mechanism behind that? Can I just superimpose two lists on each other and then say that the elements at index 1 become the same?
Also still a mystery why pea is double parensed.

The unification goal
(==
'( ((pea)) pod)
`( ((pea)) ,q))
is the same as
(==
(list (list (list 'pea)) 'pod)
(list (list (list 'pea)) q ))
so yes, it is "working through list structure", and no other kinds of structures -- just lists. This should be straightforward and plain enough to code by recursively going along the two lists in unison as long as the structure is the same and the sub-terms can be unified.
So the above goal succeeds, extending its argument substitution with the pairing of the variable q and its value, the symbol datum 'pod. But also,
(==
(list (list p ) 'pod)
(list (list (list 'pea)) q ))
would also succeed, extending its argument substitution with the pairing of the variable q the symbol 'pod as well as the pairing of the variable p with its value, (list 'pea) -- provided that p and q were indeed defined as logical variables, by run* or by fresh. Whereas
(==
(list (list "p" ) 'pod)
(list (list (list 'pea)) q ))
would fail.
The double parenthesizing has no special meaning at all.

Related

Racket count occurrences using `map`

Write a Racket function count-occurrences that consumes two lists of symbols and produces a list of
natural numbers measuring how many times items in the first list occur in the second list. For example:
(count-occurrences (list 'a 'b 'a 'q) (list 'r 'a 'b 'e 'b 'g))
=> (list 1 2 1 0)
I've been struggling with this question - how do I use map to do it, since for this question it's specified we can't use recursion.
My original idea was to do the following:
(define (count-occurrences los1 los2)
(map
(length (filter (lambda (x) (symbol=? x (first los1))) los2))
los1))
but using length here can only get us the number 'a occurred, instead of going into recursion. and for abstract functions there can only be one argument for the inside function, so I'm totally lost.
If ... x ... is an open formula, i.e. an expression which references an unbound variable x, wrapping it in a lambda form makes it a function in x, like so:
(lambda (x) ... x ... )
where x becomes bound by that lambda form; a parameter to this so called lambda function, which is to say, an anonymous function introduced by a lambda form.
So, the solution for your troubles is quite simple: recognize that
(length
(filter (lambda (x)
(symbol=? x (first los1)))
los2))
should actually be
(length
(filter (lambda (x)
(symbol=? x y))
los2))
where y refers to each of the elements of los1 in turn, not just the first one; and that it is then an open formula in y – that is to say, y is unbound, free, there. So we must capture it, and make it bound, by ... yes, enclosing this expression in a lambda form, thereby making it a function in y! Like so:
(lambda (y)
(length
(filter (lambda (x)
(symbol=? x y))
los2)))
And this is what gets mapped over los1.
With this simple tweak, your code becomes a correct, working function definition.
Does this fit your requirements and restrictions?
(define (count-occurrences lst1 lst2)
(map (lambda (e1)
(count (lambda (e2) (eq? e1 e2))
lst2))
lst1))
A good way to keep track of keys and values is with a hash-table. While it is possible to write count-occurrences using map and passing a lambda, being explicit may make it easier to see what is going on.
;;; list list -> list
;;;
(define (count-occurrences keys values)
;; Create data structure
(define ht (make-hash))
;; Initialize data structure with keys
;; Set the value of each key to zero
;; Since we have not started counting
(for ([k keys])
(hash-set! ht k 0))
;; Iterate over values and
;; Increment hash table if
;; When value is a key
(for ([v values])
(if (hash-has-key? ht v)
(hash-set! ht v (+ (hash-ref ht v) 1))
null))
;; Iterate over keys and
;; Create list of values
(for/list ([k keys])
(hash-ref ht k)))
Since recursion is prohibited, explicitly looping may make for more maintainable/readable code than an implicit loop. Besides, the variations of for are worth knowing. Hash tables have the advantage that duplicate keys read the same value and there is no need to track the same key twice.
One of the engineering advantages of using for rather than map is that it is easier to reason about the running time. The running time for this code is 2m + n where m is keys and n is values. Solutions using map will typically be m * n. There's nothing inherently wrong with that. But it is worth recognizing.

Inconsistent box-and-pointer diagrams in SICP

Structure and Interpretation of Computer Programs (SICP)'s box-and-pointer diagrams in Figures 3.16 and 3.17 don't appear equivalent (purely with respect to value, not memory) even though it says they are. ("When thought of as a list, z1 and z2 both represent "the same" list, ((a b) a b))", pg. 258)
(define x (list 'a 'b))
(define z1 (cons x x))
(define z2 (cons (list 'a 'b) (list 'a 'b)))
SICP diagrams the pair z1 like this:
and z2 like this:
The arrows in the pair, z1, don't both seem to be pointing to the entire pair, x. They don't even point to the same thing, despite both having received the same (memory and value) pair.
I would evaluate the first diagram as (a b), and the second as ((a b) a b)
I could guess that each arrow is actually pointing to the entire pair, x, but in figure 2.3 on page 98:
it very clearly points to an entire box by either pointing to the side or in between two items.
Am I understanding box-and-pointer diagrams incorrectly or something else entirely?
You're reading too much into it. :-) If it points into the box anywhere, assume it's a pointer to that cons cell. You cannot specifically point to the car or cdr portion of it.
Your last assumption is correct. The dot indicates where the pointer value is, the whole double box the arrow is pointing at is the target. It doesn't matter if it's pointing on the side, top middle, top left or top right. It's the whole pair that is the "address" of the object.
You can't point to a part of an object without accessing its part with car and cdr. The second you do that you have whatever it was pointed to and not a indirect pointer. (car '(a b)) ; ==> a and a doesn't have any essence of the list that still is pointing to it until it is garbage collected.
We could illustrate it like this instead:
[=#1|#3|#2]
[=#2|#3|()]
[=#3|a |#4]
[=#4|b |()]
The first value with =# is the location of the box itself, while the next two are car and cdr. Above, x points to the address #3 and z1 to #1. Let's make z2
[=#5|#6|#8]
[=#6|a |#7]
[=#7|b |()]
[=#8|#9|()]
[=#9|a |#10]
[=#10|b |()]
As you can see, z2 uses two more cons than z1 since it doesn't reuse the same object as both elements of its list, but uses individual similar-looking lists.
In the drawings, both car and cdr of z1 point to the same list x. z2 points to two different lists, but the elements in those lists are the same.
The reason for this is that symbols are singletons. Thus, you only have one symbol object for a and evaluating 'a in two different places will both point to the same a. Other singletons are #f, #t and ()
cons always creates a fresh pair and list is just a procedure that cons together the arguments. Thus the same code (list 'a 'b) two places in the expression makes two different objects that just look the same.
(eq? (car z1) (cdr z1)) ; ==> #t same object
(eq? (car z2) (cdr z2)) ; ==> #f not same object
(equal? (car z2) (cdr z2)) ; ==> #t they look the same, but they are not the same. (created at different places)
Quoted data can be seen as created all at once before the program starts. Thus this is undefined.
(eq? '(a b) '(a b)) ; ==> #t or #f (undefined)
(eq? '(b c) (cdr '(a b c))) ; ==> #t or #f (undefined)
The reason is that Scheme is allowed, but not obligated, to reuse data the same way as with the structure z1.

Why does `(= (car x) 'z)` work?

I was stumbling through the Arc tutorial when I got sort of confused with this:
Quoted from the Arc Tutorial:
Like Common Lisp assignment, Arc's = is not just for variables, but
can reach inside structures. So you can use it to modify lists:
arc> x
(a b)
arc> (= (car x) 'z)
z
arc> x
(z b)
But lisp is executed recursively, right? It says that car returns the first value in a list. So:
arc> (car x)
a
which makes sense, but then why isn't (= (car x) 'z) equal to (= a 'z), which would result in:
arc> a
z
arc> x
(a b) ; Note how this hasn't changed
but it doesn't. Instead, it appears that (= (car x) 'z) seems to have the effects of (= x (list 'z (car (cdr x)))):
arc> (= x '(a b))
(a b)
arc> (= (car x) 'z)
z
arc> x
(z b)
...
arc> (= x '(a b))
(a b)
arc> (= x (list 'z (car (cdr x))))
(z b)
arc> x
(z b)
So why exactly does (= (car x) 'z) work that way and what is it that I'm missing here?
Note: this is my first introduction to LISP.
= is a special operator, it's not a function. So its arguments are not evaluated according to the normal recursive process. The first argument is treated specially, it identifies a place to assign to, not the value already in that place. It may have to evaluate subexpressions within it to find the place, but once it gets to the place, it stops evaluating. The second argument will be evaluated normally, to get the value to assign there.
= appears to be an assignment operator in Arc, the equivalent in Common Lisp would be setf. In this case, (car x) returns the place that is to be modified:
? (defparameter x '(a b))
X
? x
(A B)
? (setf (car x) 'z)
Z
? x
(Z B)
See also here.
= is a macro or rather "special operator", which is just a fancy name for built-in macro. Macros' arguments (unlike functions' arguments) aren't evaluated at all, so the = operator gets (car x) unevaluated ==> it get's the list (car x) itself! Now, that = operator contains miniature code walker that traverses the list (car x) and figures out what place would be read from if the list was evaluated. And assigns to that place.
What does it assign? The result of evaluating the second argument, it evaluates that one manually.
So the effective evaluation scheme for = is in fact
(= <unevaluated-argument> <evaluated-argument>)
EDIT:
Another example of macro or special operator is if. in (if <cond> <a> <b>), if starts being evaluated first and gets arguments <cond>, <a> and <b> raw - unevaluated. Then it manually evaluates <cond> and depending on the result, it either evaluates <a> or <b> and returns result of that. If everything was really evaluated recursively, you could never have working if or cond or loop or short-circuit and and or and so on...
NOTE: = is probably (= I suppose) a macro and not special operator, at least its equivalent setf in common lisp is a macro. I doubt that P. Graham embedded = directly into the compiler. But it's not really important to know.
If you have the book "ANSI Common Lisp", there is such sentence in chapter 3.3 Why Lisp Has No Pointers:
One of Secrets to understanding Lisp is to realize that variables have values in the same way that lists have elements. As conses have pointers to their elements, variables have pointers to their values.
If x is assigned a list:
arc> (= x '(a b))
(a b)
It formulates as such, the variable x points to a list. The 1st position of the list points to the symbol a and the 2nd points to the symbol b:
When car of x is assigned with 'z in (= (car x) 'z), simply the 1st position points the new symbol z.
Finally, in the expression (= a 'z), a variable a is assigned and thus points to the symbol z

Meaning of 'quote in Lisp

This question arose when reading SICP. Why (list 'quote '(a b c)) evaluated by the interpreter (R5RS in Dr.Racket) as '(a b c). For me it should be (quote (a b c)). For instance (list 'quot '(a b c)) is evaluated as (quot (a b c)). What is so special in the 'quote?
You'll get different behaviors depending on exactly what Lisp you're using (Scheme, Racket, Common Lisp, etc.) but in general, the system will accept 'x as a shorthand or syntactic sugar for (quote x). The two forms are exactly equivalent and their values are the same: the unevaluated x. When a result is coming out of the system, it might choose to print in the first way to make the result more intuitive to the user. A similar thing happens with cons, too. For instance,
(cons 1 2)
;=> (1 . 2)
because that's the general way that cons cells (pairs) are printed. However, there's a special case defined for when the second part of the pair is another list (either the empty list () or another pair, and that's why we have the following. I've also written a bit more about how lists and cons cells are printed in an answer to Recursive range in Lisp adds a period?.
(cons 1 '())
;=> (1)
(cons 1 '(2 3))
;=> (1 2 3)
Now, I've written the values of the expression above. E.g., the value of the form (cons 1 '(2 3)) is the list (1 2 3). As an additional complication, some systems (I'm thinking of some languages is Dr. Racket, in particular) don't print the value of a form in the interactive prompt, but rather print a form that would produce the same (for certain interpretations of “the same”) values. For instance, you might evaluate '(1 . 2) and see the output (cons 1 2) because that's another form that would produce the same value. This can be helpful if you're doing pure functional programming that has referential transparency, but if you're not expecting it, it can lead to some confusion.
A good way to see that we're getting the results that we should, regardless of how the system prints them, is to inspect them. We expect that (list 'quote '(a b c)) should return a list whose car is the symbol quote and whose cadr is the list (a b c). This is what we get (in Dr. Racket 5.3 with language R5RS):
> (display (list 'quote '(a b c)))
'(a b c)
> (display (car (list 'quote '(a b c))))
quote
> (display (cadr (list 'quote '(a b c))))
(a b c)
We get similar results if we use 'qmmmt instead of 'quote:
> (display (list 'qmmmt '(a b c)))
(qmmmt (a b c))
> (display (car (list 'qmmmt '(a b c))))
qmmmt
> (display (cadr (list 'qmmmt '(a b c))))
(a b c)
The only difference is that in the first case, display displays the list whose car is the symbol quote using the shorthand that is available for such lists. That is, instead of displaying (quote (a b c)) it displayed '(a b c).
'(a b c) and (quote (a b c)) are actually different notations for the same. So don't be surprised if your Lisp prints the shorter version.
In general '<something> is the same as (quote <something>).
QUOTE is used in Lisp to mark expressions which should evaluate to themselves. Usually a list would be a function or macro call and a symbol would be a variable. If you want to treat those as data, you need to quote them.
Since (quote <something>) is used so often in Lisp, the abbreviated version '<something> has been introduced to save a bit of typing or reading...
display emits some behaviors. Eg. '(a . (b . (c . ()))) is displayed (a b c). 'quote is displayed quote and perhaps '(quote x y) is displayed (quote x y) while '(quote x) is displayed 'x or (quote x). Which one is implementation dependent but both mean the same.
As data (ie. quoted, like (quote quote) and it's abbrivation 'quote) the result of the evaluation, the symbol quote is nothing special, for any LISP, just like '+ and 'potato happen to be the symbols + and potato. Any symbol that mean something when not quoted is no special when quoted.
It also took me a while to understand this problem. But it's just your good-hearted lisp interpreter showing (quote (a b c)) in it's equivalent form '(a b c). Since there is no such equivalence/syntactic sugar for (quott (a b c)), it's shown as is.

Error: Can't bind name in null syntactic environment

I'm currently going through exercise 1.3 of the sicp book. Here's the description of the problem:
Define a procedure that takes three numbers as arguments and returns
the sum of the squares of the two larger numbers.
I tried to solve it with the following code
(define (square x) (* x x))
(define (sq2largest a b c)
((define large1 (if (> a b) a b))
(define small (if (= large1 a) b a))
(define large2 (if (> c small) c small))
(+ (square large1) (square large2))))
When I ran it in mit-scheme, I got the following error:
;Can't bind name in null syntactic environment: large1
#[reserved-name-item 13]
Googling this error doesn't yield many results. Does anyone know what's wrong with my code? (I'm not familiar with Scheme)
I'll try to break down the structure of your sq2largest procedure:
The basic structure is:
(define (sq2largest a b c)
; Body)
The Body you wrote is:
((define large1 (if (> a b) a b)) ; let this be alpha
(define small (if (= large1 a) b a)) ; let this be bravo
(define large2 (if (> c small) c small)) ; let this be charlie
(+ (square large1) (square large2)) ; let this be delta) ; This parentheses encloses body
So, the Body is structured as:
(alpha bravo charlie delta)
Which translates to: "Pass bravo, charlie and delta as arguments to alpha."
Now, alpha is being told to take a bunch of arguments, but inside the namespace reserved for large1, no provision was made for any argument... i.e. scheme encounters a null syntactic environment where it cannot bind any variable.
Parentheses are significant in Scheme (and most, if not all, Lisps) because they define the scope of a procedure and enforce[1] the order of application of operations.
[1] "No ambiguity can arise, because the operator is always the leftmost element and the entire combination is delimited by the parentheses." http://mitpress.mit.edu/sicp/full-text/sicp/book/node6.html
You have too many brackets. If you took out the extra brackets around the internal defines, things should work a lot better.

Resources