scheme apply to a list including elements with quote - scheme

I am working on a scheme project and I encountered with a problem with quotes.
When I use (apply + '(1 2 '3)) racket gives an error, on the other hand (+ 1 2 '3) works fine. At some point in the project I need to be able to do something like (apply + '(1 2 '3)) since I am taking the values from a given file and I have no freedom to use (+ 1 2 '3). I tried to write an add function that adds all the values in the list but it didn't work either. How can I solve this problem?
Thanks.

'x is an abbreviation for (quote x). In early lisps it was a reader macro and today some print routines will actually print (quote x) as 'x for convenience. Even when the printer chooses to print it as an abbriavtion it still a list with two elements so (car ''x) is quote.
(+ '1 '2 '3) works fine because all arguments are being evaluated. + gets evaluated to a procedural object #<+> (just a procedural representation of an implementation of global variable +), '1 evaluates to it's data, the number 1 and so on. In the end application of the procedure happens on the arguments (1 2 3). Numbers are self evaluating so if you were not to quote them 1 would evaluate to 1 and so on and you get the same result. Not all values are self evaluating.
With (apply + '(1 2 3)) all 3 arguments get evaluate. apply and + both to procedural objects and '(1 2 3) to the list (1 2 3). The procedure #<+> gets applied with the arguments (1 2 3)
With (apply + '(1 2 '3)) all 3 arguments gets evaluated. apply and + both to procedural objects and '(1 2 '3) to the list (1 2 (quote 3)). The evaluator only looks at the outer quote so the 3 is still quoted and now it's part of the data. The procedure #<+> gets applied with the arguments (1 2 (quote 3)). It won't work since #<+> only knows how to add numbers and not lists. You can expect a contract violation, an error of some kind.
When evaluated the result is data. If you have more quotes besides the outer one it isn't a language command any more but a list with the symbol quote and a second value. It's not handled specially like qith outer quotes.

The problem here is the meaning of the quote '.
The expression ' means "produce a value that prints as ".
For example '3 produces the value 3 since the value 3 is printed as 3.
In '(1 b) you get a list whose first element is the number 1 and whose second element is the symbol b.
Now you need to know one more thing about the quote. The quote is a reader abbreviation. When '<something> is read, the reader produces the form (quote <something>). This means that'(1 'b)produces the list(1 (quote b)). This is a list whose second element is the list(quote b), wherequote` is the symbol quote.
In your example you tried to (apply + '(1 2 '3)). The value produced by '(1 2 '3) is the list (1 2 (quote 3)). Since + adds only numbers, you got an error message.
If you want to read in numbers from a file, then read them as numbers and everything ought to be fine.

Related

OR/AND operation on lists in Racket

I want to understand what and and or represent in Racket when used with lists. When I do something like this -
> (or `(1 2) `(1 3))
'(1 2)
What is the result representing? I thought when we use or with two lists we would get a union of the lists. That is clearly not what is happening here. So, I thought it is interpreted as boolean values and that is why `(1 2) is not a false value. Hence, the result is `(1 2). But what about this? -
> (and `(1 2) `(1 3))
'(1 3)
How can I justify this?
or is looking for the first truthy value, checking arguments from left to right. Every value other than #false is truthy. If any is found, it's returned. In your example, '(1 2) is the first truthy value from the left, so it's returned.
Or called with no arguments returns #false, because no truthy values were found:
> (or)
#f
And checks whether all values are truthy, so it has to examine all of them, going from left to the right, and it can return #false (if any #false is found) or, if all values are truthy, last of them. In your example, '(1 3) is the last truthy value, so it's returned.
And called with no arguments returns #true, because no #false was found:
> (and)
#t
Read also the docs about or and and.
By the way, there is a difference between ' and `. First one is quote, the second one is quasiquote. In this very example, it doesn't matter, but you should know the difference between them.
And if you were really looking for union function, check racket/set library:
(require racket/set)
(set-union (set 1 2) (set 1 3))
=> (set 1 3 2)

How to create a lambda procedures?

I need to complete an assignment for my college course using Scheme. I've never coded in Scheme before so I have no clue what I'm doing. Our assignment is to define an anonymous function that computes the discriminant of a quadratic function. I keep running into the error: "Invalid `define'. Any help would be appreciated.
(define roots (lambda(abc))(
(lambda(discriminant))(
list(/(+(-b) discriminant)(*2a))
(/(-(-b) discriminant)(*2a))
)
(sqrt - (*bb)(*4ac))
)
First, you should learn a bit about what Scheme code looks like; find some example code (in your textbook, or online, or in answers here on SO) and notice how parentheses and whitespace are used. Then emulate that. You can't arbitrarily place parentheses or arbitrarily remove whitespace in Scheme (or in any Lisp).
For example, in the posted code (-b) gets two things wrong. First, -b is treated as one symbol, not as the negation of the value of b. Further, placing the symbol in parentheses indicates a procedure call; given an s-expression (f x), f is either a syntactic keyword (in which case (f x) is interpreted as a macro call), or (f x) is interpreted as a procedure call. If it is a procedure call and f is not bound to a procedure, then an exception is raised. So (-b) attempts to call a procedure named -b, which does not exist (unless you have defined it), raising an exception. You can use (- b), with a space between the - procedure and the symbol b; this evaluates to the negation of the value of b.
Similarly, *2a is interpreted as a symbol, not an expression; placing the *2a between parentheses is interpreted as a procedure call. The interpreter (or compiler) is expecting that *2a is a procedure which takes no arguments. You need to add the spaces: (* 2 a); this is interpreted as a call to the procedure * with the arguments 2 and a.
(*bb) and (*4ac) have exactly the same problems. The second case is interesting because when it is correctly written it illustrates one of the advantages of prefix notation. Since * is associative, it does not matter what order multiple values are multiplied in. To express naively 4 * a * c in prefix notation you could write (* 4 (* a c)), explicitly ordering the multiplications. You could also write this as (* (* 4 a) c), multiplying in a different order. It does not matter what order you multiply in, so you might as well just write (* 4 a c), so long as your language supports this notation. It turns out that Scheme and other Lisps do support this notation.
Another problem with s-expression notation in the posted code (after fixing the problems noted above): (sqrt - (* b b) (* 4 a c)). This is attempting to call the sqrt procedure on the arguments -, (* b b), and (* 4 a c). But sqrt is not a higher-order procedure (i.e., it does not take procedures as arguments), and it in fact only takes one argument. It was meant to apply the - procedure to the arguments (* b b) and (* 4 a c), subtracting them before taking the square root: (sqrt (- (* b b) (* 4 a c))).
The first lambda expression has a formal parameter list containing only one parameter: abc. As before, this is a mistake. The intention was to define three parameters: don't skimp on spaces: (lambda (a b c)).
The other significant problem is that there are syntax errors in the lambda expressions: (lambda (a b c)) has no body, but a lambda expression must have at least one expression in its body. This was probably intended to wrap the lambda expression which follows. Similarly, the inner lambda expression is missing its body. It was probably intended to wrap the (list ;;...) form that follows.
With that done, the inner lambda expression is itself inside of a pair of parentheses, taking the expression (sqrt (- (* b b) (* 4 a c))) as its argument. This is the lambda form of a let binding. Thus, the inner lambda takes one argument, discriminant, and evaluates the list form that is its body. Since the inner lambda expression itself occurs in the first position of an s-expression, it is part of a procedure call, and this inner anonymous procedure is then called on its argument, binding discriminant to the value obtained by evaluating that argument, which is (sqrt (- (* b b) (* 4 a c))). This all occurs inside of the outer lambda, which takes the three arguments a, b, and c. So, root is a function taking three arguments, and returning a list of roots, after binding the result of the discriminant calculation to discriminant (as a way of both simplifying the expression of the roots and ensuring that the discriminant need only be calculated one time).
Here is the fixed-up code. Note that I only added some spaces and added or moved a few parentheses; nothing else was changed:
(define roots
(lambda (a b c)
((lambda (discriminant)
(list (/ (+ (- b) discriminant) (* 2 a))
(/ (- (- b) discriminant) (* 2 a))))
(sqrt (- (* b b) (* 4 a c))))))
Pay attention to what this looks like. In Lisps you should almost never leave parentheses hanging on lines by themselves, and you should always place a space between arguments. Remember that everything is a procedure call.
Here is a sample interaction. Notice that you can represent negative numbers as -1 instead of (- 1) (you can do either if you wish). You just can't express a negative value using a variable as -b.
> (roots 1 0 -1)
(1 -1)
> (roots 1 8 15)
(-3 -5)

Racket variable memory

Given this code:
(define (wrapper n)
(define (sum-ints)
(set! n (+ n 1))
(display n)(newline)
(if (= n 3)
n
(+ n (sum-ints))))
(sum-ints))
Calling this procedure with n = 0
(wrapper 0) =>
1
2
3
6
I had expected the process to increment n to a value of 3, and then as it returns, add 3 to 3 to 3 for an output of 3 3 3 9.
Does the inner procedure store a shadow copy of n?
Oog, mutation is nasty. The issue here is that "plus" is evaluated left-to-right. Specifically, let's consider the case when n=2. The expression (+ n (sum-ints)) is evaluated left-to-right. First, the identifier + evaluates to the plus function. Then, n evaluates to 2. Then, the recursive call is made, and the result is 3. Then, we add them together and the result is 5.
You'll see the same result in Java, or any other language that defines left-to-right evaluation of subexpressions.
Solution to this particular problem, IMHO: don't use mutation. It's needed in only
about 10% of the cases that people want to use it.

define quote process in racket?

I have this couple of lines that I'm running on drracket,
I can't understand the output
> (define 'a 5)
> 'b
. . ..\..\Program Files\Racket\share\pkgs\drracket\drracket\private\rep.rkt:1088:24: b: undefined;
cannot reference an identifier before its definition
> '0
5
is quote redefined?
why 'b isn't working and '0 is 5?
First, symbols are atomic values. They cannot be treated like variables.
Anyway, your first line expands to:
(define (quote a) 5)
which is shorthand for defining functions in racket. So yes, you are redefining quote.
When you try to run 'b, you're running (quote b), where it expects a variable b to have some value, which is does not. That's why you receive the error, cannot reference an identifier before its definition.
When you try to run '0, you're running (quote 0). 0 is a valid value, and it becomes the value for a in your new function. So, the function evaluates as normal, and returns 5.
In other words, it's not just 0 that is a valid argument.
> (define 'a 5)
> (define b 12345)
> 'b
5
> '0
5
> '123454321
5
Check out the Racket documentation on symbols. Symbols don't contain values; they are values. You'll want to use variables instead ((define a 5)).

Why does Scheme have both list and quote?

Since (list 1 2 3) yields (1 2 3) and (quote (1 2 3)) yields (1 2 3), what is the rationale for having both?
Since Scheme is otherwise so spare, these must have some meaningful difference. What is that?
In the example you mentioned quote and list have the same result because numeric constants evaluate to themselves. If you use expressions that are not self-evaluating in the list (say variables or function calls), you'll see the difference:
(quote (a b c)) will give you a list that contains the symbols a, b and c while (list a b c) will give you a list containing the values of the variables a, b and c (or an error if the variables do not exist).
List creates a list, so (list 1 2 3) creates a three-element list.
Quote prevents evaluation. Without quote, the expression (1 2 3) would be evaluated as the function 1 called with arguments 2 and 3, which obviously makes no sense. Quote prevents evaluation and just returns the list, which is specified literally in its external printable form as (1 2 3).

Resources