Hello I have some homework that consists of extending a lisp interpreter. We are to build three primitives with pre-evaluated arguments ( for exemple <= ), and three primitives who do their own evaluation ( for example if ).
I went beyond the call of duty and created the only fun function in the bounds of this exercice : (defun) [it's the common lisp keyword for defining a user-function].
I would like to know if my algorithm for managing a user-defined function call is worthwhile.
In pseudo code, here it goes :
get list of parameters # (x y z)
get list of arguments # (1 2 3)
get body of function # (+ x (* y z))
for each parameter, arg # x
body = replace(parameter, argument, body) # (+ 1 (* y z))
# (+ 1 (* 2 z))
# (+ 1 (* 2 3))
eval(body) # 7
Are there better ways to accomplish this?
Thanks.
EDIT: replace() is a function recursing on sub-lists of body.
I never found better, no one proposed better, the question generated no interest whatever, and I'm on a rampage to close my opened questions, so here is the answer :
my algorithm was good enough.
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 currently trying to gain an understanding about side effects in general with regard to functional programming, racket to be exact. It's my understanding that it relates to changing the state of some variable, like a global one.
Here's some code that I've written;
; Define a variable with the value of 5
(define x 5)
; Define a function to add 1 to x
(define addX
(+ 1 x))
; Test out values
x
addX
x
Which outputs 5 6 5.
Shouldn't the last value be 6? Or is the fundamental principle that I'm missing, the fact that the value is stateless when using functional programming?
The way your code is written, you can think of x as a constant – ie, addX does not mutate the x binding.
It's like the same as (pseudocode)
constant X = 5
constant addX = X + 1
print(X) ; 5
print(addX) ; 6
print(X) ; 5
Functional programming requires the immutable data structures. If you approach scheme/racket with notions from other (imperative style) languages, you'll struggle and the code you produce will be very bad.
(+ 1 x) is an expression. The result of this expression, in the case where we have already (define x 5), is 6. That value just... percolates up to whatever tried to evaluate it. Whether we ask DrRacket to evaluate it, or we assign it to something else, like (define addX (+ 1 x)), what is changing is the expression is becoming the value.
So, if you want to assign a value to an identifier that is already introduced, you need to tell the interpreter to do this assignment. That form is set!, as in,
(define addX #f)
addX ; => #f
(set! addX (+ 1 x))
addX ; => 6
Learned to code C, long ago; wanted to try something new and different with Scheme. I am trying to make a procedure that accepts two arguments and returns the greater of the two, e.g.
(define (larger x y)
(if (> x y)
x
(y)))
(larger 1 2)
or,
(define larger
(lambda (x y)
(if (> x y)
x (y))))
(larger 1 2)
I believe both of these are equivalent i.e. if x > y, return x; else, return y.
When I try either of these, I get errors e.g. 2 is not a function or error: cannot call: 2
I've spent a few hours reading over SICP and TSPL, but nothing is jumping out (perhaps I need to use a "list" and reference the two elements via car and cdr?)
Any help appreciated. If I am mis-posting, missed a previous answer to the same question, or am otherwise inappropriate, my apologies.
The reason is that, differently from C and many other languages, in Scheme and all Lisp languages parentheses are an important part of the syntax.
For instance they are used for function call: (f a b c) means apply (call) function f to arguments a, b, and c, while (f) means apply (call) function f (without arguments).
So in your code (y) means apply the number 2 (the current value of y), but 2 is not a function, but a number (as in the error message).
Simply change the code to:
(define (larger x y)
(if (> x y)
x
y))
(larger 1 2)
Can someone try and explain these two functions: "define-type" and "type-case" in the PLAI scheme in racket? I'm a noob programmer and I don't really understand the documentation on the racket website. If anyone could provide examples, it would greatly be appreciated. Thanks.
Here is a little example of how to use define-type and type-case:
#lang plai
; A ListOfNumbers are either
; is either an empty list of numbers
; or is constructed to two things a, and, d,
; where a is a number and d is a list of numbers.
(define-type ListOfNumbers
(Empty)
(Cons (a number?) (d ListOfNumbers?)))
; construct a list of numbers as an example
(define a-list (Cons 42 (Cons 43 (Empty))))
a-list ; prints: (Cons 42 (Cons 43 (Empty)))
(type-case ListOfNumbers a-list
(Empty () "the list is empty")
(Cons (a d) (~a "the first number in the list is " a)))
; prints: "the first number in the list is 42"
I'm not super experienced with Lisp/Scheme/Racket, but it looks like this question is still unanswered after 5 years, so I'll give it a shot.
First of all, note that not everything is a function. For example, when you use define to define a function or some other value, define is not acting as a function. A function is something that takes some input, and then returns some output. define does not do this. Instead, it changes the environment that you're programming in such a way that a new name exists that can be used to refer to some value.
So for example, in...
(define cadr
(lambda (x)
(car (cdr x))))
... define modifies the programing environment so that the function cadr now exists. cadr is a function (if you invoke it with some input, it will yield some output), but define itself is not a function (you're not invoking define with some input in order to get some output).
With that distinction hopefully cleared up, define-type is not a function. It is similar to define in that it modifies the programming environment to make it so that you have new names to refer to certain values. It is used to define a new type, along with some functions the allow you to work with that type.
An example taken from the Racket documentation:
> (define-type Shape
[circle (radius : number)]
[rectangle (width : number)
(height : number)])
> (define (area [s : Shape])
(type-case Shape s
[circle (r) (* (* r r) 3.14)]
[rectangle (w h) (* w h)]))
> (area (circle 1))
- number
3.14
> (area (rectangle 2 3))
- number
6
Here it defines a new type Shape which it says has two variants: circle and rectangle. It further says that in the case of the circle variant, the interesting piece of data is its radius, which is a number; and in the rectangle variant, there's two pieces of data (or "fields"), which are its width and height (both numbers).
It then defines a new function area, which is expected to take a single input of type Shape (the type we just declared earlier). The type-case expression is used to specify how to compute the area of a Shape depending on which variant we're dealing with. If we're dealing with a circle then we can compute the area by squaring the radius and multiplying it by Pi. If we're dealing with a rectangle, then we can compute the area by multiplying its width by its height.
Earlier, I said define-type is not a function, but by virtue of using it, it defines a new type and a bunch of functions that allow us to work with that type. So what are these new functions it defines? See this example:
> (define c (circle 10))
> c
- Shape
(circle 10)
> (circle? c)
- boolean
#t
> (circle-radius c)
- number
10
> (define r (rectangle 2 3))
> (+ (rectangle-width r) (rectangle-height r))
- number
5
Here we then use define to modify the programming environment so that the name c refers to a circle we created with radius 10. circle? is a function that automatically got created when we did the define-type in the earlier example, and it returns whether or not the shape we're dealing with is a circle variant (as opposed to a rectangle variant). Similar, the circle-radius, rectangle-width and rectangle-height functions were automatically defined for us when we used define-type, which allow us to access the fields inside of the data type.
hy everyone, for school i have to make a function where lambda is used as a parameter
like so : (string (lambda ...) 5 40) where we have to fill in the dots
this is the function we had to reinvent, the regular string version
(define (string decoration n r) >string decoration is a function that creates a string with either fish or pumpkins hanging on the string
(define (decorations k) >decorations is the recursive function which hangs all the decorations together
(if (= k 1)
(decoration r 10) > here decoration is to be replaced with either a pumpkin or a fish as stated in the parameters
(ht-append (decoration r 10) > ht-append is a function that appends 2 figures Horizontally at the Top
(decorations (- k 1)))))
(hang-by-thread (decorations n))) > hang by thread is a function that hangs all the decorations at a string
all the names should be self-explanatory, the function takes a decoration , either a fish or a pumpkin and hangs it by a thread. But the fish has 3 parameters and the pumpkin has 2 which caused an error. So in a previous exercise we had to make an extra definition called fish-square which uses only 2 parameters to make a fish. Now we have to implement this same squared fish but with a lambda. Any help is greatly appreciated
(define (fish-square wh l) > this is the fish square functio which makes a fish but with 2 times the same parameter so it looks like a square
(vc-append (filled-rectangle 2 l) (fish wh wh))) > the l is the length of the string that attaches the fish to the string at the top
the fish function is just (fish x y) x makes it longer, y makes it taller.
the pumpkin function is just (pumpkin x y) same story
so my question is, how do rewrite the given code , but with lambda as a parameter.
i would upload an image, but my repuation isn't high enough :s
The string procedure as it is already receiving a procedure as a parameter (you don't have to rewrite it!), decoration can be any two-argument function used for decorating. Now when you call it you can pass a named procedure, for example:
(define (decoration r n)
<body>)
(string decoration
5
40)
... Or just as easily, you can pass the same procedure in-line as a lambda, and if I understood correctly, this is what you're supposed to do:
(string (lambda (r n)
<body>)
5
40)
Just replace <body> with the actual body of the decoration you want to use. In othre words: the change you're expected to do is in the way you pass the parameters to the function at invocation time, but you're not expected to change the function itself.
Imagine you have the procedure +. It could be any really. It takes several arguments but you need a different procedure that takes one and adds that to an already constant value 3.
Thus you want to pass + with the extra information that it should add 3.
A full definition of such procedure would be
(define (add3 n)
(+ 3 n))
which is the short form of the full define
(define add3
(lambda (n)
(+ 3 n)))
Now when passing a procedure 3+ you could actually just pass it's definition. These two does the same:
(do-computation add3 data)
(do-computation (lambda (n) (+ 3 n)) data)