Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I am very new to lisp, and am having a hard time even getting my feet wet. I'm sure once, I have a few functions working, I'll be able to build upon them and work on higher order functions, and more complex problems.
Can someone point out my errors in the following code.
(defun indeHelper(A L N)
(cond (Null N) nil)
((= A (first L) (cons N (indeHelper A (rest L) (+ 1 N)))))
(t (indeHelper A (rest L) (+ 1 N))))
(defun inde(A L)
(funcall indeHelper(A L 1)))
Also how would I call this? I have one function I think is working ok, but I can't get the syntax for calling it. Thanks for any help.
You have a number of syntax issues.
The syntax of COND is:
(cond (test1 body1...)
(test2 body2...)
...)
Your test1 is supposed to be (null n), and body1 should be nil, but you didn't wrap them in a level of parentheses. Then your other tests and bodies are outside cond, as should be apparent from the indentation.
It should be:
(defun indeHelper(A L N)
(cond ((Null N) nil)
((= A (first L) (cons N (indeHelper A (rest L) (+ 1 N)))))
(t (indeHelper A (rest L) (+ 1 N)))))
In the second function, you don't need to use funcall. That's used when you're calling a dynamically-determined function (e.g. when writing higher-order functions), but you're just calling a known function. It should just be:
(defun inde(A L)
(indeHelper A L 1))
If you did need to use funcall, the syntax is:
(funcall someVariable A L 1)
When using funcall, the arguments aren't put into a nested list, they're just ordinary arguments to funcall.
Related
I'm making my way through the book The Little Schemer to start to learn to think in Lisp. As you get into it and really cover the use of lambdas, the 'remove' procedure is written in the following general form, which returns a remove procedure for arbitrary test test?:
(define rember-f
(lambda (test?)
(lambda (a l)
(cond
((null? l) (quote ()))
((test? (car l) a) (cdr l))
(else (cons (car l)
((rember-f test?) a (cdr l))))))))
I understand how this works just fine, but a plain reading of it suggests that at each recursive step, it is the procedure rember-f that is called again to generate a new enclosed procedure. This would mean when you call your returned procedure on a list, it calls rember-f to generate the same procedure again anew and then that new one is what is called for recursion (if that is not clear see my fix below). I understand that this may be optimized away, but in lieu of not knowing whether it is (and also in attempting to get my head around this syntax anyway), I managed after some experimentation to move the recursion to the procedure itself rather than the enclosing procedure as follows:
(define rember-f
(lambda (test?)
(define retfun
(lambda (a l)
(cond
((null? l) (quote ()))
((test? (car l) a) (cdr l))
(else (cons (car l) (retfun a (cdr l)))))))
retfun))
I have verified that this works as expected. The return value is a procedure that removes the first element of a list (arg 2) matching a value (arg 1). It looks to me like this one only calls rember-f once, which guarantees it only generates one enclosed procedure (this time with a name, retfun).
This is actually interesting to me because unlike the usual tail call optimization, which is about not consuming space on the call stack and so making recursion about as efficient as iteration, in this case the compiler would have to determine that (rember-f test?) is the enclosing procedure scope unmodified and so replace it with the same return value, which is the anonymous (lambda (a l) ...). It would not surprise me at all to learn that the interpreter / compiler does not catch this.
Yes, I know that scheme is a specification and there are many implementations, which get the various functional programming optimizations right to differing degrees. I am currently learning by experimenting in the guile REPL, but would be interested in how different implementations compare on this issue.
Does anyone know how Scheme is supposed to behave in this instance?
You are right to be concerned about the additional repeated lambda abstractions. For example you wouldn't write this, would you?
(cond ((> (some-expensive-computation x) 0) ...)
((< (some-expensive-computation x) 0) ...)
(else ...))
Instead we bind the result of some-expensive-computation to an identifier so we can check multiple conditions on the same value -
(let ((result (some-expensive-computation x)))
(cond ((> result 0) ...)
((< result 0) ...)
(else ...)))
You discovered the essential purpose of so-called "named let" expressions. Here's your program -
(define rember-f
(lambda (test?)
(define retfun
(lambda (a l)
(cond
((null? l) (quote ()))
((test? (car l) a) (cdr l))
(else (cons (car l) (retfun a (cdr l)))))))
retfun))
And its equivalent using a named-let expression. Below we bind the let body to loop, which is a callable procedure allowing recursion of the body. Notice how the lambda abstractions are used just once, and the inner lambda can be repeated without creating/evaluating additional lambdas -
(define rember-f
(lambda (test?)
(lambda (a l)
(let loop ; name, "loop", or anything of your choice
((l l)) ; bindings, here we shadow l, or could rename it
(cond
((null? l) (quote ()))
((test? (car l) a) (cdr l))
(else (cons (car l) (loop (cdr l))))))))) ; apply "loop" with args
Let's run it -
((rember-f eq?) 'c '(a b c d e f))
'(a b d e f)
The syntax for named-let is -
(let proc-identifier ((arg-identifier initial-expr) ...)
body ...)
Named-let is a syntax sugar of a letrec binding -
(define rember-f
(lambda (test?)
(lambda (a l)
(letrec ((loop (lambda (l)
(cond
((null? l) (quote ()))
((test? (car l) a) (cdr l))
(else (cons (car l) (loop (cdr l))))))))
(loop l)))))
((rember-f eq?) 'c '(a b c d e f))
'(a b d e f)
Similarly, you could imagine using a nested define -
(define rember-f
(lambda (test?)
(lambda (a l)
(define (loop l)
(cond
((null? l) (quote ()))
((test? (car l) a) (cdr l))
(else (cons (car l) (loop (cdr l))))))
(loop l))))
((rember-f eq?) 'c '(a b c d e f))
'(a b d e f)
PS, you you can write '() in place of (quote ())
Both procedures have the same asymptotic time complexity. Let's consider the evaluation of ((rember-f =) 1 '(5 4 3 2 1 0)).
A partial evaluation proceeds as follows:
((rember-f =) 1 '(5 4 3 2 1 0))
((lambda (a l)
(cond
((null? l) (quote ()))
((= (car l) a) (cdr l))
(else (cons (car l)
((rember-f =) a (cdr l)))))) 1 '(5 4 3 2 1 0))
(cons 5 ((rember-f = 1 '(4 3 2 1 0))))
Note that the creation of the temporary lambda procedure takes O(1) time and space. So it doesn't actually add any substantial overhead to the cost of calling the function. At best, factoring out the function will lead to a constant-factor speedup and the use of a constant amount less of memory.
But how much memory does it really take to make a closure? It turns out it takes very little memory. A closure consists of a pointer to the environment and a pointer to compiled code. Basically, creating the closure requires as much time and space as making a cons cell. So even though it looks like we're using a lot of memory when I show the evaluation, very little memory and very little time is actually used to make and store the lambda.
So essentially, by factoring out the recursive function, you've allocated a single cons cell rather than writing code which allocates that cons cell one time per recursive call.
For more information on this, see Lambda is cheap, and Closures are Fast.
to start to learn to think in Lisp
That book is not about thinking in lisp, but about recursive thinking, which is one of the ways of computation discovered in the 20th century by Goedel, Herbrand, Rozsa Peter.
Does anyone know how Scheme is supposed to behave in this instance?
After you finish the little lisper you should take the SICP, which will make you understand what kind of decisions an implementation of a language can make. You mean, how different implementations act. To understand their implementation decision, the best step to do is to learn it from SICP. Take care, unless you are already a certified computer science graduate, this texbook will take you a few years to master, if you study it each day. If you are already a graduate, it will take you only about 1 year to master.
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 3 years ago.
Improve this question
I am losing my mind over evaluating this code to find the error. I am not sure why I am getting an undefined function. Would someone please guide me to understand why? thanks!
O is supposed to be an object, and L a list. I am trying to attach O to the end of the list and return the list
(defun my_attach(O L)
(cond ((eq L nil )
O )
(t (cons (car L) (my-attach O (cdr L)) )
)
)
)
If you have copied correctly your code in the post, you have used two different names for the same function: my_attach (_ is the underscore character) and my-attach (- is the dash character).
Simply use the same name. For instance:
(defun my-attach(O L)
(cond ((eq L nil ) O)
(t (cons (car L) (my-attach O (cdr L))))))
But note that this will not produce the desired result (in fact it does not produce a proper list). Rather, you should use (list O) instead of O in the terminal case:
CL-USER> (defun my-attach(O L)
(cond ((eq L nil) O)
(t (cons (car L) (my-attach O (cdr L))))))
MY-ATTACH
CL-USER> (my-attach 3 '(1 2))
(1 2 . 3)
CL-USER> (my-attach 3 '())
3
CL-USER> (defun my-attach(O L)
(cond ((eq L nil) (list O))
(t (cons (car L) (my-attach O (cdr L))))))
MY-ATTACH
CL-USER> (my-attach 3 '(1 2))
(1 2 3)
CL-USER> (my-attach 3 '())
(3)
Finally, a note about the common writing conventions for Common Lisp programs:
it is preferred to use lower case identifiers;
compound words in identifiers are separated by -, not by _ as in other languages;
it is preferred to use if when there are only two cases in a conditional statement;
check for a value which is nil is commonly done with the predicate null;
the parentheses at the end of an expression are usually written on the same line of the last part of the expression.
So your function could be rewritten as:
(defun my-attach (o l)
(if (null l)
(list o)
(cons (car l) (my-attach o (cdr l)))))
need help on making these two recursive programs in scheme iterative?
I made the recursion, but am stuck at creating an iteration for both.
question 1 - recursion
(define mylength
(lambda (l)
(cond
((null? l) 0)
(else (+ 1 (mylength (cdr l)))))))
question 1 - iteration?
question 2 - recursion
(define mylistref
(lambda (l index)
(cond
((= index 0)(car l))
(else
(mylistref (cdr l) (- index 1))))))
question 2 - iteration?
Scheme does not have any looping structures so your only option is to use recursion if you are traversing over some kind of data structure. You can read more about it here
The function is supposed to be tail-recursive and count from 1 to the specified number. I think I'm fairly close. Here's what I have:
(define (countup l)
(if (= 1 l)
(list l)
(list
(countup (- l 1))
l
)
)
)
However, this obviously returns a list with nested lists. I've attempted to use the append function instead of the second list to no avail. Any guidance?
Here's an incorrect solution:
(define (countup n)
(define (help i)
(if (<= i n)
(cons i (help (+ i 1)))
'()))
(help 1))
This solution:
uses a helper function
recurses over the numbers from 1 to n, cons-ing them onto an ever-growing list
Why is this wrong? It's not really tail-recursive, because it creates a big long line of cons calls which can't be evaluated immediately. This would cause a stack overflow for large enough values of n.
Here's a better way to approach this problem:
(define (countup n)
(define (help i nums)
(if (> i 0)
(help (- i 1)
(cons i nums))
nums)))
(help n '()))
Things to note:
this solution is better because the calls to cons can be evaluated immediately, so this function is a candidate for tail-recursion optimization (TCO), in which case stack space won't be a problem.
help recurses over the numbers backwards, thus avoiding the need to use append, which can be quite expensive
You should use an auxiliar function for implementing a tail-recursive solution for this problem (a "loop" function), and use an extra parameter for accumulating the answer. Something like this:
(define (countup n)
(loop n '()))
(define (loop i acc)
(if (zero? i)
acc
(loop (sub1 i) (cons i acc))))
Alternatively, you could use a named let. Either way, the solution is tail-recursive and a parameter is used for accumulating values, notice that the recursion advances backwards, starting at n and counting back to 0, consing each value in turn at the beginning of the list:
(define (countup n)
(let loop ((i n)
(acc '()))
(if (zero? i)
acc
(loop (sub1 i) (cons i acc)))))
Here a working version of your code that returns a list in the proper order (I replaced l by n):
(define (countup n)
(if (= 1 n)
(list n)
(append (countup (- n 1)) (list n))))
Sadly, there is a problem with this piece of code: it is not tail-recursive. The reason is that the recursive call to countup is not in a tail position. It is not in tail position because I'm doing an append of the result of (countup (- l 1)), so the tail call is append (or list when n = 1) and not countup. This means this piece of code is a normal recusrive function but to a tail-recursive function.
Check this link from Wikipedia for a better example on why it is not tail-recusrive.
To make it tail-recursive, you would need to have an accumulator responsible of accumulating the counted values. This way, you would be able to put the recursive function call in a tail position. See the difference in the link I gave you.
Don't hesitate to reply if you need further details.
Assuming this is for a learning exercise and you want this kind of behaviour:
(countup 5) => (list 1 2 3 4 5)
Here's a hint - in a tail-recursive function, the call in tail position should be to itself (unless it is the edge case).
Since countup doesn't take a list of numbers, you will need an accumulator function that takes a number and a list, and returns a list.
Here is a template:
;; countup : number -> (listof number)
(define (countup l)
;; countup-acc : number, (listof number) -> (listof number)
(define (countup-acc c ls)
(if ...
...
(countup-acc ... ...)))
(countup-acc l null))
In the inner call to countup-acc, you will need to alter the argument that is checked for in the edge case to get it closer to that edge case, and you will need to alter the other argument to get it closer to what you want to return in the end.
I need a function that will take in a list of characters and numbers, and then return the numbers added up (ignoring the characters). This is what I have so far:
(define (adder lst)
(cond
((null? lst)
0)
((number? (car lst))
(+(adder (car lst)) (adder (cdr lst))))
((char? (car lst))
((adder(cdr lst))))
))
(display (adder '(asd12sdf)))
Running it on codepad.org just displays void. I know the code is wrong because it looks wrong, but I have no idea how to fix it... How do I have the function keep track of the first number it finds and add it to the next one it finds, while skipping all characters?
In your second cond case, there's no reason to run adder on (car lst). Just adding (car list) itself to the recursive step should work.
For the last line, don't test (char? (car lst)). Just make the last line the else clause, meaning that anything BUT a number will go to the else line.
The reason you're getting void is because your input doesn't satisfy any of the cond conditions, and you have no else, so the answer is nothing (i.e. (void)).
The last mistake is in the input you're giving it. '(asd12sdf) is literally a list with one symbol named "asd12sdf". I think you want to give it '(a s d 1 2 s d f) (a list of 6 symbols and 2 numbers) which should result in 3. Notice that there's a very important difference between the symbol 'a and the character #\a.
It looks like you have the logic down, so your problem doesn't seem to be functional languages, just Scheme's syntax.
Edit: and in the last line, you have ((adder(cdr lst))) which has one too many parens wrapped around it. That will cause Scheme to attempt to evaluate the result of adder (which is a number) as a procedure (error!).
You should observe that this function is more or less sum which can be defined simply by using fold.
(define (adder lst)
(fold + 0 lst))
What does fold do? Basically, it's defined like so:
(define (fold f initial lst)
(if (null? lst)
initial
(fold f (f (car lst) initial) (cdr lst))))
(In other words, it calls f, a function of 2 arguments, on each element of lst, using the car of the lst as the first argument, and the accumulated result as the second argument to f.)
The issue here which you need to address is that + doesn't know how to operate on non-numeric values. No problem, you've already dealt with that. What happens if it's a character instead? Well, you're not adding anything to the total value, so replace it with a 0. Therefore, your solution is as simple as:
(define (adder lst)
(fold your-new-protected-+ 0 lst))
In Common Lisp:
(reduce #'+ '(1 #\a #\b 2 1 2 #\c #\d 4)
:key (lambda (item) (if (numberp item) item 0)))
or
(loop for item in '(1 #\a #\b 2 1 2 #\c #\d 4)
when (numberp item) sum item)