I'm new in LISP and I'm trying to understand recursion.
What I know is that recursion needs a STOP condition. In my code below, can you explain to me why (equal x 0) 1 is my STOP condition SINCE fact(- X 1) could continue indefinitely as in my second condition, I have set to t the second line of my cond which means it should continue.
BUT when I run the program, it works fine though. Below is my code (found by chance)
(defun fact(x)
(cond
((equal x 0) 1)
(t (*(fact(- x 1)) x))
)
)
cond expresssions have a number of clauses. Each clause is of the form (expr1 expr2). If the expr1 evaluates to true then expr2 is evaluated and that is the returned value of thecond`. No other clauses are evaluated.
So, once x becomes 0 the first clauses of cond evaluates to true and that call to fact returns 1.
The other clause of cond has a first expression of t which is true by definition; thus if the first clause is not used it always uses the second clause. (A cond clause with t is like an "else" in an "if" statement in other langugaes.)
This function is recursive, if you call it with an argument of 2, it checks if 2 == 0, it doesn't so then it multiplies 2 with the value returned by recursively calling itself with 1. Since 1 != 0 it will return the value of 1 multiplied by the value of recursively calling itself with 0. Since 0 does equal 0 it just returns 1, which is used one layer to return 1 which is then used at the top layer of this recursion to return 2.
Common Lisp has a function trace which will let you see when your function is called and with what arguments. Typically each recursive call will be indented so you can see something like this:
(fact 2)
(fact 1)
(fact 0)
Which can be helpful for understanding this function.
(As mentioned in a comment - this function doesn't catch the case of a negative input - but that is error handling and could be easily fixed).
Related
Question Asked
(defun a-sum(n p)
(setq sum 0)
( loop for i from n to p
do(setq sum (+ sum i))
)
(format t "~d" sum)
)
My code works for all of my Test Cases but using the loop method I keep returning a NIL right before my value. Is there any way to stop this? Or maybe an alernative method I'm meant to use when faced with a probem like this?
Here is your code formatted in a readable way, please refer to https://stackoverflow.com/help/formatting when asking question and follow the conventional ways of formatting the programming language your question is about:
(defun a-sum (n p)
(setq sum 0)
(loop for i from n to p
do (setq sum (+ sum i)))
(format t "~d" sum))
There are some problems here, notably:
you call SETQ on symbol sum, but there is no variable in scope that is declared with such a name. You introduce variables with let, for example:
(let ((sum 0))
;; here you are allowed to use SETQ
(setq sum 1))
Strictly speaking, your code is not a conforming program for Lisp, but it still works: the call to SETQ does modify the symbol-value of sum, so that's as-if you used a global variable. This is usually not a good idea since then your functions have effects that are not localized to their body, but also change the environment.
In a function body, the last expression is the value returned by the function, so here the value being returned is the result of evaluating (format ...). In the case you format to a stream, which is the case here, the return value is always NIL. That's why you have a NIL result. If you want to return sum then you need to have sum as the last expression in your function.
Generally speaking, a function should do one thing, not mix different actions together: either you compute a sum, or you print it, but try not doing both at the same time (except when debugging).
The loop construct is powerful enough to do the job with needing to use an intermediate sum, calling do (setq ...), etc. Read LOOP for black belts and you should be able to rewrite it more concisely.
The sum of consecutive numbers is a well-known formula that admits a solution without loops.
I have been resisting giving an answer, because instructors should not ask students questions like this (see below).
The question is to write a function which computes the sum of i from n to p, where n and p are integers, n and p >= 0 and p >= n (the question does not state this latter requirement, and it's easy to relax it in the answer, but let's assume it).
Well, before you write some laborious and futile loop, think a bit. Write out the sum by hand:
s = n + n+1 + ... + p
= (n + n+1 + ... + p
+ p + p-1 + ... + n)/2
= (n+p + n+p + ... + n+p)/2
And now there are (p - n + 1) terms in this sum, all of which are n+p. So
s = (p - n + 1)*(n+p)/2
Or
(defun a-sum (n p)
(/ (* (+ (- p n) 1)
(+ n p))
2))
And here's why you do this:
> (time (a-sum/mindless 0 1000000000))
Evaluation took:
6.716 seconds of real time
6.716005 seconds of total run time (6.713082 user, 0.002923 system)
100.00% CPU
0 bytes consed
500000000500000000
> (time (a-sum 0 1000000000))
Evaluation took:
0.000 seconds of real time
0.000003 seconds of total run time (0.000002 user, 0.000001 system)
100.00% CPU
0 bytes consed
500000000500000000
So here's the thing: if you are the instructor and you're reading this (which I am sure you are, because I would be) don't ask questions which have well-known closed-form solutions and expect students to write the terrible brute-force solution, because doing that is teaching people to be bad programmers, and you should not do that.
In regular Racket, ((curry * 2) 3) works as expected, with 6 as a result.
However, in Typed Racket:
> ((curry * 2) 3)
; readline-input:3:0: Type Checker: could not apply function;
; wrong number of arguments provided
; expected: 0
; given: 1
; in: ((curry * 2) 3)
; [,bt for context]
Why?
I believe it has something to do with the fact that * can take only one argument, so when you curry it with a parameter, it is returning a procedure that takes no additional arguments. Type (curry * 2) at the command line in typed/racket and observe the result: (-> Number).
Note that there is only a return type and no parameter. I don't see a way around this in typed racket, but I hope that at least explains why it is happening. You should be safe to use currying with more complex procedures as long as they do not have an option to take only one parameter.
I'm trying to build a simple function that gets a number, checks if the number is more the zero and return the square root of the number:
#lang pl 03
(: sqrtt: Number -> Number)
(define (sqrtt root)
(cond [(null? root) error "no number ~s"]
[( < root 0) error "`sqrt' requires a non-negative input ~s"]
[else (sqrt root)]))
but the result I get when I'm trying to compile the function is:
type declaration: too many types after identifier in: (: sqrtt: Number
-> Number)
Why am I getting that error and how do I fix it?
Try this:
(define (sqrtt root)
(cond [(null? root) (error "no number ~s")]
[(< root 0) (error "`sqrt' requires a non-negative input ~s")]
[else (sqrt root)]))
You simply forgot the () around error. Remember that error is a procedure and, like all other procedures, to apply it you have to surround it with parentheses together with its arguments.
The error message you're getting tells you that you have too many types after an identifier in a : type declaration. Now in racket, sqrtt: counts as an identifier. What you probably meant was sqrtt :, with a space in between.
(: sqrtt : Number -> Number)
The difference is that type declarations of the form (: id : In ... -> Out) are treated specially, but those of the form (: id In ... -> Out) are not. And sqrtt: is counts as the id.
There's also the problem Oscar Lopez pointed out, where you're missing parens around the error calls. Whenever you call a function in racket, including error, you need to wrap the function call in parens.
Also, the (null? root) clause is useless, since root has the type Number and null? will always return false for numbers.
And another thing, depending on what the pl language does, if you get a type error from < afterwards, that's because < operates on only Real numbers, but the Number type can include complex numbers. So you might have to change the type to Real or something.
I was messing around in SLIME (connected a Clozure REPL) when I discovered this:
It looks like the variables +, *, and / are all bound to some variation on recent input, + is the input itself, * is the result of evaluating that input, and / is the result contained in a list.
Is this right? Who is responsible for this, SLIME or Clozure? I couldn't find anything in the SLIME manual.
Thanks!
; SLIME 2010-05-13
CL-USER> +
NIL
CL-USER> *
NIL
CL-USER> /
(NIL)
CL-USER> -
-
CL-USER> +
-
CL-USER> (list 1 2)
(1 2)
CL-USER> +
(LIST 1 2)
CL-USER> /
((LIST 1 2))
CL-USER> (+ 1 2)
3
CL-USER> /
(3)
CL-USER> *
(3)
CL-USER> (* 1 2)
2
CL-USER> *
2
CL-USER>
Those are all, and more, specified by the Common Lisp standard. Search the environment dictionary for 'Variable'.
+
++
+++
While a form is being evaluated by the top-level loop, the variable + is bound to the previous form read by the loop. The variable ++ holds the previous value of + (that is, the form evaluated two interactions ago), and +++ holds the previous value of ++.
-
While a form is being evaluated by the top-level loop, the variable - is bound to the form itself; that is, it is the value about to be given to + once this interaction is done.
*
**
***
While a form is being evaluated by the top-level loop, the variable * is bound to the result printed at the end of the last time through the loop; that is, it is the value produced by evaluating the form in +. If several values were produced, * contains the first value only; * contains nil if zero values were produced. The variable ** holds the previous value of * (that is, the result printed two interactions ago), and * holds the previous value of **.
/
//
///
While a form is being evaluated by the top-level loop, the variable / is bound to a list of the results printed at the end of the last time through the loop; that is, it is a list of all values produced by evaluating the form in +. The value of * should always be the same as the car of the value of /. The variable // holds the previous value of / (that is, the results printed two interactions ago), and /// holds the previous value of //. Therefore the value of ** should always be the same as the car of //, and similarly for * and ///.
From Common Lisp the Language, 2nd Edition 20.2
I'm writing a scheme interpreter, and in the case of an if statement such as:
(if (< 1 0) 'true)
Any interpreter I've tried just returns a new prompt. But when I coded this, I had an if for whether there was an alternative expression. What can I return in the if such that nothing gets printed?
(if (has-alternative if-expr)
(eval (alternative if-expr))
#f) ;; what do I return here?
According to the R6RS specification:
If <test> yields #f and no <alternate>
is specified, then the result of the
expression is unspecified.
So go wild, return anything you want! Although #f or '() are what I, personally, would expect.
Scheme can indeed return no values:
> (values)
In R5RS the one-armed form of if is specified to return an unspecified value.
That means it is up to you, to decide which value to return.
Quite a few Schemes have chosen to introduce a specific value called
"the unspecified value" and returns that value.
Others return "the invisible value" #<void> and the REPL is written
such that it doesn't print it.
> (void)
At first one might think, this is the same as (values),
but note the difference:
> (length (list (void)))
1
> (length (list (values)))
error> context expected 1 value, received 0 values
(Here (list ...) expected 1 value, but received nothing)
If #<void> is part of a list, it is printed:
> (list (void))
(#<void>)
A number of Schemes (PLT, Ikarus, Chicken) have a void type, which you can produce with (void).
In PLT at least, void is what you get when you do (when (< 1 0) #t).
(PLT v4 doesn't allow if without an else clause.)
When the return value is unspecified you can return what you like; the user just can't rely on that value being there, ever, or across implementations.
First, it's OK to require if to have an else clause, if it makes it easier for you. Second, Scheme supports returning multiple values from a function, so if you were to implement the return values as a list, you could have an empty list signify that no return value was given.
(if (has-alternative if-expr)
(eval (alternative if-expr)) ; make sure eval returns a list
'())
An important distinction here: I'm not returning an empty list if there was no else clause. The empty list signifies that there was no return value. If there were one return value from an expression (say it was 3) you would have (3) as the return from the eval behind the scenes. Similarly, returning multiple values from an expression would cause the eval return list to have multiple elements.
Finally, in all practicality, you could really return anything if the condition fails and there's no else, because it would be an error in a program to attempt to capture the value of a function that doesn't return anything. As such, it would be the job of the programmer, not the language, to catch this error.
Weird people would return 'nil or '|| (the empty symbol). The problem is to return a symbol that cannot be return by (eval (alternative if-expr)) to avoid confusion.
If anything can be returned by (eval (alternative if-expr)) and you still want to know whether you came in this alternative or not, you have to pack the result with more information :
(if (has-alternative if-expr)
(cons #t (eval (alternative if-expr)))
(cons #f #f))
Thus, the result is a cons cell. If its car is #t, then you evaled something. If it is #f, you didn't.
What is wrong with just:
(if (has-alternative if-expr) (eval (alternative if-expr)))
?