Scheme expression evaluation - scheme

I am going through the book - The Scheme Programming Language, 4th Edition. In an exercise, there is an expression ((car (list + - * /)) 2 3). Below are the steps in which I believe the expression will be evaluated. Please let me know if my understanding is correct.
The expression (list + - * /) is evaluated to a list of procedures: (+ - * /). (I understand that list always produces a "proper list", could someone please state a few differences between using list and cons?)
The expression (car (+ - * /)) is evaluated to the symbol + which evaluates to a procedure. (I don't really understand how (car (+ - * /)) is evaluated, typing (car (+ - * /)) at the REPL prompt produces an error).
The expression (+ 2 3) is evaluated to 5.
I would like if I could get some other / in depth explanation.

Yes! However the procedures doesn't have literal representation so when you evaluate + you get some crazy textual representation like #<primitive-procedure-+> and copying it and pasting it into the repl won't give you the same object back. The same with lists. When you evaluate (list 1 2 3) you get (1 2 3) but you cannot just write (1 2 3) since it will think it should call 1 as a procedure with two arguments. (list 1 2 3) makes (cons 1 (cons 2 (cons 3 '()))) a chain of nested pairs. That the last cdr is () is what makes it proper. Thus the primitive that allows list to do it's thing is cons.
Wrong. You have an evaluated expression (list + - * /) to something like (#<primitive-procedure-+> #<...> #<...> #<...>). A list of evaluated variables and you now see their visual representations. Doing car on it gives you the first object #<primitive-procedure-+> which is the same you get when you evaluate the global variable +. There are no symbols involved in this step. The previous step didn't involve symbols either since bare symbols are variables. 'test becomes a symbol while test becomes whatever the variable pointed to. All procedures by name are just variables getting evaluated before application. It's the default behaviour in Scheme.
Since the object is the same as the value + is it will add the rest of the operands together after they have been evaluated. Since they all are numbers the arguments passed to apply stay the same, but if you have expressions there like (+ (* 3 3) (* 4 4)) then the operands like (* 3 3) need to get evaluated and it's result is what is applied.
You can apply substitution rules. It's not what the Scheme interpreter does, but any variable can be replaced by the value it has and every expression can be replaced by its result as long as you do not mutate anything:
((car (list + - * /)) (- 5 2) (/ 4 2)) ; == (car (list + - * /)) evaluates to the same value as the variable +
(+ (- 5 2) (/ 4 2)) ; == (- 5 2) evaluates to 3, (/4 2) evaluates to 2
(+ 3 2) ; == (+ 3 2) evaluates to 5
; ==> 5 (the result)
Notice I substitute (car (list + - * /)) with the variable + and not a symbol. They both are the same: (eq? (car (list + - * /)) +) ; ==> #t

The stepper in DrRacket is the perfect tool for exploring evaluation order.
The stepper allows you to see the effect of one evaluation step at a time.
You can even step backwards.
The stepper however only works in the Beginner and Intermediate languages.
The image is from the following program using the Intermediate language.
(car (list + - * /))
(+ 2 3)

Related

Why is the word "list" showing up in my results?

Very new to Scheme, so I'm sorry for a basic question. Whenever I print out something as a test, my result always contains the word "list" in the list that is printed.
My code:
(define get-lower-half
(lambda (lst n)
(if (< n (quotient (length lst) 2))
(cons (list-ref lst n) (get-lower-half lst (+ n 1)))
'())))
(get-lower-half '(1 2 3 4 5) 0)
My result is then:
(list 1 2)
instead of just
(1 2)
The examples of using cons I find online don't have this problem, what the heck am I doing wrong here? I'm using DrRacket as my IDE with Intermediate Student with Lambda as the language.
I'm pretty sure you're expecting '(1 2) (a list), and not (1 2).
(1 2) is not a valid procedure in Racket or in the intermediate language.
In the intermediate language, lists are represented with the list procedure, (list 1 2) and not '(1 2) like in regular Racket. What you are seeing is regular intermediate language behaviour.
In Scheme there are the concepts of datum and datum syntax.
A datum is the mathematical part of an object. For example, the number 3 or the pair (x y) is a datum. A datum syntax is a way to represent datum. For example, #x03 or 3 or #b11 are datum syntax for representing the datum 3. In the same way, the datum (x y) can be represented in syntax as (x y) or (x . (y . ())).
The scheme output has many options to print the datum. Some output functions print the datum such that what they print to be valid code that creates the given datum or they can print the datum as valid syntax as data that will create that datum.
See io-ports and datum definitions.

Why does '(1 2 3) evaluate to a list en Lisp (Scheme)?

The quote (') is used to introduce a pre-evaluated value, so (quote x) results in the symbol x and not what the symbol evalutes to.
Numbers, Booleans, characters and strings are self-evaluating in Scheme, so quoting them doesn't matter.
But why does (quote (1 2 3)) or (quote ()) answers #t to the predicate list?.
Should't the result be a "pre-evaluated" value? But in this case (1 2 3) has actually been evaluated to (list 1 2 3)?
Thank you.
pre-evaluated value
I'm not sure where you got that term from. I've never used it. It's not "pre-evaluated", it's unevaluated.
This is really all works from the fact Lisp (and Scheme) is Homoiconic: the structure of the program really uses lists and atoms underneath.
quote is the dual to eval: (eval (list '+ '1 '2 '3)) (and since a quoted number is just the number, (eval (list '+ 1 2 3)) does it as well) is the opposite of (quote '(+ 1 2 3)).
An evaluated list is a call, so an unevaluated call is a list.
Should't the result be a "pre-evaluated" value? But in this case (1 2 3) has actually been evaluated to (list? 1 2 3)?
You're missing some parentheses here! You get (list? '(1 2 3)) (or (list? (quote (1 2 3)). That is, (list? (list 1 2 3)). Which is true.
You can check the opposite with (eval (list '+ 1 2 3)): you get 6.
Note: Some values just evaluate to themselves (like numbers or functions. You can throw eval at it as many times as you want, and it won't change a thing: (eval (eval (eval 1))) is just 1.)
(quote (+ 1 2 3)) = '(+ 1 2 3) = (list '+ '1 '2 '3) = (list '+ 1 2 3) (numbers are self-evaluating, i.e. evaluating to self).
(eval '(+ 1 2 3)) = (+ 1 2 3) = 6. And (eval '(1 2 3)) = (1 2 3) = error.
The first identity is just syntactical. The central identity here is the second one, '(+ 1 2 3) = (list '+ '1 '2 '3). It holds because everything is evaluated in Lisp, but before that, it must be read. Which means, converted from textual source code to actual data structures.
Since ( ... ) parentheses denote lists, reading ( ... ) forms creates lists. Then, evaluating the quoted form just returns that form as is (i.e. non-evaluated). The token + gets read as a symbol +; the literals 1, 2, 3 get read as numbers 1, 2, 3. So the end result is the same as the result of evaluating the form (list '+ '1 '2 '3).
And of course all this still applies without the + inside, as well.
The quote introduces an unevaluated value, not pre-evaluated, whatever that means.
When the expression (quote X) is treated as a form to be evaluated, it simply evaluates to X itself. X is not treated as a form to be evaluated to a value, but rather the resulting value is the syntax X itself.
Quote is a way of the program expressing, "I want to use a piece of my own syntax as a value". And that's precisely what a "literal" is in computer science: a piece of program text reflected back into the program as a run-time value.
In Lisp, atoms other than symbols denote themselves when evaluated. The syntax 3 evaluates to the integer 3. They are the same thing: Lisp syntax is a data structure, and in that data structure, an integer literal 3 is already represented by the object that it denotes.
Thus, under evaluation, there is no difference between (quote 3) and just 3. "Give me the syntax 3 itself" and "give me the value of the syntax 3" are the same: just 3.
Under (quote (1 2 3)), the syntax being quoted is (1 2 3). That syntax is the list object that it looks like; quote just regurgitates it. If were to evaluate the (1 2 3) form, it would be an error: it looks like 1 is being used as an operator or function, with arguments 2 and 3. When quote is itself evaluated, it suppresses this evaluation and just yields the (1 2 3) as-is.
Because the (1 2 3) is a piece of the program syntax, however, there is a restriction in the language that this list may not be modified. An operation like (inc (car (quote (1 2 3)))) which tries to change the list to (2 2 3) invokes undefined behavior. Essentially, the program is trying to modify its own syntax; if for a moment we disregard the additional complexity that Lisp is a compiled language, this is de facto self-modifying code.

What does '(list 1 2) means in Scheme?

I'm studying SICP and at the beginning of section 2.2.2 it gives the following code: (cons '(list 1 2) (list 3 4))) and says it constructs a list like ((1 2) 3 4). But when I typed it into DrRacket(I'm using Racket here actually) it produces '((list 1 2) 3 4) and if I write (cons (list 1 2) (list 3 4)) then it'll be alright. I know in Scheme '(1 2) is equal to (list 1 2) but what does '(list 1 2) mean?
It should mean "a list consisting of the atom list, the atom 1, and the atom 2". Until Scheme evaluates the list (which the single quote prevents), it doesn't treat "list" differently from any other string.
Scheme has a convenient syntax for representing data literals: prefix any expression with ' (single quote) and the expression, rather than being evaluated, will be returned as data
For more informations:
http://courses.cs.washington.edu/courses/cse341/04wi/lectures/14-scheme-quote.html
Fix output style
First off, When you use the #!racket language in DrRacket, the default way of printing is not printing it's representation but an expression that evaluates to the same. You can turn it off from the menu language >> choose language. You select Show details and under Output style you select write
After pressing Run, when evaluating 'test you will get the output test.
Typo in expression
In section 2.2.2 there is an expression (cons (list 1 2) (list 3 4)). It is not the same as what you wrote in the question, (cons '(list 1 2) (list 3 4)). While an expression (list 1 2) applies the procedure list with values 1 and 2 and thus becomes (1 2), the expression '(list 1 2) just return the quoted data (list 1 2) unchanged.
Thus:
(cons (list 1 2) (list 3 4)) ; ==> ((1 2) 3 4)
(cons '(list 1 2) (list 3 4)) ; ==> ((list 1 2) 3 4)
'(cons '(list 1 2) (list 3 4)) ; ==> (cons '(list 1 2) (list 3 4))
The notation 'foo makes a symbol named foo.
The notation '(foo bar) makes a list with two symbols named foo and bar.
In the same way '(list foo bar) makes a list of three symbols. The symbol 'list happens to be called list.
Now (list 'foo 'bar) makes a list of two symbols called foo and bar.

Are these 2 expressions using quotation and list the same when evalulating expressions?

Are these 2 expressions using quotation and list the same when evaluating the expression such as a derivative?
The intrepreter outputs the same values for both:
(define a '(+ 3 4))
(define b (list '+ 3 4))
a
b
(car a)
(car b)
Output:
=> (+ 3 4)
=> (+ 3 4)
+
+
For these expressions:
(define a '(+ 3 4))
(define b (list '+ 3 4))
Do they have the same value? yes:
(equal? a b)
=> #t
Do they refer to the same object? no:
(eq? a b)
=> #f
I guess that you want to somehow process the lists (say, for calculating a derivative). It doesn't matter how you created the lists as long as you're only interested in treating them as lists of symbols, and you can safely switch back and forth between either representation. It'd be different if you were to treat the operators as actual procedures, these are different things:
(define a '(+ 3 4))
(define b (list + 3 4)) ; quote was removed
(equal? a b)
=> #f
Consider this example:
(define a '(+ 3 4))
(define b (list '+ 3 4))
(define c '(+ 3 4))
Here a will point to an immutable* list (+ 3 4). b will point to a list whose elements are the same as a but it's produced when that statement is evaluated (a can exist before the program runs since it's a constant and for a compiled program the order and how it gets produced is not important). In b you are guaranteed that all the cons cells are newly created and unique. Thus (equal? a b) ; ==>#t while (eq? a b) ; ==> #f.
The output of (eq? a c) is undefined. Some Scheme implementations will create a new immutable list while others will point to the same list created earlier because they are both immutable according to the spec.
*Immutable by the specifications in the Scheme standard but this is seldom enforced so many implementations lets you alter immutable data with undefined behavior as consequence.

have a function in Scheme return value (or do something else) and call itself

I would like to have two expressions evaluated in function body. How would I go about it?
Given the following:
(define (f)
((+ 2 2) (+ 4 4)))
I would like both to have 2+2 and 4 + 4 evaluated (obviously the above doesn't work).
Basically, if I understand it correctly, in a spot where I can get a single thing done, I would like to have two things done. For example instead of calling just one function as a consequent in the if expression, I'd like to call two functions. Or ideally return a value and have the function call itself.
I am not sure if this makes sense but conceptually having such a mechanism seems plausible.
The body of a procedure evaluates from top-to-bottom, no matter how many expressions are at the beginning, only the value of the last one is returned. For instance, if we write this:
(define (f)
(+ 2 2) ; evaluates to 4, but we don't do anything with it, so it's lost
(+ 4 4)) ; evaluates to 8, this is the returned value
... When we call (f) the returned value is 8, the first expression's value is lost. Perhaps you meant to say, that you want multiple values returned? this is possible depending on the interpreter, for instance in Racket:
(define (f)
(values (+ 2 2) (+ 4 4)))
(f)
=> 4
8
Now (f) returns two values, if we are going to use them, we need special forms to "capture" the multiple returned values. In this example, I'll use let-values:
(let-values (((x y) (f))) ; 4 is bound to x, 8 is bound to y
(+ x y))
=> 12
Another interpretation of your question, regarding the use of an if expression: if you need to write more than one expression inside an if, then you have to pack all the expressions inside a begin form (by the way: the body of a procedure is implicitly inside a begin).
But again, even tough all the expressions are executed in sequence, only the value of the last one is returned as a result - so all the expressions in the middle should be executed only for the effect, not for the value. For example:
(if (= 1 1) ; condition is true
(begin ; execute a sequence of expressions
(+ 2 2) ; evaluates to 4, but the value is lost
(+ 4 4)) ; evaluates to 8, this is the returned value
(begin
(+ 1 1)
(+ 3 3)))
=> 8
Of course, in the above example it'd be simpler to just use a cond, which has an implicit begin. This is equivalent to the previous snippet:
(cond
((= 1 1) ; condition is true, implicit `begin`
(+ 2 2) ; evaluates to 4, but the value is lost
(+ 4 4)) ; evaluates to 8, this is the returned value
(else
(+ 1 1)
(+ 3 3)))
=> 8
I am not sure I understand what you mean, you simply call the functions one after another:
(define (f)
(display "calling-function-1")
(newline)
(display "calling-function-2"))
Output:
Welcome to DrRacket, version 5.3.5 [3m].
Language: SICP (PLaneT 1.17); memory limit: 128 MB.
> (f)
calling-function-1
calling-function-2
If you did this with addition:
(define (f)
(+ 2 2) (+ 4 4))
It would still work correctly, and just return the last value:
Welcome to DrRacket, version 5.3.5 [3m].
Language: SICP (PLaneT 1.17); memory limit: 128 MB.
> (f)
8
If you want to evaluate a sequence of expressions in a place where only a single one is allowed (i.e. an if consequence), you need to use begin. This isn't the case for the body of a define.

Resources