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)).
Related
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)
I'm pretty new to Scheme and I'm currently working in DR Racket to learn it. So basically my problem is that I'm having trouble permanently changing global variable.
This is my change function:
(define (change b)
(set! b (- b 1)) b)
As you can note I return the value of a at the end of the function.
And this is the output on the console.
> (define a 4)
> (change a)
3
> a
4
As you can see, in the function it returned the value of 3 (4 - 1). But it seems as though the global variable didn't actually change when i call it after the function. How do I leave it changed? Thanks in advance.
First, Racket is NOT Scheme. They both are similar in this example, but they are very different languages. And calling them the same thing is similar to saying C and C++ are the same language.
Now, on to your actual reference.
The reason change doesn't appear to do anything is because you are passing the 'value' into b, rather than any actual variable.
If you want to pass the actual reference of a primitive like this what you need to do is to box it with the box function. Then you can use set-box! to do the actual mutation, and unbox to get the value in the box
Giving you the following function:
(define (change b)
(set-box! b (- (unbox b) 1)) b)
Now when you use the change function, the variable should update.
> (define a (box 4))
> (change a)
'#&3
> a
'#&3
> (unbox a)
3
(The '#& is just a compact way that the Racket repl says that the next value is in a box. Which is why we get 3 when you unbox it.)
There are plenty of other data structures to that will have the same effect, vectors, structs, etc. But for a single value box is the simplest.
You're not truly changing the global variable! you're just modifying a parameter, which for all practical purposes is acting as a local variable. If you want to modify the global one, don't pass it as a parameter:
(define a 4)
(define (change)
(set! a (- a 1))
a)
a
=> 4
(change)
=> 3
a
=> 3
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.
First time stackoverflow user but occasional lurker, hope you guys can help me out.
So the first part of my assignment is to drop all 'leading zeros' in a list.
ex: (0 0 0 0 0 1 0 1 0 1) -> (1 0 1 0 1)
To do this, I thought to use an IF statement to check whether the first element was a 0 or not, and to recursively call the rest of the list until the there were no more leading zeros. As I have basically no idea how to program in Scheme, through searching the internet, I came up with what you see below. However when I run it, DrRacket tells me there are no arguments- I assume this either a syntactical error.. or more likely, I have no idea what I'm doing. So, if you could help me out, I'd really appreciate it!
>(define zz
> (lambda (n)
> (if (= (car (n)) 0)
> (zz (cdr (n)))
> ((n)))))
>
>(remove '(0 0 0 0 1 0 1 0))
The error I get in DrRacket is:
"procedure application: expected procedure, given: (0 0 0 0 1 0 1 0) (no arguments)"
Again, thanks a lot! (P.S. Sorry if the formatting is a little odd...)
EDIT
Okay, changing up some stuff, I now get a "expects type as 1st argument, given: (0 0 0 0 0 1 0 1 0); other arguments were: 0" error flagged at my if statement.
>(define zz
> (lambda n
> (if (= (car n) 0) <----- here
> (zz(cdr n))
> (n))))
EDIT 2
>(define zz
> (lambda (n)
> (if (= (car n) 0)
> (zz (cdr n))
> n)))
It works, thank you very much!
(num) is not correct - you're trying to call 42 or whatever as a command. (Also, your if syntax is off; you may want to do read more code to get a better feel for the syntax).
This should compile:
(define remove
(lambda (num)
(if (= (car num) 0)
(remove (cdr num))
num)))
Parenthesis in Lisp are for calling functions, unless used in quotes.
Okay, the OP asked about a general rundown of the syntax for Scheme.
a - A symbol, which is looked up by the evaluator and substituted for its value. Some symbols (such as 42) evaluate to themselves.
'a - This "quotes" the symbol and transforms it into (quote a). quote prevents its argument from being evaluated - instead, the value a is returned. Not the string "a", not the result of looking up a, a itself. This also works for lists ('(1 2 3))
(if <expr> <true-value> <false-value>) - This evaluates <expr>, and sees if its value is truthy or not, and executes the corresponding value.
(cond (<expr> <true-value>)
...
(else <false-value>)) - This runs though its arguments, and evaluates the car of it to see if it is true. If it is, the value of evaluating the cdr is returned. Otherwise, it skips to the next value.
(define <name> <expr>) - Sets the value of evaluating the second argument to the name of the first argument.
(lambda <arg-list> <body>) - Creates a procedure which is the result of binding the arguments passed in to the names present in the second argument and evaluating the third argument.
(<func> <arg1> <arg2> ... <argn>) - If the evaluator finds out that none of the above patterns match, then it calls the car of the list as a function, with the arguments in the cdr.
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).