I just start to learn Scheme today.
I wrote a function gcd(), but it always returns 0.
(define (gcd a b)
(cond (= b 0)
(a)
(else ((gcd b (modulo a b))))
)
)
Why I am wrong?
This should fix the problems:
(define (gcd a b)
(cond [(= b 0) a]
[else (gcd b (modulo a b))]))
You were incorrectly surrounding some expressions between parenthesis, and some parenthesis were missing from the cond expression.
Notice that in Scheme, when you surround something in parenthesis, say (a) you're telling the interpreter: a is a procedure with no arguments and I want to call it, and this was not the case in here, a is just a number.
Also, for readability's sake, it's a good idea to use [] instead of () to separate each of the conditions in a cond expression, as shown in my code above - but don't forget them, they're mandatory and in your code you forgot them in the first condition.
Other people have described what your mistake is and what you should do.
It is also instructive to consider how your code is actually run and why it produces the output you see. Because of your missing parentheses, the first case for your cond is (= b 0). The first thing (=) is taken as the condition. Everything in Scheme except #f is true, so this is always true. Since it is true, this case is evaluated. Specifically, the rest of the things in the parentheses is taken as (possible multiple) expressions to evaluate, as an implicit begin. So basically it evaluates (begin b 0). The result is the result of the last expression, 0.
Related
I am trying to do Recursive method to find max value in list.
Can anyone explain where I made the mistake on this code and how to approach it next time.
(defun f3 (i)
(setq x (cond (> (car (I)) (cdr (car (I))))
(f3 (cdr (I)))))
)
(f3 '(33 11 44 2) )
also I tried this following method and didn't work:
(defun f3 (i)
(cond ((null I )nil )
(setq x (car (i))
(f3(cdr (i)))
(return-from max x)
)
Thanks a lot for any help. I am coming from java if that helps.
If you're working in Common Lisp, then you do this:
(defun max-item (list)
(loop for item in list
maximizing item))
That's it. The maximizing item clause of loop determines the highest item value seen, and implicitly establishes that as the result value of loop when it terminates.
Note that if list is empty, then this returns nil. If you want some other behavior, you have to work that in:
(if list
(loop for item in list
maximizing item))
(... handle empty here ...))
If the number of elements in the list is known to be small, below your Lisp implementation's limit on the number of arguments that can be passed to a function, you can simply apply the list to the max function:
(defun max-item (list)
(apply #'max list))
If list is empty, then max is misused: it requires one or more arguments. An error condition will likely be signaled. If that doesn't work in your situation, you need to add code to supply the desired behavior.
If the list is expected to be large, so that this approach is to be avoided, you can use reduce, treating max as a binary function:
(defun max-item (list)
(reduce #'max list))
Same remarks regarding empty list. These expressions are so small, many programmers will avoid writing a function and just use them directly.
Regarding recursion, you wouldn't use recursion to solve this problem in production code, only as a homework exercise for learning about recursion.
You are trying to compute the maximum value of a list, so please name your function maximum and your parameter list, not f3 or i. You can't name the function max without having to consider how to avoid shadowing the standard max function, so it is best for now to ignore package issues and use a different name.
There is a corner case to consider when the list is empty, as there is no meaningful value to return. You have to decide if you return nil or signal an error, for example.
The skeleton is thus:
(defun maximum (list)
(if (null list)
...
...))
Notice how closing parentheses are never preceded by spaces (or newlines), and opening parentheses are never followed by spaces (or newlines). Please note also that indentation increases with the current depth . This is the basic rules for Lisp formatting, please try following them for other developers.
(setq x <value>)
You are assigning an unknown place x, you should instead bind a fresh variable if you want to have a temporary variable, something like:
(let ((x <value>))
<body>)
With the above expression, x is bound to <value> inside <body> (one or more expressions), and only there.
(car (i))
Unlike in Java, parentheses are not used to group expressions for readability or to force some evaluation order, in Lisp they enclose compound forms. Here above, in a normal evaluation context (not a macro or binding), (i) means call function i, and this function is unrelated to your local variable i (just like in Java, where you can write int f = f(2) with f denoting both a variable and a method).
If you want to take the car of i, write (car i).
You seem to be using cond as some kind of if:
(cond (<test> <then>) <else>) ;; WRONG
You can have an if as follows:
(if <test> <then> <else>)
For example:
(if (> u v) u v) ;; evaluates to either `u` or `v`, whichever is greater
The cond syntax is a bit more complex but you don't need it yet.
You cannot return-from a block that was undeclared, you probably renamed the function to f3 without renaming that part, or copied that from somewhere else, but in any case return-from is only needed when you have a bigger function and probably a lot more side-effects. Here the computation can be written in a more functionnal way. There is an implicit return in Lisp-like languages, unlike Java, for example below the last (but also single) expression in add evaluates to the function's return value:
(defun add-3 (x)
(+ x 3))
Start with smaller examples and test often, fix any error the compiler or interpreter prints before trying to do more complex things. Also, have a look at the available online resources to learn more about the language: https://common-lisp.net/documentation
Although the other answers are right: you definitely need to learn more CL syntax and you probably would not solve this problem recursively in idiomatic CL (whatever 'idiomatic CL' is), here's how to actually do it, because thinking about how to solve these problems recursively is useful.
First of all let's write a function max/2 which returns the maximum of two numbers. This is pretty easy:
(defun max/2 (a b)
(if (> a b) a b))
Now the trick is this: assume you have some idea of what the maximum of a list of numbers is: call this guess m. Then:
if the list is empty, the maximum is m;
otherwise the list has a first element, so pick a new m which is the maximum of the first element of the list and the current m, and recurse on the rest of the list.
So, we can write this function, which I'll call max/carrying (because it 'carries' the m):
(defun max/carrying (m list)
(if (null list)
m
(max/carrying (max/2 (first list) m)
(rest list))))
And this is now almost all we need. The trick is then to write a little shim around max/carrying which bootstraps it:
to compute the maximum of a list:
if the list is empty it has no maximum, and this is an error;
otherwise the result is max/carrying of the first element of the list and the rest of the list.
I won't write that, but it's pretty easy (to signal an error, the function you want is error).
I am learning about racket/scheme and came across an online resource that said, if a function written using a cond gives true or false, it can be rewritten using only not, and, and or. I have worked out some simple examples where I was able to to convert cond statements into a statement only involving not and and or. My question is if there is a way that the logic can be "seen" right away when converting between these two types of statements. I understand that it is not always practical to convert every cond statement into a combination of not's and's and or's but I am interested in learning about the logic behind the process of converting.
Thanks in advance.
(If something about the question does not make sense, leave a comment and I will try clarifying what I want to understand)
All conditional expressions (and not only those evaluating to true/false) can be rewritten using only boolean combinators. This is because of how logical operators are evaluated in Scheme/Racket. For instance, logically (and a b) would be true if both a and b are true, and otherwise false. But in Racket, the result of (and a b) is b if both a and b are truthy, and otherwise false. That is, evaluation proceeds to the right until either the last argument or a falsy value is encountered. At that point, evaluation stops and that value (which could be a boolean but needn't be) is returned. It's because and and or don't simply produce boolean output that they can be used to stand in for conditional expressions.
E.g.
(if #t 'hello 'bye) ;=> hello
(or (and #t 'hello) 'bye) ;=> hello
(if #f 'hello 'bye) ;=> bye
(or (and #f 'hello) 'bye) ;=> bye
(cond [#f 'hello]
[#f 'bye]
[#t 'aloha]) ;=> aloha
(or (and #f 'hello)
(and #f 'bye)
(and #t 'aloha)) ;=> aloha
But you wouldn't usually want to use them that way since they're hard to read. As a general guideline, use if and cond in most cases, rather than elementary boolean operators. If you only care about taking action on a positive or negative result of the conditional, then you could use when or unless. If you do care about handling both positive and negative results, but one of them is a boolean result such as this example:
(if (positive? n)
#t
(even? n))
... then this would be a case where a boolean operator would be preferable, like so:
(or (positive? n) (even? n))
If both arms of the if conditional are boolean values, like this:
(if (> n 3)
#t
#f)
... then just replace the entire conditional expression with the condition itself:
(> n 3)
Otherwise, stick to if and cond.
Once you convert a cond to nested ifs, you can always turn it into and or and not like this:
(if A B C) --> (or (and A B) (and (not A) C))
However, if you do this blindly, you will get a much more complicated expression than what you could get, so I would add a couple more transformations you can use:
(if A B #f) --> (and A B)
(if A B #t) --> (or (not A) B)
(if A #f C) --> (and (not A) C)
(if A #t C) --> (or A C)
(note: that or above might return a different truthy-value other than #t, making it technically different but equivalent-when-used-as-a-boolean)
Another thing I should note is that sometimes you can transform a multi-branch cond into and or not without transforming into ifs first. For example a 3-branch cond:
(cond [A B]
[C D]
[else E])
-->
(or (and A B)
(and (not A) C D)
(and (not A) (not C) E))
Or a 4-branch cond:
(cond [A B]
[C D]
[E F]
[else G])
-->
(or (and A B)
(and (not A) C D)
(and (not A) (not C) E F)
(and (not A) (not C) (not E) G))
Each and corresponds to a cond-branch, and each cond-branch's and has nots in it for every previous condition, in addition to its own condition.
A more generic rule you can apply:
for i from 1 through n,
(cond [Q_i A_i]
...
[else E])
-->
on each i, for j from 1 through i-1,
(or (and (not Q_j) ... Q_i A_i)
...
(and (not Q_i) ... E)
First of all, you need to desugar cond language into a sequence of if-then-else sequences, which is trivial.
After that, you can rewrite if conditionals into boolean operators. You can look into a manual of propositional logic to learn this. Or look here.
Btw. It is forbidden to paste your homework on stack overflow.
I am stuck, I did it this way but I feel it is wrong.
(defun (find-min a b))
(cond
(> a b) (find-min b (read))
(< a b) (find-min a (read))
)
(display (find-min (read) (read)))
Code review
The code as given is badly formatted. It is really important to test your code often, to check that at least the syntax is correct. Instead of writing the code in isolation, you should ask the environment, the interpreter, to parse your code and execute it. You'll have a shorter feedback loop, which will help getting the code right.
For example, if you start your interpreter (you mentionned clisp), you are in a Read Eval Print Loop (REPL), where you write Lisp forms, which are evaluated to produce a result, which is printed. So just by writing code, it will get parsed and evaluated, which can quickly inform you about possible errors.
So if you write the code as you wrote it, you will notice that the interpreter first reads this:
(defun (find-min a b))
This is because all parentheses are balanced: the Lisp reader (the R in REPL) will build a list of two elements, namely defun and the list (find-min a b).
When evaluation is performed (the E in REPL), the list will be interpreted as a Lisp form, but this is a malformed defun.
DEFUN expects a function name, followed by a list of variable bindings, followed by the function body. So you can try writing for example:
(defun find-min (a b)
0)
This above defines a function named find-min, which accepts two parameters a and b, and always evaluate as 0 (the body of the function).
In your case you want to write:
(defun find-min (a b)
(cond ...))
You COND form is malformed too:
(cond
(> a b) (find-min b (read))
(< a b) (find-min a (read))
)
Each clause in a cond should be a list containing first a test, then zero or more expressions. So it would be:
(cond
((> a b) ...)
((< a b) ...))
Note that there is a remaining case, namely (= a b), which is not addressed.
Approach
But overall, I do not understand what your code is trying to achieve. Since all inputs are supposed to be obtained with (read), there is no need to accept arguments a and b. The whole thing could be a loop:
(defun read-min ()
(loop
for val = (read)
for zerop = (= val zero)
for min = val then (if zerop min (min min val))
until (= val 0)
finally (return min)))
As suggested by #leetwinski, there is also a shorter alternative:
(loop for val = (read) until (= val 0) minimizing val)
But I suppose you are not expected to use the loop form, so you should try to write a recursive function that does the same.
What you need to do is to pass the current minimum value ever read to your function, recursively, like so:
(defun read-min-rec (min-so-far)
...)
The first part of my function is a simple cond statement. It works perfectly by itself but when the rest of the function is added it causes an unexpected error.
Problems occure when passing:
(expo 2 0)
(expo 2 1)
The function works perfectly for any other positive value of n.
(defun expo (b n)
(cond ((= n 0) 1)
((= n 1) b))
(defparameter m (* b b))
(defun expo_iter (a b)
(cond ((= a n) b)
((= (+ a 1) n) (* b (sqrt m)))
((expo_iter (+ a 2) (* b m)))))
(expo_iter 2 m)
When (expo 2 0) 'lisp connection lost unexpectedly, connection broken by remote peer.' Never had this error before, any ideas?
There are many things wrong with this function.
The initial cond is almost certainly malformed since it does nothing at all. Probably it should.
There's a missing close paren which I assume is a cut & paste error.
Don't use defparameter (or defvar, or defconstant) other than at toplevel unless you really know what you are doing. Instead use let.
Don't use defun other than at toplevel unless you really know what you are doing. Instead use labels (or flet).
the local function has an argument with the same name as one of the arguments to the the global function which is confusing (although I often do that too, this says something bad about my programs, not that it is OK).
The use of non-toplevel defun &c makes it look as if it has been translated, badly, from Scheme perhaps? The Scheme equivalent would be less atrocious but still would fail to terminate.
Then if you actually think about what the function does you will see why it fails to terminate, and will either cause a stack overflow very quickly in if tail calls are not eliminated, or will eventually die through memory exhaustion because of bignum consing if they are. Just think about what the base case of the recursion is. What should the junk cond be doing?
I have a function which, sort of like assoc, searches a symbol in list and returns either #f or the position in the list.
The return type for this function should be a union of #f and Natural, (U #f Natural).
But when I want to use the value as a number, it will always type mismatch because the value is not just a Natural but in fact a union.
How can I pull the Natural value out and avoid the type-mismatch error?
Typed Racket has a feature called Occurrence Typing, which allows you to filter a value's type using predicates and assertions. The basic idea is that predicates, such as string?, empty?, and number? can filter types based on a program's control flow.
To illustrate this, see this example:
(: nat/#f->nat ((U Natural False) -> Natural))
(define (nat/#f->nat n)
(if n n
(error "Expected a number, given " n)))
This will typecheck because, if the first branch is taken, then n cannot be #f, so it must be a Natural. In the second case, the function just errors and doesn't return, so the type still holds.
In most cases, you won't just simply error on the failure case, but you'll provide some sort of alternate behavior. This still allows you to refine the type within a body itself.
(define n : (Option Natural) #f)
(cond
[n
; do something with n as a number
(+ n 1)]
[else
; do something else
(void)])
Within the body of the first case, the type of n is refined to be Natural, so it can be used as such.
In the case that you actually do want to just throw an error when a type doesn't match, you can use assert or cast. The former is effectively a derived concept, which basically performs the same sort of check as the first example above. You use it like this:
(assert n number?) ; now n is a number, and if it isn't, an error is thrown
(+ n 1)
The cast form is a little bit different, since it specifies types instead of predicates. That means you can use it like this:
(+ (cast n Natural) 1)
This also throws an error if it turns out that n isn't actually a Natural, but otherwise, the overall expression becomes of type Natural.
Do something like this:
(define i (assoc ...))
(cond
[i <use-i-here>]
[else <raise-error>])
From (define i (assoc ...)) we know that i has the return type of assoc i.e. it is either #f or a natural. In the cond clause [i <use-i-here>] the <use-i-here> will only be evaluated if i is not #f so the type checker know that in <use-i-here> i will be a natural.