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

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.

Related

just started learning Scheme

I don't know why this does not work. I get an error saying "Error: 1 is not a function[(anon)]"
(define (mem lst ele)
(cond ;if the list is empty return false
((null? lst) #f)
;if the first element is equal to the given element return true
;otherwise call the function with rest of the list
(else (if (= ele (car lst))
#t
(mem (cdr lst) ele)))))
(mem ’(1) ’(1 4 -2))
It works for me; how are you calling mem? I am guessing that you did something like: (mem (1 2 3 4) 1). Procedure calls always evaluate their arguments in Scheme, so in the procedure call (mem (1 2 3 4) 1) the expression (1 2 3 4) is evaluated; but lists are evaluated as if the first member is a procedure, so 1 is treated as a function; it is not, and this raises an exception.
You could quote the list: (mem (quote (1 2 3 4)) 1), or you can use the shorthand (mem '(1 2 3 4) 1). quote is a special form that does not evaluate its argument; instead it just returns whatever datum it is given. You can try this out at the REPL:
> (+ 1 2)
3
> (quote (+ 1 2))
(+ 1 2)
> '(+ 1 2)
(+ 1 2)
Here the naked expression (+ 1 2) evaluates to 3, but the quoted expressions just return the expressions given to quote. That is, (quote (+ 1 2)) evaluates to the expression (+ 1 2), not to the result of evaluating the expression (+ 1 2). In the case of (1 2 3 4):
> (quote (1 2 3 4))
(1 2 3 4)
> '(1 2 3 4)
(1 2 3 4)
> (1 2 3 4)
Exception: attempt to apply non-procedure 1
Type (debug) to enter the debugger.
The procedure call (mem '(1 2 3 4) 1) would evaluate the expression '(1 2 3 4) before passing that value to mem. Since the expression '(1 2 3 4) evaluates to a list, that list is the value which is passed to mem. This differs from the erroneous call (mem (1 2 3 4) 1), which attempts to evaluate the expression (1 2 3 4) by calling the (nonexistent) procedure 1 with the arguments 2, 3, and 4.
You could also use list to create the input: (mem (list 1 2 3 4) 1). list is also a procedure, and so it evaluates its arguments. Here the call to mem would evaluate the expression (list 1 2 3 4), and since list is a procedure the call to list would evaluate the arguments 1, 2, 3, and 4. Numbers are self-evaluating in Scheme, so the call to list would return a list (1 2 3 4); this list is the value passed to mem, which has now evaluated its argument (list 1 2 3 4).
Some Comments on the Posted Code
The cond form can take multiple conditional clauses, and there is no reason to use if here. Instead, you can do:
(define (mem lst ele)
(cond
((null? lst) #f)
((= ele (car lst)) #t)
(else
(mem (cdr lst) ele))))
The = predicate only works for numbers; to handle more general inputs you might choose equal?:
(define (mem lst ele)
(cond
((null? lst) #f)
((equal? ele (car lst)) #t)
(else
(mem (cdr lst) ele))))
Now you can work with, e.g., lists of symbols, or lists of lists:
> (mem '(a b c d) 'c)
#t
> (mem '(a b c d) 'e)
#f
> (mem '(1 (2 3) 4) '(2 3))
#t
> (mem '(1 (2 (3 4)) 5) '(2 (3 4)))
#t
> (mem '(1 (2 3) 4) 3) ;; does not descend into nested lists
#f
Note that changing the equality predicate to equal? will allow lists to be searched for at the top level of the input list, but no deeper. The list (2 (3 4)) can be found in the list (1 (2 (3 4)) 5) because it is at the top level of the list, i.e., (2 (3 4)) is an element of the list (1 (2 (3 4)) 5). But, (3 4) is not an element of the top level list, so the current mem procedure can't find it here. Another definition for mem would be needed to search within nested lists.
It seems from your example that you are looking for the list '(1 4 -2) in the list '(1), which should evaluate to #f. However your implementation expects all elements to be numbers since you compare with = which is a number only comparison procedure. If you want to compare any type you should use equal? which compares two objects of any type and supports comparing structures.
You were using an acute-accent instead of a single-quote for your literals.
#lang racket
(define (mem ele lst) ;; easier to read with one element -then- list
;; ..plus that's how you wrote your call to it,
;; so this arg-order makes more sense here.
(cond ;; cond doesn't need "else"
((null? lst) #f)
((if (= ele (car lst)) #t
(mem ele (cdr lst)))) ;; element, then list now
)
)
(mem 1 '(1 4 -2))
;; don't know why element needed to be wrapped in a '(1) literal list container
;; also literals require single-quote ' character, not the ’ acute-accent
https://docs.racket-lang.org/racket-cheat/index.html

Scheme create list of pairs using foldr without explicit recursion

I am learning a course of Scheme and have to do the following task. I have to write a function that gets two lists A and B in the same length and returns one list that every item inside is a list of two items - one from A and second from B.
For example the function gets '( 1 2 3) and '(4 5 6) and returns '((1 4)(2 5)(3 6)).
I can do that using map like this:
(define (func lst1 lst2) (map (lambda(x y) (list x y)) lst1 lst2))
But the the question is to do that by foldr and without explicit recursion.
Can anyone please help me? I have no idea how to do that....
Thanks!
The trick is knowing what to pass as a function parameter, here's how:
(define (func l1 l2)
(foldr (lambda (e1 e2 acc)
(cons (list e1 e2) acc))
'()
l1 l2))
Notice that we're passing two lists at the end of foldr, so the lambda expects three parameters: the current element from the first list (e1), the current element from the second list (e2) and the accumulated output (acc), which starts with value '(). The rest is easy, just build the output along using cons and list. It works as expected:
(func '(1 2 3) '(4 5 6))
=> '((1 4) (2 5) (3 6))

#<Closure> in output

I was writing a function to switch the last element of a list to the beginning:
(define last-elem
(lambda (l)
(car (reverse l))))
(define all-but-last
(lambda (l)
(reverse (cdr (reverse l)))))
(define (last-to-first x) (append (list last-elem x) (all-but-last x)))
(last-to-first '(1 2 3 4 5 6))
It didn't work and I knew why. I forgot to put the brackets around list last-elem x
The thing is, I was curious about the output of the wrongly-typed code:
(#<Closure> (1 2 3 4 5 6) 1 2 3 4 5)
What is the meaning if this? How did it come out to this?
In Racket, the output is
'(#<procedure:last-elem> (1 2 3 4 5 6) 1 2 3 4 5)
which is a little clearer.
A reference to a function is always stored with its referencing environment, a.k.a. as a closure, and your Scheme implementation chooses to display it that way.
(list last-elem x)
doesn't call the function last-elem. It simply returns a list of two elements: the value of the variable last-elem (which is a procedure) and the value of the argument x. You want:
(list (last-elem x))
But there's no reason to make a list in the first place. Try:
(define (last-to-first x)
(cons (last-elem x) (all-but-last x)))
In Scheme, all identifiers denote either a syntactic keyword (bound to a 'transformer') or a variable (bound to a value). In your code last-elem denotes a variable bound to a function, which you defined. When you write:
(list last-elem x)
the interpreter/compiler produces a list with the value of last-elem and x. Thus, the result of #<Closure> in the list.

On Scheme cons and dots notation

Given
#;> (cons (cons 1 2) 3)
((1 . 2) . 3)
When we try
#;> (cons 3 (cons 1 2))
(3 1 . 2)
What governs where the . is used? What would the memory representation of these constructs be?
Scheme implementations usually print things that look like lists in list form:
-> (cons 1 (cons 2 '()))
'(1 2)
In your example, (cons 3 (cons 1 2)) would be a list if it weren't for the last 2. So your implementation makes a best effort to print it as a list until the 2. The other example does not contain any part that looks like a list, so it just prints as nested pairs.

Are pair and list different in Scheme?

I wonder whether '(1 . 2) and '(1 2) mean the same data (equal to each other) in Scheme or not? I think they are the same thing, is this correct?
No, they are not the same.
'(1 . 2) means (cons 1 2)
whereas
'(1 2) means (cons 1 (cons 2 nil))
(1 . 2) is sometimes called an improper list, because it is not NIL terminated. (1 2) represented in dot form may be written (1 2 . NIL), but you should not write something like this.
dr rackect explains it much more clearer:
"A pair joins two arbitrary values.....The cons procedure constructs pairs"
(cons 1 2)
'(1 . 2)
(pair? (cons 1 2))
#t
on the other hand
"A list is a combination of pairs that creates a linked list. More precisely, a list is either the empty list null, or it is a pair whose first element is a list element and whose second element is a list."
(cons 0 (cons 1 (cons 2 null)))
'(0 1 2)
http://docs.racket-lang.org/guide/pairs.html
please LISP has been around since the 50's for accurate answers look at their documentation and example they area around for more than 60 years some people was not even born there.
Yes!
Pairs: (cons y z) creates a pair between the values y and z. Likewise, the (more complicated) expression (cons x (cons y z)) creates a pair between x and the pair (y . z). You can also represent these pairs as '(y . z) and '(x . (y . z))
Lists: A list is just a special type of pair. It's the case where a value is paired onto an already-existing list. Since the very first list has to start somewhere, we always have the null list '() (sometimes called the 'empty list') ready to be paired. So (cons y '()) pairs y with the null list to become the one-item list '(y). Likewise, (cons x '(y)) and (cons x (cons y '())) pair x to the list '(y) to become the list '(x y).
listspairs
List must end with empty list (also termed as null). Below sample code on repl illustrates the difference.
> (cons 1 (cons 2 '())) ; I am a pair as well as list
'(1 2)
(pair? (cons 1 (cons 2 '())))
#t
> (list? (cons 1 (cons 2 '())))
#t
> (cons 1 (cons 2 3)) ;I am a pair but but not list
'(1 2 . 3)
> (pair? (cons 1 (cons 2 3)))
#t
> (list? (cons 1 (cons 2 3)))
#f

Resources