How to explain funny behavior of call/cc in Racket? - racket

combine must map reduce a list with the binary operator bin but must return exc if it finds any value that fails the predicate pred?, and if it finds any such value it must not perform any calculation on the list.
This is a simple continuation problem.
#lang racket
(define (id x)
x)
(define (const x)
(lambda (_) x))
(define (combine pred? bin zero exc)
(call/cc
(lambda (exit)
(letrec
((f (lambda (xs)
(if (empty? xs)
zero
(if (pred? (first xs))
(exit exc)
(bin (first xs) (f (rest xs))))))))
f))))
(define product
(combine zero?
*
1
0))
(product '(1 2 3 0 4))
The code almost works, but it has a very subtle error.
It raises the following exception:
define-values: assignment disallowed;
cannot re-define a constant
constant: product
It is easy to make it work. Only a small change is needed:
(define (combine pred? bin un zero exc)
(lambda (ys)
(call/cc
(lambda (exit)
(letrec
((f (lambda (xs)
(if (empty? xs)
zero
(if (pred? (first xs))
(exit exc)
(bin (first xs) (f (rest xs))))))))
(f ys))))))
I see that the problem is that Racket the continuation of define is to define a function, but can anyone give more details? What syntatic transformations involved, for example?

Think of the order you have to have here:
(define product (combine ....))
Here you first evaluate (combine ...) and the continuation is the rest of the program starting with storing the computed value as the name product. Calling the continuation from withing f jumps right back to storing product all over again.
By calling (product '(1 2 3 0 4)) you are redefining product since it is the continuation of the program and call/cc captures the continuation.
In your second attempt you do a true refactoring of wrapping it in a lambda and call f with the same argument. It's just delaying when the call/cc happens and thus what is included in the continuation. In this version the continuation is whatever comes after the (product ...) and not the setting pf product in (define product ...)

Related

Get the maximum value of a list with three numbers

I'm learning Lisp now, and I'm trying to do an exercise that asks me to get the maximum value of a list, the syntax is totally different from most programming languages I've learned, so I'm having some difficulties.
My code:
(defun test(y)
(cond
((and (first y) (> (second y)) (> (third y)))
(format t "numero maximo ~d" (first y))
((and (second y) (> (first y)) (> (third y)))
(t (format t "numero maximo ~d" (second y))
((and (third y) (> (second y)) (> (first y)))
(t (format t "numero maximo ~d" (third y))
))
I'm receiving this error: incomplete s-expression in region
Your code is too complex, it tries to take elements from a list, compare them, and print something. Like in other languages, use smaller functions and, particularly with a new language, test often in order to avoid having to debug something too large.
Your code, automatically indented with Emacs, looks as follows:
(defun test(y)
(cond
((and (first y) (> (second y)) (> (third y)))
(format t "numero maximo ~d" (first y))
((and (second y) (> (first y)) (> (third y)))
(t (format t "numero maximo ~d" (second y))
((and (third y) (> (second y)) (> (first y)))
(t (format t "numero maximo ~d" (third y))
))
And the editor complains about unbalanced parentheses:
In (> (second y)), the > function is given only one argument
All your cond clauses are in fact nested inside the first clause. Using an editor that highlights matching parentheses helps a lot here. The syntax should be:
(cond
(test-1 ...)
(test-2 ...)
(t ...))
If your test involves calling predicates, then it looks like:
(cond
((and (f1 ...) (f2 ...)) ;; <-- test
... ;; <-- code
) ;; end of first clause
) ;; end of cond
But note that you do not need to put comments for closing delimiters, the indentation and the automatic highlighting of parentheses should help you avoid mistakes.
Let's try a rewrite.
First of all, you can write a function that just compares numbers, not thinking about lists or formatting; here is a very straightforward max-of-3 implementation (without cheating and calling the built-in max function):
(defun max-of-3 (x y z)
(if (> x y)
(if (> x z) x z)
(if (> y z) y z)))
Evaluate the function, and test it on multiple inputs, for example in the REPL:
CL-USER> (max-of-3 0 2 1)
2
....
Then, you can build up the other function, for your list:
(defun test (list)
(format t
"numero maximo ~d"
(max-of-3 (first list)
(second list)
(third list))))
If you need to do more error checking ahead of time, like checking that the lists is well-formed, you should probably define other auxiliary functions.
If I understood the question and answer, I might be able to provide a solution or two that returns the max, regardless of the length of the list. So, these solutions are not limited to a list of three.
This illustrates a way to test where "max-lst" is the Lisp function under test:
(defconstant test-case
(list 1 2 0 8 7 6 9 4 5))
(defun run-test ()
(max-lst test-case))
Solution 1
This solution uses recursion. If you like loops better, Lisp has several loops. The Lisp function "max" is not used:
(defun max-lst (lst-in)
(cond ((null (second lst-in))
(first lst-in))
((> (first lst-in) (second lst-in))
(max-lst
(list* (first lst-in) (rest (rest lst-in)))))
(t
(max-lst
(list* (rest lst-in))))))
Solution 2
If you have no objection to using the Lisp function "max," here is a solution using max.
Note that max is not limited to two arguments.
(max 5 6 4 7 3)
will return 7.
In this solution, the function "max" is passed to the function "reduce" as an argument. The "reduce" function takes a function and a list as arguments. The function is applied to each adjacent pair of arguments and returns the result. If you want the sum, you can pass the + argument.
(defun max-lst-using-max (lst-in)
(reduce #'max lst-in))
Alas, I fear that I provide these solutions too late to be pertinent to the original poster. But maybe someone else will have a similar question. So, perhaps this could help, after all.

How do I call another function in lisp;

My program is supposed to convert a given temperature from Fahrenheit to Centigrade or the other way around. It takes in a list containing a number and a letter. The letter is the temperature and the letter is the unit we are in. Then I call the appropriate function either F-to-C or C-to-F. How do I call the functions with the given list that was first checked in my temperature-conversion function. Here is my code.
(defun temperature-conversion (lst)
(cond
((member 'F lst) (F-to-C))
((member 'C lst) (C-to-F))
(t (print "You didn't enter a valid unit for conversion"))
)
)
(defun F-to-C ()
;;(print "hello")
(print (temperature-conversion(lst)))
)
(defun C-to-F ()
(print "goodbye"))
;;(print (temperature-conversion '(900 f)))
(setf data1 '(900 f))
You have infinite recursion: temperature-conversion calls F-to-C which calls temperature-conversion again.
I would do this:
(defun c2f (c) (+ 32 (/ (* 9 c) 5)))
(defun f2c (f) (/ (* 5 (- f 32)) 9))
(defun temperature-conversion (spec)
(ecase (second spec)
(C (c2f (first spec)))
(F (f2c (first spec)))))
(temperature-conversion '(32 f))
==> 0
(temperature-conversion '(100 c))
==> 212
(temperature-conversion '(100))
*** - The value of (SECOND SPEC) must be one of C, F
The value is: NIL
The following restarts are available:
ABORT :R1 Abort main loop
I think this example is generally used to demonstrate how functions are first-class values.
With a little modification to sds's answer, you can have an ECASE statement that selects the appropriate function, which is then used by a surrounding FUNCALL.
(defun temperature-conversion (spec)
(destructuring-bind (temperature unit) spec
(funcall
(ecase unit (C #'c2f) (F #'f2c))
temperature)))
I added a DESTRUCTURING-BIND in case you don't know yet what it is.

'('(LIST) 'NIL 'NIL) should be a lambda expression in (hanoi('('(list)'()'())))

I'm trying to implement the Towers of Hanoi.I'm not printing out anything between my recursive calls yet, but I keep getting an error saying
'('(LIST) 'NIL 'NIL) should be a lambda expression
I've read that the reason this happens is because of a problem with the parenthesis, however I cannot seem to find what my problem is. I think it's happening in the pass-list function when I am trying to call the hanoi function. My code:
(defun pass-list(list)
(hanoi('('(list)'()'())))
)
(defun hanoi ('('(1) '(2) '(3)))
(hanoi '('(cdr 1) '(cons(car 1) 2) '(3)))
(hanoi '('(cons(car 3)1) '(2)'(cdr 3)))
)
This code has many syntax problems; there are erroneous quotes all over the place, and it looks like you're trying to use numbers as variables, which will not work. The source of the particular error message that you mentioned comes from
(hanoi('('(list)'()'())))
First, understand that the quotes in 'x and '(a b c) are shorthand for the forms (quote x) and (quote (a b c)), and that (quote anything) is the syntax for getting anything, without anything being evaluated. So '(1 2 3) gives you the list (1 2 3), and '1 gives you 1. quote is just a symbol though, and can be present in other lists, so '('(list)'()'()) is the same as (quote ((quote (list)) (quote ()) (quote ()))) which evaluates to the list ((quote (list)) (quote ()) (quote ())). Since () can also be written nil (or NIL), this last is the same as ('(list) 'NIL 'NIL). In Common Lisp, function calls look like
(function arg1 arg2 ...)
where each argi is a form, and function is either a symbol (e.g., list, hanoi, car) or a list, in which case it must be a lambda expression, e.g., (lambda (x) (+ x x)). So, in your line
(hanoi('('(list)'()'())))
we have a function call. function is hanoi, and arg1 is ('('(list)'()'())). But how will this arg1 be evaluated? Well, it's a list, which means it's a function application. What's the function part? It's
'('(list)'()'())
which is the same as
'('(list 'NIL 'NIL))
But as I just said, the only kind of list that can be function is a lambda expression. This clearly isn't a lambda expression, so you get the error that you're seeing.
I can't be sure, but it looks like you were aiming for something like the following. The line marked with ** is sort of problematic, because you're calling hanoi with some arguments, and when it returns (if it ever returns; it seems to me like you'd recurse forever in this case), you don't do anything with the result. It's ignored, and then you go onto the third line.
(defun pass-list(list)
(hanoi (list list) '() '()))
(defun hanoi (a b c)
(hanoi (rest a) (cons (first a) b) c) ; **
(hanoi (cons (first c) a) b (rest c)))
If hanoi is supposed to take a single list as an argument, and that list is supposed to contain three lists (I'm not sure why you'd do it that way instead of having hanoi take just three arguments, but that's a different question, I suppose), it's easy enough to modify; just take an argument abc and extract the first, second, and third lists from it, and pass a single list to hanoi on the recursive call:
(defun hanoi (abc)
(let ((a (first abc))
(b (second abc))
(c (third abc)))
(hanoi (list (rest a) (cons (first a) b) c))
(hanoi (list (cons (first c) a) b (rest c)))))
I'd actually probably use destructuring-bind here to simplify getting a, b, and c out of abc:
(defun hanoi (abc)
(destructuring-bind (a b c) abc
(hanoi (list (rest a) (cons (first a) b) c))
(hanoi (list (cons (first c) a) b (rest c)))))

Forming Lisp code to task -- related to flatten list method

I'm having issues trying to form code for a problem I want to resolve. It goes like this:
~ Goal: flatten a nested list into one number
If the object is a list, replace the list with the sum of its atoms.
With nested lists, flatten the innermost lists first and work from there.
Example:
(CONDENSE '(2 3 4 (3 1 1 1) (2 3 (1 2)) 5))
(2 3 4 (6) (2 3 (3)) 5)
(2 3 4 (6) (8) 5)
(28)
=> 28
I've tried to implement the flatten list function for this problem and I ended up with this:
(defun condense (lst)
(cond
((null lst) nil)
((atom lst) (list lst)))
(t (append (flatten (apply #'+ (cdr lst))))))
But it gives me errors :(
Could anyone explain to me what is wrong with my processing/code? How can I improve it?
UPDATE: JUNE 5 2012
(defun condense(lxt)
(typecase lxt
(number (abs lxt))
(list
(if (all-atoms lxt)
(calculate lxt)
(condense (mapcar #'condense lxt))))))
So here, in this code, my true intent is shown. I have a function calculate that performs a calculation based off the values in the list. It is not necessarily the same operation each time. Also, I am aware that I am returning the absolute value of the number; I did this because I couldn't find another way to return the number itself. I need to find a way to return the number if the lxt is a number. And I had it recurse two times at the bottom, because this is one way that it loops on itself infinitely until it computes a single number. NOTE: this function doesn't implement a flatten function anymore nor does it use anything from it.
Imagine you have your function already. What does it get? What must it produce?
Given an atom, what does it return? Given a simple list of atoms, what should it return?
(defun condense (x)
(typecase x
(number
; then what?
(condense-number x))
(list
; then what?
(if (all-atoms x)
(condense-list-of-atoms x) ; how to do that?
(process-further-somehow
(condense-lists-inside x))))
; what other clauses, if any, must be here?
))
What must condense-lists-inside do? According to your description, it is to condense the nested lists inside - each into a number, and leave the atoms intact. So it will leave a list of numbers. To process that further somehow, we already "have" a function, condense-list-of-atoms, right?
Now, how to implement condense-lists-inside? That's easy,
(defun condense-lists-inside (xs)
(mapcar #'dowhat xs))
Do what? Why, condense, of course! Remember, we imagine we have it already. As long as it gets what it's meant to get, it shall produce what it is designed to produce. Namely, given an atom or a list (with possibly nested lists inside), it will produce a number.
So now, fill in the blanks, and simplify. In particular, see whether you really need the all-atoms check.
edit: actually, using typecase was an unfortunate choice, as it treats NIL as LIST. We need to treat NIL differently, to return a "zero value" instead. So it's better to use the usual (cond ((null x) ...) ((numberp x) ...) ((listp x) ...) ... ) construct.
About your new code: you've erred: to process the list of atoms returned after (mapcar #'condense x), we have a function calculate that does that, no need to go so far back as to condense itself. When you substitute calculate there, it will become evident that the check for all-atoms is not needed at all; it was only a pedagogical device, to ease the development of the code. :) It is OK to make superfluous choices when we develop, if we then simplify them away, after we've achieved the goal of correctness!
But, removing the all-atoms check will break your requirement #2. The calculation will then proceed as follows
(CONDENSE '(2 3 4 (3 1 1 1) (2 3 (1 2)) 5))
==
(calculate (mapcar #'condense '(2 3 4 (3 1 1 1) (2 3 (1 2)) 5)))
==
(calculate (list 2 3 4 (condense '(3 1 1 1)) (condense '(2 3 (1 2))) 5))
==
(calculate (list 2 3 4 (calculate '(3 1 1 1))
(calculate (list 2 3 (calculate '(1 2)))) 5))
==
(calculate (list 2 3 4 6 (calculate '(2 3 3)) 5))
==
(calculate (list 2 3 4 6 8 5))
==
28
I.e. it'll proceed in left-to-right fashion instead of the from the deepest-nested level out. Imagining the nested list as a tree (which it is), this would "munch" on the tree from its deepest left corner up and to the right; the code with all-atoms check would proceed strictly by the levels up.
So the final simplified code is:
(defun condense (x)
(if (listp x)
(reduce #'+ (mapcar #'condense x))
(abs x)))
a remark: Looking at that last illustration of reduction sequence, a clear picture emerges - of replacing each node in the argument tree with a calculate application. That is a clear case of folding, just such that is done over a tree instead of a plain list, as reduce is.
This can be directly coded with what's known as "car-cdr recursion", replacing each cons cell with an application of a combining function f on two results of recursive calls into car and cdr components of the cell:
(defun condense (x) (reduce-tree x #'+ 0))
(defun reduce-tree (x f z)
(labels ((g (x)
(cond
((consp x) (funcall f (g (car x)) (g (cdr x))))
((numberp x) x)
((null x) z)
(T (error "not a number")))))
(g x)))
As you can see this version is highly recursive, which is not that good.
Is this homework? If so, please mark it as such. Some hints:
are you sure the 'condensation' of the empty list in nil? (maybe you should return a number?)
are you sure the condensation of one element is a list? (maybe you should return a number?)
are you sure the condensation of the last case is a list? (shouldn't you return a number)?
In short, how is your condense ever going to return 28 if all your returned values are lists?
Task: With nested lists, flatten the innermost lists first and work from there
sum
flatten lists
For sum use REDUCE, not APPLY.
For flatten lists you need a loop. Lisp already provides specialized mapping functions.
Slightly more advanced: both the sum and the flatten can be done by a call to REDUCE.
You can also write down the recursion without using a higher-order function like APPLY, REDUCE, ... That's a bit more work.
Here's added the explanation of the errors you were having, actually you were close to solving your problem, just a bit more effort and you would get it right.
; compiling (DEFUN CONDENSE ...)
; file: /tmp/file8dCll3
; in: DEFUN CONDENSE
; (T (APPEND (FLATTEN (APPLY #'+ (CDR LST)))))
;
; caught WARNING:
; The function T is undefined, and its name is reserved
; by ANSI CL so that even
; if it were defined later, the code doing so would not be portable.
;
; compilation unit finished
; Undefined function:
; T
; caught 1 WARNING condition
;STYLE-WARNING: redefining CONDENSE in DEFUN
(defun condense (lst)
(cond
((null lst) nil)
((atom lst) (list lst)))
;.------- this is a function call, not a condition
;| (you closed the parens too early)
(t (append (flatten (apply #'+ (cdr lst))))))
;; Argument Y is not a NUMBER: (3 1 1 1)
;; [Condition of type SIMPLE-TYPE-ERROR]
(defun condense (lst)
(cond
((null lst) nil)
((atom lst) (list lst)); .-- not a number!
;You are calling #'+ -------. |
;on something, which | '(3 4 (3 1 1 1) (2 3 (1 2)) 5)
; is not a number. | |
(t (append (flatten (apply #'+ (cdr lst)))))))
;; You probably wanted to flatten first, and then sum
(defun condense (lst)
(cond
((null lst) nil); .--- returns just the
((atom lst) (list lst)); / atom 28, you can
; .---------------------/ just remove it.
(t (append (apply #'+ (flatten lst))))))
;; Now, you are lucky that append would just return the
;; atom if it's not a list
(defun condense (lst)
(cond
((null lst) nil)
((atom lst) (list lst))
(t (apply #'+ (flatten lst)))))
;; Again, you are lucky because (apply can take enough arguments
;; while your list is reasonably small - this will not always be
;; the case, that is why you need to use something more durable,
;; for example, reduce.
(defun condense (lst)
(cond
((null lst) nil)
((atom lst) (list lst))
(t (reduce #'+ (flatten lst)))))
;; Whoa!
(condense '(2 3 4 (3 1 1 1) (2 3 (1 2)) 5))
This is all given the flatten function actually works.
If your lisp already implements flatten and reduce functions (such as Clojure, which I will use here), you can just do something like:
user=> (defn condense [l] (reduce + 0 (flatten l)))
#'user/condense
user=> (condense [1 [2 [[3 4] 5]]])
15
user=>
Failing that, a naive implementation of those functions might be:
(defn flatten [l]
(cond (nil? l) l
(coll? l) (let [[h & t] l]
(concat (flatten h) (flatten t)))
true [l]))
and:
(defn reduce [op initial-value [h & t]]
(if (nil? t)
(op initial-value h)
(op initial-value (reduce op h t))))
But make sure to check the semantics of the particular Lisp you are using. Also, if you are implementing reduce and flatten, you may want to make them tail recursive which I didn't so as to maintain clarity.
In Common Lisp you would do something like:
(defun flatten (l)
(cond ((null l) l)
((atom l) (list l))
(t (append (flatten (car l))
(flatten (cdr l))))))
and use apply instead of reduce:
(defun condense (l) (apply #'+ (flatten l)))

LISP disposing of pesky NILs

I have the following filter function that filters out a list, x, that doesn't satisfy the function f.
For example, I call (filter 'evenp '(0 1 2 3)) and get back (NIL 1 NIL 3). But this is exactly my problem. How do I make it so that I just get back (1 3) ?
(defun filter (f x)
(setq h (mapcar #'(lambda (x1)
(funcall f x1))
x))
(mapcar #'(lambda (a b)
(cond ((null a) b)))
h x))
i.e. the problem is right here: (lambda (a b) (cond ( (null a) b) ) ) In my cond I don't have a t , or else statement, so shouldn't it just stop right there and not return nil ? How do I make it "return" nothing, not even nil, if the (cond ( (null a) b) ) isn't satisfied?
Much appreciated. :)
Based on this question it would be:
(remove-if #'evenp '(0 1 2 3))
Ignoring the other questions raised by this post, I'll say that mapcar will always return something for each thing it's mapping over, so you can't use another mapcar to clean up the NILs there. This is what mapcar does -- it walks over the item (or items, if mapping on multiple lists, as your second attempted mapcar does) and collects the result of calling some function on those arguments.
Instead, in this situation, if you had to use mapcar for some reason, and didn't want the NILs, you could use the remove function, i.e. (remove nil (mapcar ...))
Since #stark's answer is posted above, I'll say that the remove-if function there is essentially what you're trying to implement here. (That's where the question of whether or not this is for homework becomes most relevant.)
To answer the more general question of how to splice an arbitrary number of items (including none at all) into the result, mapcan (which is semantically mapcar + append) is useful for that:
(defun filter (f xs)
(mapcan (lambda (x)
(if (funcall f x)
(list x)
nil))
xs))
mapcan is also useful when you want to map an item to multiple results:
(defun multi-numbers (xs)
(mapcan (lambda (x) (list x (+ x x) (* x x))) xs))
(multi-numbers (list 1 2 3))
;=> (1 2 1 2 4 4 3 6 9)