Lisp: IF condition using AND operator - syntax

I making this function.
(f 3 4) (sum = 7)
(f 'a 'b) (not num!)
My problem is how can I make if condition using and operator.
I try....
(IF (and (typep a 'integer) (typep b 'integer)) (1) (0))
(IF (and ((typep a 'integer)) ((typep b 'integer))) (1) (0))
(IF ((and ((typep a 'integer)) ((typep b 'integer)))) (1) (0))
But it doesn't work.
(1) (0) is I set it temporarily.
Could I get some lisp syntax help?

The most important thing you need to learn about Lisp at this moment is that parens matter.
In C you can write 1+3, (1)+3, (((1+3))) and they all mean the same thing. In lisp they are very very different:
a means "the value of the variable named a".
(a) means "the return value of the function named a called without any arguments".
((a)) is a syntax error (but see PPS)
So, every version with ((...)) is outright wrong.
Since there is no function named 1, the first version is no good either.
What you need is:
(if (and (typep a 'integer)
(typep b 'integer))
1
0)
Note formatting and indentation.
Lispers read code by indentation, not parens, so proper indentation is critical.
Note that Emacs (and maybe some other Lisp-specific IDEs) will indent lisp code for you.
PS. The description of what you are trying to accomplish is unclear, but it might be that the easiest way is to use generic functions:
(defgeneric f (a b)
(:method ((a integer) (b integer))
(+ a b)))
(f 1 2)
==> 3
(f 1 'a)
*** - NO-APPLICABLE-METHOD: When calling #<STANDARD-GENERIC-FUNCTION F> with
arguments (1 A), no method is applicable.
PPS. Eventually you will see legitimate ((...) ...), e.g., cond:
(defun foo (a)
(cond ((= a 1) "one")
((= a 2) "two")
(t "many")))
(foo 1)
==> "one"
(foo 3)
==> "many"
or lambda forms:
((lambda (x) (+ x 4)) 5)
==> 9
but you do not need to worry about those yet.

Related

Let as syntactic sugar for lambda

Is the following how a let statement resolves in terms of lambda?
(let((a 4)(b 5)) (+ a b))
-->
((lambda (a b) (+ a b)) 4 5)
Is the general form something along the lines of:
(lambda (key1 key2 ...) <body> (val1 val2 ...))
-->
(let ((key1 val1) (key2 val2) ...) <body>)
What's the advantage of using the let syntax? Is it just the easier readability placing the key/value pair next to each other?
(lambda (key1 key2 ...) <body> (val1 val2 ...))
-->
(let ((key1 val1) (key2 val2) ...) <body>)
The first pattern is actually like this:
((lambda (par1 par2 ...) <body>) arg1 arg2 ...)
-->
(let ((par1 arg1) (par2 arg2) ...) <body>)
The function has parameters. Common Lisp has positional, optional, rest and keyword parameters.
The function form has argument forms. Each argument form gets evaluated and the function then gets called with the arguments values. The parameters (local variables) get bound to the arguments values and the body gets executed.
The main benefit of a let is a question of easier seeing which parameter has which argument form and how many arguments (and possibly which) one has to provide.
Imagine:
((lambda (a b c d e f)
<long body> ; and yes the body can get long
)
1 2 3 4 5 5)
Be warned, there is a lot of code where the body is longer than five lines.
The let moves the argument forms to the top and it is easier to see what the environment is in which the body gets evaluated:
(let ((a 1)
(b 2)
(c 3)
(d 4)
(e 5)
(d 6))
<long body>
)
or even
(let ((a 1) (b 2) (c 3) (d 4) (e 5) (d 6))
<long body>
)
Not only easier readability; it is easier to write code using let than it is to write code that uses lambda to express let. Consider:
(let ((x 2)
(y 3))
(let ((u (+ x y))
(v (* x y)))
(display "let version:\n")
(for-each display (list x ", " y "\n" u ", " v "\n"))))
let version:
2, 3
5, 6
And a lambda version of the same construct:
((lambda (x y)
((lambda (u v)
(display "lambda version:\n")
(for-each display (list x ", " y "\n" u ", " v "\n")))
(+ x y) (* x y))) 2 3)
lambda version:
2, 3
5, 6
Both versions work, but the let version expresses intent through use of an appropriate syntax. The lambda version expresses intent only through the semantics of its construction. If you are unaware if the idiom that allows the expression of the idea of let binding, or if you can't piece together what is happening by analyzing the code, the meaning of the lambda version is opaque. But the let version clearly states its intent by using syntax dedicated to let binding.
Further, as let binding scenarios get more complex, using let offloads a substantial portion of that complexity to the syntax. The above example is a simple nested let, and it is already easy to make mistakes in the lambda version. You have to be sure that the parentheses are placed correctly (I actually managed to get one out of place when writing the example code), and the final version places all of the variable identifiers at the beginning of the construction, with all of the bound values at the end. This means that to understand the lambda version you must keep referencing the beginning and the end to understand what is happening in the body.
Generally speaking, lambda expresses a very general idea, but let expresses a more specific idea that is often needed. The advantage of let syntax is that it allows you to express the more specific idea easily, concisely, and readably in a way that is less error-prone than always expressing the specific idea by implementing it in terms of the more general idea.

DrRacket define begin set! probably should work but dont

Im learning for exam of programming in lisp using DrRacket..
In presentation from lectures i found this code:
(define (f a b c)
(define delta)
(begin
(set! delta (- (* b b) (* 4 a c))
(if (>=? delta 0)
(writeln ”są pierwiastki”)
(writeln ”nie ma pierwiastków)))))
But it dont work.
DrRacket is showing:
. define: bad syntax (missing expression after identifier) in: (define delta)
Can't I set delta value later?
What is the problem?
thanks in advance
The original error message is because
(define delta)
is missing a value. Instead it should be something like:
(define delta 0)
There some other issues:
The double quotes weren't the " character and weren't recognized
by Racket.
Some parens were wrong.
Also I don't know why it was define-ing delta, then immediately
set!-ing it.
I tried to fix/simplify what you posted, and came up with the
following. But I'm not really sure what the function is supposed to
do, so I don't know if the example output is correct.
#lang racket
(define (f a b c)
(define delta (- (* b b) (* 4 a c)))
(if (>= delta 0)
(displayln "są pierwiastki")
(displayln "nie ma pierwiastków")))
;; Example output:
(f 1 2 3)
;;-> nie ma pierwiastków
(f 1 200 3)
;;-> są pierwiastki
Try this:
#lang racket
(define (f a b c)
(define delta 0)
(set! delta (- (* b b) (* 4 a c)))
(if (>= delta 0)
(displayln "są pierwiastki")
(displayln "nie ma pierwiastków")))
What was wrong with your code:
It's probably a copy-paste error, but in Scheme we delimit strings using the " character, not ” as in your code. And the last line is missing the closing ".
Although some interpreters accept a define without an initial value, the standard is that a value must be present after the variable name
A closing parenthesis is missing at the end of the set! line
The define and set! lines can be merged into a single line: (define delta (- (* b b) (* 4 a c)))
The >=? operator is not standard in Scheme, it might work in your interpreter but if possible use the standard >=
The writeln procedure is not standard in Scheme, in Racket you can substitute it for displayln
Not really an error, but you don't need to write a begin inside a procedure definition, it's implicit
In conclusion: the code in the question seems to be intended for a different interpreter, this question was tagged racket but believe me, what you have is not valid Racket code - heck, is not even standard Scheme. Make sure to use the correct interpreter, and be very alert for typos in the text.
I think Greg already has a perfect answer to your problem, but I just want to add the obvious let version of his code as well:
;; for a given ax^2+bx+c=0
;; this displays if it has at least one
;; real number answer or not
(define (equation-has-answer a b c)
(let ((delta (- (* b b) (* 4 a c))))
(if (>= delta 0)
(displayln "Has answer(s)")
(displayln "Has no answers"))))
To just make a predicate you can do this:
;; for a given ax^2+bx+c=0
;; this returns #t if it has at least one
;; real number answer and #f otherwise
(define (equation-has-answer? a b c)
(>= (- (* b b) (* 4 a c)) 0))

Meaning of 'quote in Lisp

This question arose when reading SICP. Why (list 'quote '(a b c)) evaluated by the interpreter (R5RS in Dr.Racket) as '(a b c). For me it should be (quote (a b c)). For instance (list 'quot '(a b c)) is evaluated as (quot (a b c)). What is so special in the 'quote?
You'll get different behaviors depending on exactly what Lisp you're using (Scheme, Racket, Common Lisp, etc.) but in general, the system will accept 'x as a shorthand or syntactic sugar for (quote x). The two forms are exactly equivalent and their values are the same: the unevaluated x. When a result is coming out of the system, it might choose to print in the first way to make the result more intuitive to the user. A similar thing happens with cons, too. For instance,
(cons 1 2)
;=> (1 . 2)
because that's the general way that cons cells (pairs) are printed. However, there's a special case defined for when the second part of the pair is another list (either the empty list () or another pair, and that's why we have the following. I've also written a bit more about how lists and cons cells are printed in an answer to Recursive range in Lisp adds a period?.
(cons 1 '())
;=> (1)
(cons 1 '(2 3))
;=> (1 2 3)
Now, I've written the values of the expression above. E.g., the value of the form (cons 1 '(2 3)) is the list (1 2 3). As an additional complication, some systems (I'm thinking of some languages is Dr. Racket, in particular) don't print the value of a form in the interactive prompt, but rather print a form that would produce the same (for certain interpretations of “the same”) values. For instance, you might evaluate '(1 . 2) and see the output (cons 1 2) because that's another form that would produce the same value. This can be helpful if you're doing pure functional programming that has referential transparency, but if you're not expecting it, it can lead to some confusion.
A good way to see that we're getting the results that we should, regardless of how the system prints them, is to inspect them. We expect that (list 'quote '(a b c)) should return a list whose car is the symbol quote and whose cadr is the list (a b c). This is what we get (in Dr. Racket 5.3 with language R5RS):
> (display (list 'quote '(a b c)))
'(a b c)
> (display (car (list 'quote '(a b c))))
quote
> (display (cadr (list 'quote '(a b c))))
(a b c)
We get similar results if we use 'qmmmt instead of 'quote:
> (display (list 'qmmmt '(a b c)))
(qmmmt (a b c))
> (display (car (list 'qmmmt '(a b c))))
qmmmt
> (display (cadr (list 'qmmmt '(a b c))))
(a b c)
The only difference is that in the first case, display displays the list whose car is the symbol quote using the shorthand that is available for such lists. That is, instead of displaying (quote (a b c)) it displayed '(a b c).
'(a b c) and (quote (a b c)) are actually different notations for the same. So don't be surprised if your Lisp prints the shorter version.
In general '<something> is the same as (quote <something>).
QUOTE is used in Lisp to mark expressions which should evaluate to themselves. Usually a list would be a function or macro call and a symbol would be a variable. If you want to treat those as data, you need to quote them.
Since (quote <something>) is used so often in Lisp, the abbreviated version '<something> has been introduced to save a bit of typing or reading...
display emits some behaviors. Eg. '(a . (b . (c . ()))) is displayed (a b c). 'quote is displayed quote and perhaps '(quote x y) is displayed (quote x y) while '(quote x) is displayed 'x or (quote x). Which one is implementation dependent but both mean the same.
As data (ie. quoted, like (quote quote) and it's abbrivation 'quote) the result of the evaluation, the symbol quote is nothing special, for any LISP, just like '+ and 'potato happen to be the symbols + and potato. Any symbol that mean something when not quoted is no special when quoted.
It also took me a while to understand this problem. But it's just your good-hearted lisp interpreter showing (quote (a b c)) in it's equivalent form '(a b c). Since there is no such equivalence/syntactic sugar for (quott (a b c)), it's shown as is.

Issues with evaluating expressions from user input

I'm trying to make a recursive definition that reads and execute user expressions, such as (3 + 5). Everything is working, except of one problem with the arithmetic symbol.
I managed to replicate the error in a simpler example:
(define v '(1 + 3))
((cadr v) 2 4)
The (cadr v) is the + symbol, but for some reason the procedure can't be executed on the two arguments that followed. Am I missing something?
I think that's because
(cadr v)
returns '+ not + (literal + not a + function).
You need to evaluate it before applying it to arguments.
This should work:
((eval (cadr v)) 2 4)
^evaluates the '+ to +
edit
This worked in racket in interactive mode.
I'm not really sure what's the difference, but made it work in r5rs mode in racket (a script):
#lang r5rs
;required by r5rs
(define user-initial-environment (scheme-report-environment 5))
(define v '(1 + 2))
;eval expects a quoted expression
;(it seems that if it's a function it has to have arguments too)
;and evaluation environment.
((eval (cadr v) user-initial-environment) 2 4)
As others have pointed out, the problem is that the list you've constructed contains the symbol plus, rather than the function plus.
At its heart, this is the same reason that '(a b) returns a list of two symbols, rather than signalling an unbound identifier error; the quote starts a term in a "data language" where legal identifiers are interpreted as symbols, rather than as variable references.
The question, of course, is what you should do about it. Some here have suggested using 'eval'; this is probably a bad idea, for reasons that I think Matthew Flatt captures elegantly in his blog post on the topic.
Instead, you should probably write a simple mapping function. Here's the way I'd write it. If you use my code in an assignment, be sure to credit me :).
#lang racket
;; a mapping from symbols to operators
(define operator-hash
(hash '+ +
'- -
'* *))
;; ... and whatever other operators you want.
;; example of using it:
(hash-ref operator-hash '+) ;; ==> +
Try this:
(define v '(1 + 3))
(let ((operator (eval (cadr v)))
(operand1 (car v))
(operand2 (caddr v)))
(apply operator (list operand1 operand2)))
You can do it this way with eval in Guile:
(define (infix-eval v)
(eval (list (cadr v)(car v)(caddr v))
(interaction-environment)))
> (infix-eval '(1 + 2))
3
Rather than using interaction-environment, you could supply another environment for evaluation, where you could also define some other symbols not found in standard Scheme, so that expressions like (7 % 3) and (2 ^ 6) would also work.

Using let in Scheme

I want to write a program to find the roots of the quadratic equation in Scheme. I used LET for certain bindings.
(define roots-with-let
(λ (a b c)
(let ((4ac (* 4 a c))
(2a (* 2 a))
(discriminant (sqrt ( - (* b b) (4ac)))))
(cons ( / ( + (- b) discriminant) 2a)
( / ( - (- b) discriminant) 2a)))))
I defined the discriminant with 4ac since I did not want (* 4 a c). Even though I have defined (4ac (* 4 a c)), it is giving me this error:
expand: unbound identifier in module in: 4ac.
My question is how is let evaluated (what order)? And if i want 4ac in my let should i write another inner let? Is there a better way to do this?
Use let* instead of let.
The difference between let and let* is the following:
let* binds variables from left to right. Earlier bindings can be used in new binding further to the right (or down).
let on the other hand can be thought of as syntactic sugar (or macro) for simple lambda abstraction:
(let ((a exp1)
(b exp2))
exp)
is equivalent to
((lambda (a b)
exp)
exp1 exp2)
4ac is a variable with a numeric value, so (4ac) is not meaningful.
LET binds all variables, but the variables can't be used in the computations for the values.
This does not work:
(let ((a 1) (b 1) (c (* a b)))
c)
Use:
(let ((a 1) (b 1))
(let ((c (* a b)))
c))
Above introduces A and B with the first LET. In the second LET both A and B now can be used to compute C.
Or:
(let* ((a 1) (b 1) (c (* a b)))
c)
You'll need a special let-construct (let*) here since the variables inside the let-definition refer to each other.
It's rather a problem of defining a scope than of evaluating an expression (In usual let-definitions, the order of evaluation doesn't matter since the values may not use each other)
When you use let, the bindings are not visible in any of the bodies. Use let* instead and see the RNRS docs for details.

Resources