Can anyone help me with this please?
(define f (lambda (x)
(cond
((null? x) 0)
(#t (+ (* (car x) (car x)) (f (cdr x)))))))
I couldn't understand if this function is tail recursive or not?
If it is, what is the reason?
It's not tail recursive because the last thing the function does before returning is to evaluate (+ ...). In order to be tail recursive the last operation before returning has to be the recursive call.
Making a function tail recursive usually involves a helper function which takes an accumulator parameter:
(define f0 (lambda (x acc)
(if (null? x)
acc
(f0 (cdr x) (+ acc (* (car x)(car x)))))))
(define f (lambda (x)
(f0 x 0)))
Related
I'm new in lisp, I'm trying to define a simple function that search an element in a list.
I'm not finding myself comfortable with the sintax of the language, also I don't quite understand the error/warning messages.
(defun in-list (x l)
(let y (car l))
(let z (cdr l))
(if (null l)
nil
(if (equal x y)
t
(in-list x z)
)
)
)
I also tried to replace let with seq, but still gave me warnings on "variables assumed to be special".
There is an error in the syntax of let. The correct form is:
(let ((var1 exp1)
(var2 exp2)
...
(varn expn))
body-of-let)
So you should write:
(defun in-list (x l)
(let ((y (car l))
(z (cdr l)))
(if (null l)
nil
(if (equal x y)
t
(in-list x z)))))
Note that it is not necessary define the two local variables since the corresponding expression is used only once, so you could abbreviate the function in this way:
(defun in-list (x l)
(if (null l)
nil
(if (equal x (car l))
t
(in-list x (cdr l)))))
and, since you have three different cases in the body, you could use a single cond instead of two if:
(defun in-list (x l)
(cond ((null l) nil)
((equal x (car l)) t)
(t (in-list x (cdr l)))))
There are very good free books on the web to learn the basis of the language. See for instance this one.
To be able to use setq, you can declare your function's inner variables after the &aux keyword in the function's lambda-list:
(defun in-list (x l &aux y z)
(setq y (car l)
z (cdr l))
(and l
(or (equal x y)
(in-list x z))))
A better style is to give the auxiliary variables their values right at the point of declaration:
(defun in-list (x l &aux (y (car l)) (z (cdr l)))
(and l
(or (equal x y)
(in-list x z))))
Can Horner's method be implemented in lisp using mapcan or any other map function?
Here is my implementation without map functions:
(defun Horner (lst x)
(cond
((null (cdr lst)) (car lst))
(t
(Horner
(cons
(+ (* (car lst) x) (cadr lst))
(cddr lst)
)
x
)
)
)
)
You cannot do it with map-like functions because they produce lists and
you need the result to be a number.
However, not all is lost --
reduce to the rescue!
(defun horner (polynomial x)
(reduce (lambda (a b)
(+ (* a x) b))
polynomial :initial-value 0))
Note that this version also handles the 0 polynomial correctly: it
returns 0 when called as (horner () 1) (replace 1 with any number).
This glitch in your tail-recursive version is easily fixed:
(defun horner (polynomial x)
(if (rest polynomial)
(horner (cons (+ (* (first polynomial) x) (second polynomial))
(cddr polynomial))
x)
(or (first polynomial) 0)))
What's wrong with this code?
(defun f (l)
(funcall #'(lambda (ff)
(cond
((null l)nil)
((listp (car l)) (append ff (f (cdr l)) (car ff)))
(t (list (car l)))))
(f (car l))))
If I enter (f '(( 1 2 3))) it gives me an error:
"Cannot take car of 1".
What's wrong?
Here is a more detailed explanation of the comment of #Sylwester, that answers correctly to the question.
If you write (f '((1 2 3)) then the function f is called, l is bound to ((1 2 3)), and the result is the application of the internal function (lambda (ff) (cond ...)) to the value of (f (car l)).
To perform this application, first (f (car l)) is evaluated to produce a value, and since l is bound to ((1 2 3)), its car is (1 2 3).
So, f is applied to the list (1 2 3), which is bound to l in the recursive call. This evaluation again means that fshould apply the internal function (lambda (ff) (cond ...)) to the value of (f (car l)), that is to (f 1).
The process is reapeated, l is bound this time to 1, and again fshould apply the internal function (lambda (ff) (cond ...)) to the value of (f (car l)), but, since l is now 1, the function tries to evaluate the (car 1), which produces the error that you have found.
since yesterday I've been trying to program a special case statement for scheme that would do the following:
(define (sort x)
(cond ((and (list? x) x) => (lambda (l)
(sort-list l)))
((and (pair? x) x) => (lambda (p)
(if (> (car p) (cdr p))
(cons (cdr p) (car p))
p)))
(else "here")))
instead of using all the and's and cond's statement, I would have:
(define (sort x)
(scase ((list? x) => (lambda (l)
(sort-list l)))
((pair? x) => (lambda (p)
(if (> (car p) (cdr p))
(cons (cdr p) (car p))
p)))
(else "here")))
What I could do so far, was this:
(define (sort x)
(scase (list? x) (lambda (l)
(sort-list l)))
(scase (pair? x) (lambda (p)
(if (> (car p) (cdr p))
(cons (cdr p) (car p))
p))))
with this code:
(define-syntax scase
(syntax-rules ()
((if condition body ...)
(if condition
(begin
body ...)))))
What I wanted to do now, is just allow the scase statement to have multiple arguments like this:
(scase ((list? (cons 2 1)) 'here)
((list? '(2 1)) 'working))
but I can't seem to figure out how I can do that. Maybe you guys could give me a little help?
Thanks in advance ;)
If this is an exercise in learning how to use syntax-rules, then disregard this answer.
I see a way to simplify your code that you are starting with.
(define (sort x)
(cond ((list? x)
(sort-list x))
((pair? x)
(if (> (car x) (cdr x))
(cons (cdr x) (car x))
x)))
(else "here")))
Since all the (and (list? x) x) => (lambda l ... does is see if x is a list, and then bind l to x, (since #f is not a list, and '() is not false, at least in Racket), you can just skip all that and just use x. You do not need to use => in case, and in this case it doesn't help. => is useful if you want to do an test that returns something useful if successful, or #f otherwise.
Now, if you want to use a macro, then you're going to need to clarify what you want it to do a bit better. I think that case already does what you want. Your existing macro is just if, so I'm not sure how to extend it.
I found the solution for my question, here it goes:
(define-syntax cases
(syntax-rules ()
((_ (e0 e1 e2 ...)) (if e0 (begin e1 e2 ...)))
((_ (e0 e1 e2 ...) c1 c2 ...)
(if e0 (begin e1 e2 ...) (cases c1 c2 ...)))))
Thank you all anyway :)
Here's a solution :
#lang racket
(require mzlib/defmacro)
(define-syntax scase
(syntax-rules (else)
((_ (else body1)) body1)
((_ (condition1 body1) (condition2 body2) ...)
(if condition1
body1
(scase (condition2 body2) ...)))))
(define (sort1 x)
((scase ((list? x) (lambda (l)
(sort l <)))
((pair? x) (lambda (p)
(if (> (car p) (cdr p))
(cons (cdr p) (car p))
p)))
(else (lambda (e) "here")))
x))
It works in DrRacket. I made three changes to your solution. First, i renamed your sort procedure to sort1 since sort is inbuilt in scheme ( I have used it inside sort1). Second, I have changed the sort1 itself so that the input given will be passed to the procedure returned by scase and you will directly get the sorted result. Third, I have modified the scase syntax extension, so that it will accept the else condition.
>(sort1 (list 3 1 2))
'(1 2 3)
> (sort1 (cons 2 1))
'(1 . 2)
> (sort1 'here)
"here"
I suggest you read "The Scheme Programming Language" by Kent Dybvig. There is an entire chapter on syntactic extensions.
Goal: implement unfold function using only two arguments.
The arguments:
the first argument is f which takes an initial value of some type I and returns nil or a cons pair of two elements (the first of these two is the next element that goes in the list of some type A and the next initial value again of some type I).
The second argument is an initial value of some type I and the return is a list of items of type A.
This is what I have so far and I am not sure why it is not working:
(define (descending i)
(if (= i 0)
(list)
(cons i (- i 1))))
(define nil (list))
(define (unfold f init)
(if (eq? (f init) '())
(list)
(cons init (unfold f (f init)))))
(unfold (descending 5))
should evaluate to
'(5 4 3 2 1)
This should be the result but isn't. What am I doing wrong?
First, it should be (unfold descending 5). Then f would produce a pair and you would use both components of it,
(define (unfold f init)
(if (eq? (f init) '())
(list)
(cons (car (f init)) (unfold f (cdr (f init))))))
But this has awful computational complexity as it calls (f init) three times per iteration. A humble let binding remedies this.
(define (unfold f init)
(let ((r (f init)))
(if (empty? r) ;; instead of (eq? r '())
(list)
(cons (car r) (unfold f (cdr r))))))
And a tail recursive form using named let
(define (unfold f init)
(let loop ((acc empty)
(state (f init)))
(if (empty? state)
(reverse acc)
(loop (cons (car state) acc)
(f (cdr state))))))
And using match.
(define (unfold f init)
(let loop ((acc empty)
(state (f init)))
(match state
((cons x next)
(loop (cons x acc)
(f next)))
(empty
(reverse acc)))))