I have written the following code snippet in scheme,
(define (test-for-prime number divisor)
(cond (prime? number) (number)
(else (let ((next-divisor) (find-next-divisor number (+ 1 divisor)))
(test-for-prime (/ number next-divisor) (next-divisor))))))
However, I get the following error
let: bad syntax (not an identifier and expression for a binding) in: (next-divisor)
How do I rectify it?
Try this version, it fixes all the syntax errors:
(define (test-for-prime number divisor)
(cond ((prime? number)
number)
(else
(let ([next-divisor (find-next-divisor number (+ 1 divisor))])
(test-for-prime (/ number next-divisor) next-divisor)))))
You have lots of misplaced parenthesis. Some are missing, some are mistaken ... I'd suggest you take a good read at a Scheme tutorial and play around writing some basic procedures to get the hang of it, in particular here is the documentation and correct structure for a let special form:
(let ([id val-expr] ...) body ...+)
The first form evaluates the val-exprs left-to-right, creates a new location for each id, and places the values into the locations. It then evaluates the bodys, in which the ids are bound. The last body expression is in tail position with respect to the let form. The ids must be distinct according to bound-identifier=?
Also it's a good idea to use an IDE/editor which highlights this kind of problems and helps you indent the code properly. In particular, be aware that a variable must not be surrounded in parenthesis, when you write this: (x) Scheme assumes that x is a procedure and that you're calling it.
Let has the following syntax (example with two bindings):
(let ((<var> <expr>)
(<var1> <expr1>))
<body>)
If we fill in your let form, you have two bindings: next-divisor gets bound to nothing, and find-next-divisor gets bound to number, but there is a third form (+ 1 divisor) that does not fit into let's syntax.
This might be what you want:
(let ((next-divisor (find-next-divisor number (+ 1 divisor))))
;; ...
)
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 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)
...)
As a project I am required to make a roman numeral converter in lisp using recursion. While working on the roman numeral to English portion I am running into a problem where the compiler is telling me that that one of my variables is is an undefined function. I am very new to lisp and could use any tips or tricks possible for this program. I would like to know the changes I would have to make to stop getting that error and if anyone has tips for my recursion that would be appreciated.
I know my code is messy but I plan on learning all the proper ways to format when I have something that works. The function is supposed to take a list of roman numerals and then convert the first and second element of the list into the corresponding integers and add them. It recursively is called until it hits NIL when it will return a 0 and add all the remaining integers and display that as an atom. Hopefully that makes sense. Thank you in advance.
(defun toNatural (numerals)
"take a list of roman numerals and process them into a natural number"
(cond ((eql numerals NIL) 0)
((< (romans (first (numerals)))
(romans (second (numerals))))
(+ (- (romans (first (numerals))))
(toNatural (cdr (numerals)))))
(t
(+ (romans (first (numerals)))
(toNatural (cdr (numerals)))))))
(defun romans (numer)
"take a numeral and translate it to its integer value and return it"
(cond((eql numer '(M)) 1000)
((eql numer '(D)) 500)
((eql numer '(C)) 100)
((eql numer '(L)) 50)
((eql numer '(X)) 10)
((eql numer '(V)) 5)
((eql numer '(I)) 1)
(t 0)))
here is the error. I use emacs and clisp for this project.
The following functions were used but not defined:
NUMERALS
0 errors, 0 warnings
In Common Lisp, the form (blah) means "call the function blah" and the form (blah foobar) means "call the function foo, with the argument foobar". Thus, you are telling the compiler to call the function numerals in multiple places, when you actually want to just use the value of the variable.
Also, unless you have a lisp environment that uses "modern mode", the symbol denoted by "toNatural" is the same as the one denoted by "tonatural" or "TONATURAL", don't use case to distinguish word breaks, use "-" (so (defun to-natural ...).
When I had asked how to Get numbers for the lottery I was given the hint to create a function that shuffles a list. So I tried to do so, and I even got it working.
My current implementation looks like this:
(defun shuffle (list)
(let ((len (length list)))
(loop repeat len
do
(rotatef
(nth (random len) list)
(nth (random len) list))
finally
return list)))
Good news is that it works:
(shuffle '(1 2 3 4 5 6))
;; => (3 1 4 2 6 5)
Bad news is that I get an error message:
WARNING: LOOP: loop keyword immediately after FINALLY: permitted by CLtL2, forbidden by ANSI CL.
Unfortunately I don't understand it. Why does it tell me that loop immediately appears after finally? And, what's wrong with the code that actually causes this?
Is there a better way to formulate this?
WARNING: LOOP: loop keyword immediately after FINALLY: permitted by CLtL2, forbidden by ANSI CL.
This means that RETURN is a loop keyword, which is not allowed after finally, according to the ANSI CL standard.
If we want to return from the LOOP, we need to use the return macro:
(loop ...
finally (return list))
It's actually a common mistake. finally return <expr> is no longer allowed since the ANSI CL standard. That's also a reason not to use CLtL2 (Common Lisp the Language, 2nd Edition) as a reference. The CL Hyperspec is the better reference.
I'm porting some code from lisp, but I got stuck at this part (apparently that's for mit-scheme)
(define (end-of-sentence? word)
(and (or (char-exist-last? word '#\.)
(char-exist-last? word '#\!)
(char-exist-last? word '#\?))
(not (initial? word))
(or (eq? (peek-char) '#\Space) ;;peek- so test for linefeed isn't affected
(eq? (peek-char) '#\n) ;;note- test for space isn't neccessary
(eq? (read-char) '#\t))))
;;counts the number of sentences in a given file and
;;stops at the given number
;;returns true once at that position, returns error if eof
(define (goto-sentence? file stop)
(define (c-g-iter num)
(cond ((= num stop)
#t)
((end-of-sentence?)
(c-g-iter (+ num 1)))
((not (char-ready?))
(error "EOF reached, number to large in goto-sentence?: " stop))
(else
(c-g-iter num))))
(begin
(open-path file)
(c-g-iter 1)))
Of course I could just skip that and implement what the comments say it does, but just wanted to be sure there's no magic happening in the background. So... how does this function even work -- where is it actually reading the characters? Is it as ugly as I think and does it consume the characters as a side-effect in the last check in end-of-sentence?? Or does the char-ready? actually read something?
But then again - what does (end-of-sentence?) (c-g-iter (+ num 1)) mean, as I don't expect c-g-iter to return a word.
I'm no scheme programmer, but it appears that characters are being consumed in read-char source
end-of-sentence? on the other hand appears to be getting called without a parameter, even though it is declared to take one. I assume that the functions it calls in turn are tolerant to whatever the system provides for unspecified parameters (nil?)
The pair (end-of-sentence?) (c-g-iter (+ num 1)) is a parameter to cond, which you can think like a switch or concise if/else; the first part is a test (end-of-sentence?), and the second is what to execute if true (c-g-iter (+ num 1))
Just adding my voice to the chorus; maybe I can provide some insight.
Some functions that are in these functions are not standard mit-sheme, such as char-exist-last? and initial?.(1) So I can't be sure what they do.
That being said, I think that end-of-sentence? takes in a string (word, so it should be a word) and returns true if its last character is a '!', '? or '.', and the next character after the word is a space, newline or tab character. Also, looking at intial, it probably can't be the first word in the sentence ('A.', for example, shouldn't return true, but 'A dog.' should.)
read-char does indeed 'consume characters' - "Returns the next character available from input-port, updating input-port to point to the following character." (Googled 'read-char mit scheme' to get MIT-Scheme input procedures.)
Per the same source char-ready? works like so: "Returns #t if a character is ready on input-port and returns #f otherwise."
Hope this is at least someone enlightening!
(1) MIT-Scheme Reference