I am writing my first program in scheme. I get pretty deep into recursion because I basically interpret a program for a simple robot which can have nested procedure calls.
If I find a violation I need to stop interpreting the program and return the last valid state.
I've solved it by declaring a global variable (define illegalMoveFlag 0) and then setting it via set!.
It works fine, but I guess my tutor won't like it (because it's not functional approach I guess)
Other approach I've thought about is to add an error parameter to every function I call recursively in the program. I don't quite like it because it would make my code far less readable, but I guess it's more 'functional'.
Is there maybe a third way I didn't think about? And can my approach be justified in this paradigm, or is it basically a code smell?
Since this was your first Scheme program, you probably just need to introduce a conditional expression, cond, in order to avoid further recursion when you reach the end. For example:
; sum : natural -> natural
; compute the sum 0+1+...+max
(define (sum max)
(define (sum-helper i sum-so-far)
(if (> i max)
sum-so-far
(sum-helper (+ i 1) (+ sum-so-far i))))
(sum-helper 0 0))
(display (sum 10))
(newline)
However, if you need a traditional return to return like longjmp in C, you will need to store and use an escape continuation. This can be done like this:
(define (example)
(let/ec return
(define (loop n)
(if (= n 100000)
(return (list "final count: " n))
(loop (+ n 1))))
(loop 0)))
(display (example))
If let/ec is not defined in your Scheme implementation, then prefix your program with:
(define-syntax let/ec
(syntax-rules ()
[(_ return body ...)
(call-with-current-continuation
(lambda (return)
body ...))]))
UPDATE:
Note that cond has an => variant:
(cond
[(call-that-can-fail)
=> (lambda (a) <use-a-here>))]
[else <do-something-else>])
If the call succeeds then the first, clause is
taken and the result is bound to a. If the call fails,
then the else clause is used.
The usual way to stop recursing is, well, to stop recursing. i.e., don't call the recursive function any longer. :-)
If that is too hard to do, the other way to break out of something is to capture a continuation at the top level (before you start recursing), then invoke the continuation when you need to "escape". Your instructor may not like this approach, though. ;-)
You might want to use the built-in procedure error, like so:
(error "Illegal move") ; gives ** Error: Illegal move
This will raise an exception and stop interpreting the program (though I suspect this may not be what you are looking for).
You can also provide additional arguments, like this:
(error "Illegal move: " move) ; gives ** Error: Illegal move: <move>
You can exit of a recursion (or from any other process) using a continuation. Without knowing more specifics, I'd recommend you take a look at the documentation of your interpreter.
Make illegalMoveFlag a paramter in the function instead of a global variable
I'll give you a simple example with factorials
ie:
0! = 1
n! = n * (n - 1)! when n (1 ... infinity)
lets call this a recursive factorial
(define (fact-r n)
(if
[eq? n 0]
1
(* n (fact-r (- n 1)))
)
)
An alternative would be to use a parameter to the function to end the recursion
Lets call it iterative factorial
(define (fact-i n total)
(if
(eq? n 0)
total
(fact-i (- n 1) (* n total))
)
)
total needs to start at 1 so we should make another function to make using it nicer
(define (nice-fact n)
(fact-i n 1))
You could do something similar with illegalMoveFlag to avoid having a global variable
As far as avoiding using set! goes, we'll probably need more information.
In some cases its still rather hard to avoid using it. Scheme is fully turing complete without the use of set! however when it comes to accessing an external source of information such as a database or a robot set! can become the only practical solution...
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)
...)
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?
If Racket's match macro were a function I could do this:
(define my-clauses (list '[(list '+ x y) (list '+ y x)]
'[_ 42]))
(on-user-input
(λ (user-input)
(define expr (get-form-from-user-input user-input)) ; expr could be '(+ 1 2), for example.
(apply match expr my-clauses)))
I think there are two very different ways to do this. One is to move my-clauses into macro world, and make a macro something like this (doesn't work):
(define my-clauses (list '[(list '+ x y) (list '+ y x)]
'[_ 42]))
(define-syntax-rule (match-clauses expr)
(match expr my-clauses)) ; this is not the way it's done.
; "Macros that work together" discusses this ideas, right? I'll be reading that today.
(on-user-input
(λ (user-input)
(define expr (get-form-from-user-input user-input)) ; expr could be '(+ 1 2), for example.
(match-clauses expr)))
The alternative, which might be better in the end because it would allow me to change my-clauses at runtime, would be to somehow perform the pattern matching at runtime. Is there any way I can use match on runtime values?
In this question Ryan Culpepper says
It's not possible to create a function where the formal parameters and body are given as run-time values (S-expressions) without using eval.
So I guess I'd have to use eval, but the naive way won't work because match is a macro
(eval `(match ,expr ,#my-clauses) (current-namespace))
I got the desired result with the following voodoo from the guide
(define my-clauses '([(list'+ x y) (list '+ y x)]
[_ 42]))
(define-namespace-anchor a)
(define ns (namespace-anchor->namespace a))
(eval `(match '(+ 1 2) ,#my-clauses) ns) ; '(+ 2 1)
Is the pattern matching happening at runtime now? Is it a bad idea?
To answer the first part of your question (assuming you don't necessarily need the match clauses to be supplied at runtime):
The key is to:
Define my-clauses for compile time ("for syntax").
Reference that correctly in the macro template.
So:
(begin-for-syntax
(define my-clauses (list '[(list '+ x y) (list '+ y x)]
'[_ 42])))
(define-syntax (match-clauses stx)
(syntax-case stx ()
[(_ expr) #`(match expr #,#my-clauses)]))
The pattern matching is happening at runtime in the last example.
One way to check is to look at the expansion:
> (syntax->datum
(expand '(eval `(match '(+ 1 2) ,#my-clauses) ns)))
'(#%app eval (#%app list* 'match ''(+ 1 2) my-clauses) ns)
Whether is a good idea...
Using eval is rather slow, so if you call it often it might be better to find another solution. If you haven't seen it already you might want to read "On eval in dynamic languages generally and in Racket specifically." on the Racket blog.
Thank you both very much, your answers gave me much food for thought. What I am trying to do is still not very well defined, but I seem to be learning a lot in the process, so that's good.
The original idea was to make an equation editor that is a hybrid between paredit and a computer algebra system. You enter an initial math s-expression, e.g. (+ x (* 2 y) (^ (- y x) 2). After that the program presents you with a list of step transformations that you would normally make by hand: substitute a variable, distribute, factor, etc. Like a CAS, but one step at a time. Performing a transformation would happen when the user presses the corresponding key combination, although one possibility is to just show a bunch of possible results, and let the user choose the new state of the expression amongst them. For UI charterm will do for now.
At first I thought I would have the transformations be clauses in a match expression, but now I think I'll make them functions that take and return s-expressions. The trouble with choosing compile time vs runtime is that I want the user to be able to add more transformations, and choose his own keybindings. That could mean that they write some code which I require, or they require mine, before the application is compiled, so it doesn't force me to use eval. But it may be best if I give the user a REPL so he has programmatic control of the expression and his interactions with it as well.
Anyway, today I got caught up reading about macros, evaluation contexts and phases. I'm liking racket more and more and I'm still to investigate about making languages... I will switch to tinkering mode now and see if I get some basic form of what I'm describing to work before my head explodes with new ideas.
I'm a noob in scheme ... I am trying to make an exercise so that it will check if a number is a palindrome or not ( I know how to do it in c, c++ and java). But I keep getting this error "c: unbound identifier in module in: c". I searched wide and far for the error, and yes there are tens of topics on it, but all on complicated stuff that have nothing to do with my punny code. My question is, can somebody please explain to me what does the error actually mean and how can I avoid it ? My code so far :
#lang racket
(define (palindrome n)
(if (> 10 n) #t
(check n)
)
)
(define (check n)
(if (> n 0)
((= c (modulo n 10))
(= x (+ (* x 10) c))
(= n (/ n 10)))
(checkp )
)
)
(define (checkp k)
(if (= k n) #t
#f)
)
The error reported occurs in the check procedure. All those references to the variables called c and x will fail, what are those variables supposed to be? where do they come from? Remember: in Scheme = is used for comparing two numbers, not for assignment.
There are other problems. The last line of check is calling checkp, but you forgot to pass the parameter. Also the syntax in the if expression is wrong, you can't write more than two conditions in it (the "consequent" and the "alternative"), if you need more than two conditions you should use cond.
Please be careful with those parentheses, you must not use them to group expressions (they're not like curly braces!). In Scheme, if you surround an expression with () it means function application, and that's not what you want to do in check.
And in the checkp procedure we have the same problem: the variable n is unbound. It's just like in any other programming language: you have to make sure that the variables come from somewhere (a parameter, a local variable, a global definition, etc.), they can't simply appear out of thin air.
UPDATE
After the update, now it's clear what you wanted to do. I'm sorry to say this, but you don't have a good grasp of even the most basic concepts of the language. All along you needed to do an iteration (typically implemented via recursion), but this is reflected nowhere in your code - you'll have to grab a good book or tutorial on Sceheme, to get the basics right. This is how the code in Java or C would look like in Scheme:
(define (check k)
(let loop ((x 0) (n k))
(if (zero? n)
(= k x)
(loop (+ (* 10 x) (remainder n 10)) (quotient n 10)))))
(define (palindrome)
(display "Enter the number: ")
(if (check (read))
(display "The number is a palindrome")
(display "The number is not a palindrome")))
Use it like this:
(palindrome)
Enter the number: 12321
The number is a palindrome