Something like find in lisp - lisp

is there a function like find in lisp that returns true instead of the element we're trying to find?
example:
I want it to do
(find 'x '(a c x)) = t
not
(find 'x '(a c x)) = x
Also, the reason I am asking is because I am trying to reach the deepest element in a list. My plan was to flatten the list every time i recursively called it.
I would then stop the recursive call when
(mapcar 'atom list)
would tell me every atom in there is true.
Do you believe this is a good approach to this problem?

There's no such function, but it can't be easier to write one:
(defun find-t (&rest args)
(when (apply #'find args)
t))
Also instead of (mapcar 'atom list) you can use (every #`(eql t %) list), i.e. check that every item in list is exactly t. (Here #`() is syntactic sugar for one-argument lambdas, that I use.)
But overall it's unclear, what you're trying to achieve with all this. Can you elaborate on what you're trying to do?

Related

Creating a lisp file that reads numbers from the keyboard until 0 is read. Display the minimim value

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)
...)

How to express lisp (lambda (pair) (apply #'f pair)) more simply?

Say I've got the following function:
(defun f (v1 v2) ...)
I've got the following code that I'd like to simplify:
(lambda (pair) (apply #'f pair))
The goal here is to create a function that takes a list of two values and calls f with the contents of that list. While this works, it seems a bit verbose. Is there a simpler way to express this?
Maybe:
(lambda(p)(apply #'f p)) ;; 24 bytes
More seriously, Alexandria provides a curry function:
(let ((fun (curry #'apply #'f)))
(funcall fun '(a b)))
Edit: Also, I agree with the sentiment expressed by #Paulo Madeira that your original version is far from being verbose. I would let it as it is, thought, because I think it is in fact easier to debug than using an assert.
(lambda (args) (apply #'f args))
... means "take a list of arguments and apply function F with those arguments". The meaning is straightforward and the function does not make assumptions about what F accepts as arguments. If F is later changed, your closure will still work reliably.
Edit: We don't know what is the context of your code and without more information, your closure looks fishy. If you could describe why you need to pass arguments, we might realize that this approach is not necessarily the most appropriate (or agree that this is in fact a sensible thing to do).

SICP: Can or be defined in lisp as a syntactic transformation without gensym?

I am trying to solve the last part of question 4.4 of the Structure and Interpretation of computer programming; the task is to implement or as a syntactic transformation. Only elementary syntactic forms are defined; quote, if, begin, cond, define, apply and lambda.
(or a b ... c) is equal to the first true value or false if no value is true.
The way I want to approach it is to transform for example (or a b c) into
(if a a (if b b (if c c false)))
the problem with this is that a, b, and c would be evaluated twice, which could give incorrect results if any of them had side-effects. So I want something like a let
(let ((syma a))
(if syma syma (let ((symb b))
(if symb symb (let ((symc c))
(if (symc symc false)) )) )) )
and this in turn could be implemented via lambda as in Exercise 4.6. The problem now is determining symbols syma, symb and symc; if for example the expression b contains a reference to the variable syma, then the let will destroy the binding. Thus we must have that syma is a symbol not in b or c.
Now we hit a snag; the only way I can see out of this hole is to have symbols that cannot have been in any expression passed to eval. (This includes symbols that might have been passed in by other syntactic transformations).
However because I don't have direct access to the environment at the expression I'm not sure if there is any reasonable way of producing such symbols; I think Common Lisp has the function gensym for this purpose (which would mean sticking state in the metacircular interpreter, endangering any concurrent use).
Am I missing something? Is there a way to implement or without using gensym? I know that Scheme has it's own hygenic macro system, but I haven't grokked how it works and I'm not sure whether it's got a gensym underneath.
I think what you might want to do here is to transform to a syntactic expansion where the evaluation of the various forms aren't nested. You could do this, e.g., by wrapping each form as a lambda function and then the approach that you're using is fine. E.g., you can do turn something like
(or a b c)
into
(let ((l1 (lambda () a))
(l2 (lambda () b))
(l3 (lambda () c)))
(let ((v1 (l1)))
(if v1 v1
(let ((v2 (l2)))
(if v2 v2
(let ((v3 (l3)))
(if v3 v3
false)))))))
(Actually, the evaluation of the lambda function calls are still nested in the ifs and lets, but the definition of the lambda functions are in a location such that calling them in the nested ifs and lets doesn't cause any difficulty with captured bindings.) This doesn't address the issue of how you get the variables l1–l3 and v1–v3, but that doesn't matter so much, none of them are in scope for the bodies of the lambda functions, so you don't need to worry about whether they appear in the body or not. In fact, you can use the same variable for all the results:
(let ((l1 (lambda () a))
(l2 (lambda () b))
(l3 (lambda () c)))
(let ((v (l1)))
(if v v
(let ((v (l2)))
(if v v
(let ((v (l3)))
(if v v
false)))))))
At this point, you're really just doing loop unrolling of a more general form like:
(define (functional-or . functions)
(if (null? functions)
false
(let ((v ((first functions))))
(if v v
(functional-or (rest functions))))))
and the expansion of (or a b c) is simply
(functional-or (lambda () a) (lambda () b) (lambda () c))
This approach is also used in an answer to Why (apply and '(1 2 3)) doesn't work while (and 1 2 3) works in R5RS?. And none of this required any GENSYMing!
In SICP you are given two ways of implementing or. One that handles them as special forms which is trivial and one as derived expressions. I'm unsure if they actually thought you would see this as a problem, but you can do it by implementing gensym or altering variable? and how you make derived variables like this:
;; a unique tag to identify special variables
(define id (vector 'id))
;; a way to make such variable
(define (make-var x)
(list id x))
;; redefine variable? to handle macro-variables
(define (variable? exp)
(or (symbol? exp)
(tagged-list? exp id)))
;; makes combinations so that you don't evaluate
;; every part twice in case of side effects (set!)
(define (or->combination terms)
(if (null? terms)
'false
(let ((tmp (make-var 'tmp)))
(list (make-lambda (list tmp)
(list (make-if tmp
tmp
(or->combination (cdr terms)))))
(car terms)))))
;; My original version
;; This might not be good since it uses backquotes not introduced
;; until chapter 5 and uses features from exercise 4.6
;; Though, might be easier to read for some so I'll leave it.
(define (or->combination terms)
(if (null? terms)
'false
(let ((tmp (make-var 'tmp)))
`(let ((,tmp ,(car terms)))
(if ,tmp
,tmp
,(or->combination (cdr terms)))))))
How it works is that make-var creates a new list every time it is called, even with the same argument. Since it has id as it's first element variable? will identify it as a variable. Since it's a list it will only match in variable lookup with eq? if it is the same list, so several nested or->combination tmp-vars will all be seen as different by lookup-variable-value since (eq? (list) (list)) => #f and special variables being lists they will never shadow any symbol in code.
This is influenced by eiod, by Al Petrofsky, which implements syntax-rules in a similar manner. Unless you look at others implementations as spoilers you should give it a read.

CLISP - Reversing a simple list

I have to reverse the elements of a simple (single-dimension) list. I know there's a built-in reverse function but I can't use it for this.
Here's my attempt:
(defun LISTREVERSE (LISTR)
(cond
((< (length LISTR) 2) LISTR) ; listr is 1 atom or smaller
(t (cons (LISTREVERSE (cdr LISTR)) (car LISTR))) ; move first to the end
)
)
Output pretty close, but is wrong.
[88]> (LISTREVERSE '(0 1 2 3))
((((3) . 2) . 1) . 0)
So I tried to use append instead of cons:
(t (append (LISTREVERSE (cdr LISTR)) (car LISTR)))
But got this error:
*** - APPEND: A proper list must not end with 2
Any help?
I can give you a couple of pointers, because this looks like homework:
The base case of the recursion is when the list is empty (null), and not when there are less than two elements in the list
Consider defining a helper function with an extra parameter, an "accumulator" initialized in the empty list. For each element in the original list, cons it at the head of the accumulator. When the input list is empty, return the accumulator
As an aside note, the above solution is tail-recursive.
As a follow-up to Óscar López (and fighting the temptation to just write a different solution down):
Using both append and length makes the posted solution just about the least efficient way of reversing a list. Check out the documentation on cons and null for some better ideas on how to implement this.
Please, please indent properly.
Tail recursion really is both more efficient and reasonably simple in this case. Try it if you haven't already. labels is the form you want to use to define local recursive functions.
It may be worth your while to flip through The Little Schemer. It'll give you a better feel for recursion in general.
It's ok what you did. You only missed the composition of the result list.
Think about it: You have to append the 1-element list of the CAR to the end of the list of the reversed CDR:
(defun LISTREVERSE (LISTR)
(cons
((< (length LISTR) 2) LISTR) ; listr is 1 atom or smaller
(t (append (LISTREVERSE (cdr LISTR)) (list (car LISTR))))))
(defun listreverse (list)
(let (result)
(dolist (item list result)
(push item result))))
Don't use recursion in Common Lisp when there is a simple iterative way to reach the same goal. Common Lisp does not make any guarantees about tail recursion, and your tail recursive function invocation may not be optimized to a jump at the discretion of the compiler.
push prepends the item to the result
dolist has an optional third argument which is the value returned. It is evaluated when the loop is exited.

Macro and array crossing

I am having a problem with a lisp macro. I would like to create a macro
which generate a switch case according to an array.
Here is the code to generate the switch-case:
(defun split-elem(val)
`(,(car val) ',(cdr val)))
(defmacro generate-switch-case (var opts)
`(case ,var
,(mapcar #'split-elem opts)))
I can use it with a code like this:
(generate-switch-case onevar ((a . A) (b . B)))
But when I try to do something like this:
(defparameter *operators* '((+ . OPERATOR-PLUS)
(- . OPERATOR-MINUS)
(/ . OPERATOR-DIVIDE)
(= . OPERATOR-EQUAL)
(* . OPERATOR-MULT)))
(defmacro tokenize (data ops)
(let ((sym (string->list data)))
(mapcan (lambda (x) (generate-switch-case x ops)) sym)))
(tokenize data *operators*)
I got this error: *** - MAPCAR: A proper list must not end with OPS, but I don't understand why.
When I print the type of ops I get SYMBOL I was expecting CONS, is it related?
Also, for my function tokenize, how many times is the lambda evaluated (or the macro expanded)?
Thanks.
This makes no sense. You trying to use macros, where functions are sufficient.
What you want is similar to this:
(defun tokenize (data ops)
(mapcar (lambda (d)
(cdr (assoc d ops)))
(string->list data)))
CASE is a macro that expects a bunch of fixed clauses. It does not take clauses that are computed at runtime. If list data should drive computation, then use functions like ASSOC.
GENERATE-SWITCH-CASE is also an odd name, since the macro IS a switch case.
GENERATE-SWITCH-CASE also does expect a list as a second argument. But in TOKENIZE you call it with a symbol OPS. Remember, macros compute with Lisp source code.
Next, there are also no ARRAYs involved. Lisp has arrays, but in your example is none.
Typical advice:
if you want to write a MACRO, think again. Write it as a function.
if you still want to write a macro, Go to 1.