or as procedure in scheme - functional-programming

I want to apply or to every element of list, example:
(apply or '(#t #t #f)) expected result #t, but I'm getting error:
'#' to 'apply' has wrong type (kawa.lang.Macro) (expected: procedure, sequence, or other operator)
As I understand or is not a procedure.
Is there any procedure that can be used instead of or?

The easiest way to do this is with exists*. Whenever you would use (apply or some-list), you can use (exists values some-list). Or if you like, you can define a function that uses exists to do that:
#!r6rs
(import (rnrs base)
(rnrs lists))
(define (or* . lst)
(exists values lst))
values is the identity function, so (values x) is just x.
exists is a higher-order function defined so that (exists f (list x ...)) is equivalent to (or (f x) ...).
For example (exists values (list #t #t #f)) is equivalent to (or (values #t) (values #t) (values #f)), which is the same as (or #t #t #f).
Trying it out:
> (apply or* '(#t #t #f))
#t
> (apply or* '(#f #f #f))
#f
> (or* #t #t #f)
#t
> (or*)
#f
*exists is sometimes known as ormap or any

In SRFI-1 List Library you have every and any which basically is and and or for a procedure over a list.
#!r6rs
(import (rnrs base)
(only (srfi :1) every any)
(define num1-10 '(1 2 3 4 5 6 7 8 9 10))
(define odd1-9 '(1 3 5 7 9))
(every odd? num1-10) ; ==> #f
(any odd? num1-10) ; ==> #t
(every odd? odd1-9) ; ==> #t
For a list of booleans the procedure only need to return the argument. values returns it's argument and serve as identity:
(define booleans '(#f #t))
(every values booleans) ; ==> #f
(any values booleans) ; ==> #t
SRFI-1 is a safe choice as it is the list library of the upcoming R7RS Red edition. In many R5RS and R6RS implementations SRFI-1 is included and you can easily add it from the SRFI reference implementation if it isn't. In DrRacket's default language DrRacket, that has ormap and andmap, you can opt to use SRFI-1 instead by importing them with (require srfi/1).

You could define your own procedure that uses or
(define (orp . ls)
(if (null? ls) #f
(if (< (length ls) 2) (car ls) (or (car ls) (orp (cdr ls))))))
And use it:
(apply orp '(#t #f #t))

The main point is that or (and if, cond, and ....) operator has lazy evaluation semantics. Hence (or #t (/ 1 0)) does not make a division by zero. Because of that or cannot be an ordinary function.
You might code a lambda to force the eager evaluation, e.g. define your eager-or variadic function, and apply that.

Related

Common lisp recursive macro in matrix addition

I have to write a recursive macro for list addition in Common Lisp (homework). What I have so far is :
(defmacro matrix-add-row (r1 r2 sum_row)
(if (not (and r1 r2)) `sum_row
(progn
`(matrix-add-row (cdr r1) (cdr r2) (cons sum_row (+ (car r1) (car r2))))
(reverse sum_row)
)
)
)
I call this function with
(matrix-add-row `(1 2) `(3 4) ())
and as an output I get unvaluated code instead of numbers (which leads going to infinite loop).
How to put , ` properly (or call the macro properly)?
Firstly, to me this seems a rather bizarre thing to do with a macro. I assume the point is that you use the macro to transform (matrix-add-row '(1 2) '(3 4)) to an explicit list of sums like (list (+ 1 3) (+ 2 4)).
Also, what you have written has several problems which look like you don't quite understand how the backtick works. So I think the easiest way to help is to solve an example for you.
Since this is homework, I'm going to solve a different (but similar) question. You should be able to take the answer and use it for your example. Suppose I want to solve the following:
Write a macro, diffs, which computes all differences of pairs of successive elements in a list. For example,
(diffs '(1 2 3)) should expand to (list (- 2 1) (- 3 2)), which will then evaluate to (1 1).
Note that my macro won't do the actual subtraction, so I can use it even if I don't know some of the numbers until runtime. (The reason I think this sort of question is a bit weird is that it does need to know the length of the list at compile time).
My solution is going to be used as a macro with one argument but if I want to use recursion I'll need to pass in an accumulator too, which I can start with nil. So I write something like this:
(defmacro diffs (lst &optional accumulator)
...)
Now what do I do with lst? If lst is nil, I want to bottom out and just return the accumulator, with a call to list at the front, which will be code to make my list. Something like this:
(defmacro diffs (lst &optional accumulator)
(cond
((null lst)
;; You could write `(list ,#accumulator) instead, but that seems
;; unnecessarily obfuscated.
(cons 'list accumulator))
(t
(error "Aargh. Unhandled"))))
Let's try it!
CL-USER> (diffs nil)
NIL
Not hugely exciting, but it looks plausible. Now use macroexpand, which just does the expansion without the evaluation:
CL-USER> (macroexpand '(diffs nil))
(LIST)
T
And what if we'd already got some stuff from a recursion?
CL-USER> (macroexpand '(diffs nil ((- a b) (- b c))))
(LIST (- A B) (- B C))
T
Looks good! Now we need to deal with the case when there's an actual list there. The test you want is consp and (for my example) it only makes sense when there's at least two elements.
(defmacro diffs (lst &optional accumulator)
(cond
;; A list of at least two elements
((and (consp lst) (consp (cdr lst)))
(list 'diffs (cdr lst)
(cons (list '- (cadr lst) (car lst)) accumulator)))
;; A list with at most one element
((listp lst)
(cons 'list accumulator))
(t
(error "Aargh. Unhandled"))))
This seems almost to work:
CL-USER> (macroexpand '(diffs (3 4 5)))
(LIST (- 5 4) (- 4 3))
T
but for two problems:
The list comes out backwards
The code is a bit horrible when we actually construct the recursive expansion
Let's fix the second part first by using the backtick operator:
(defmacro diffs (lst &optional accumulator)
(cond
;; A list of at least two elements
((and (consp lst) (consp (cdr lst)))
`(diffs ,(cdr lst)
,(cons `(- ,(cadr lst) ,(car lst)) accumulator)))
;; A list with at most one element
((listp lst)
(cons 'list accumulator))
(t
(error "Aargh. Unhandled"))))
Hmm, it's not actually much shorter, but I think it's clearer.
For the second part, we could proceed by adding each item to the end of the accumulator rather than the front, but that's not particularly quick in Lisp because lists are singly linked. Better is to construct the accumulator backwards and then reverse it at the end:
(defmacro diffs (lst &optional accumulator)
(cond
;; A list of at least two elements
((and (consp lst) (consp (cdr lst)))
`(diffs ,(cdr lst)
,(cons `(- ,(cadr lst) ,(car lst)) accumulator)))
;; A list with at most one element
((listp lst)
(cons 'list (reverse accumulator)))
(t
(error "Aargh. Unhandled"))))
Now we get:
CL-USER> (macroexpand '(diffs (3 4 5)))
(LIST (- 4 3) (- 5 4))
T
Much better!
Two last things. Firstly, I still have an error clause in my macro. Can you see how to trigger it? Can you think of a better behaviour than just outputting an error? (Your macro is going to have to deal with the same problem)
Secondly, for debugging recursive macros like this, I recommend using macroexpand-1 which just unfolds one level at once. For example:
CL-USER> (macroexpand-1 '(diffs (3 4 5)))
(DIFFS (4 5) ((- 4 3)))
T
CL-USER> (macroexpand-1 *)
(DIFFS (5) ((- 5 4) (- 4 3)))
T
CL-USER> (macroexpand-1 *)
(LIST (- 4 3) (- 5 4))
T
There are two problems with your logic. First you are calling reverse on each iteration instead of at the end of the iteration. Then you are accumulating the new values, through cons, in the cdr of the cons cell as opposed to the car.
Also I don't see why this have to be a macro so using a function.
(defun matrix-add-row (r1 r2 sum-row)
(if (or (endp r1) (endp r2))
(reverse sum-row)
(matrix-add-row (cdr r1)
(cdr r2)
(cons (+ (car r1) (car r2))
sum-row))))
(matrix-add-row '(1 2) '(3 4) ())
;; => (4 6)

Input a value to be used instead of (FDEFINITION 'COMP

clisp:
(defun sorted (seq comp)
(or
(< (length seq) 2)
(and (comp (car seq) (car seq))
(sorted (cdr seq) comp)
)
))
on ubuntu, run clisp :
(sorted '(1 3 4) #'<)
ERROR:USE-VALUE :R1 Input a value to be used instead of (FDEFINITION 'COMP).
how fix it?
There are quite a few things amiss in your code.
First, in Common Lisp, data and functions live in separate namespaces. For this reason, you cannot use (comp x y) to call the function referred to by the variable comp. You have to use the funcall function.
Second, you are comparing (car seq) with (car seq) - that is, with itself. You probably meant to say (car (cdr seq)), which refers to the second element in the list.
After these changes, the code works correctly:
(defun sorted (seq comp)
(or (< (length seq) 2)
(and (funcall comp (car seq) (car (cdr seq)))
(sorted (cdr seq) comp))))
* (sorted '(1 3 4) #'<)
T
* (sorted '(1 4 3) #'<)
NIL
Evaluating (length seq) on every iteration of your function is not efficient; to get the list's length, the system must go through the entire list. Effectively, your code will spend quadratic time doing a linear operation. It would be better to replace that with a simple end check.
Also, I would use the functions first and second instead of (car seq) and (car (cdr seq)), and rest instead of cdr. It is better to explicitly state in your code what you mean with it.
With these changes, the final code looks like this:
(defun sorted (seq comp)
(or (endp (rest seq))
(and (funcall comp (first seq) (second seq))
(sorted (rest seq) comp))))

Application not a procedure (Scheme map procedure)

I am attempting to write my own simplified map procedure in R5RS. In short, it takes a procedure and two lists, and returns a list with the results of the procedure called on every pair of objects in the two argument lists, until either is empty.
This works fine for arithmetic operators, such as:
(map2-rec + '(1 2 3) '(1 2 3 4))
However, when I attempt to pass an anonymous lambda function (the return value of my both? procedure) which returns either #t or #f, this does not work.
(define (map2-rec proc items1 items2)
(if (or (null? items1) (null? items2))
'()
(cons (proc (car items1) (car items2))
(map2-rec proc (cdr items1) (cdr items2)))))
(define (both? proc)
(lambda (item1 item2)
((if (and (proc item1) (proc item2))
#t
#f))))
The specific error I am receiving in DrRacket is:
application: not a procedure;
expected a procedure that can be
applied to arguments
given: #t
arguments...: [none]
If someone could tell me how I can correct this error, I'd be very happy. I cannot understand why this code fails myself.
There's an extra (and erroneous) pair of parentheses in both?, surrounding the if expression. This should fix it:
(define (both? proc)
(lambda (item1 item2)
(if (and (proc item1) (proc item2))
#t
#f)))
Now your procedure works as expected:
(map2-rec + '(1 2 3) '(1 2 3 4))
=> '(2 4 6)
(map2-rec (both? even?) '(1 2 3) '(1 2 3 4))
=> '(#f #t #f)

What is wrong with my code in determining palindrome in scheme?

I am trying to detect the palindrome lists in scheme. Here is my code:
;- Input : Takes only one parameter named inSeq
;- Output : It returns the reverse of inSeq if inSeq is a sequence.
; Otherwise it produces an error.
;- Examples :
; (reverse-sequence '(a b c)) --> evaluates to (c b a)
; (reverse-sequence '()) -------> evaluates to ()
(define reverse-sequence
(lambda (inSeq)
(if (sequence? inSeq)
(if (null? inSeq)
inSeq
(append (reverse-sequence (cdr inSeq))
(list (car inSeq)))))))
;- Input : Takes only one parameter named inSeq
;- Output : It returns true if inSeq is a sequence and it is a palindrome.
; It returns false if inSeq is a sequence but not a plaindrome.
; Otherwise it gives an error.
;- Examples :
; (palindrome? '(a b a)) --> evaluates to true
; (palindrome? '()) -------> evaluates to true
; (palindrome? '(a 1 a)) --> produces an error
(define palindrome
(lambda (inSeq)
(if (sequence? inSeq)
(if (equal? reverse-sequence(inSeq) inSeq )
#t
#f))))
When i try the input '(a b a) i get the following error:
The object (a b a) is not applicable
Can anyone help me with this error? Thanks
You wrote
(equal? reverse-sequence(inSeq) inSeq )
which tries to call (inSeq) as a function of no arguments. It should read:
(equal? (reverse-sequence inSeq) inSeq )
Remember, in Scheme the correct way to invoke procedure f on argument x is: (f x). That explains why this snippet doesn't work:
reverse-sequence(inSeq)
It should have been:
(reverse-sequence inSeq)
Be aware that you'll run into trouble if the argument received isn't a sequence, you'll get a void value and you won't get a correct answer. Also, you could have used the built-in reverse procedure, but I guess you want to implement it yourself - with that in mind, it'd be a better idea to reverse the list accumulating the result in a parameter (tail recursion), so you don't have to append the results (which is expensive), just cons the results (which is very cheap). This is what I mean:
(define (reverse-sequence inSeq)
(if (not (sequence? inSeq))
'() ; can't reverse if it's not a sequence
(let loop ((inSeq inSeq)
(reversed '()))
(if (null? inSeq)
reversed
(loop (cdr inSeq) (cons (car inSeq) reversed))))))
(define (palindrome inSeq)
(if (not (sequence? inSeq))
#f
(equal? inSeq (reverse-sequence inSeq))))

Basic LISP recursion, enumerate values greater than 3

I need a recursive LISP function that enumerates the number of elements in any list of numbers > 3. I'm not allowed to use lets, loops or whiles and can only use basic CAR, CDR, SETQ, COND, CONS, APPEND, PROGN, LIST...
This is my attempt at the function:
(defun foo (lst)
(COND ((null lst) lst)
(T (IF (> (CAR lst) 3)
(1+ (foo (CDR lst)))
(foo (CDR lst)) ) ) ) )
The function call:
(foo '(0 1 2 3 4 5 6))
Your code is pretty close to correct, just a small mistake in the base case:
For the empty list you return the empty list. So if you have the list (6), you add 6 to foo of the empty list, which is the empty list. That does not work because you can't add a number to a list.
You can easily fix it by making foo return 0 instead of lst when lst is empty.
As a style note: Mixing cond and if like this, seems a bit redundant. I would write it like this, using only cond instead:
(defun foo (lst)
(cond
((null lst)
0)
((> (car lst) 3)
(1+ (foo (cdr lst))))
(T
(foo (cdr lst)))))
Some stylistic points:
There's no need to put some Lisp built-ins in uppercase. It's not 1958 anymore!
But if you are going to put built-ins in uppercase, why not DEFUN and NULL?
You have an if inside the last branch of your cond. This is redundant. Since the purpose of cond is testing conditions, why not use it?
There's no need to space out your closing parentheses like that. No-one counts parentheses these days, we have parenthesis-matching editors.
Lisp has separate namespaces for functions and values, so you don't have to call your argument lst to avoid conflicting with the built-in function list.
If you were programming this for real, of course you'd use count-if:
(count-if #'(lambda (x) (> x 3)) '(0 1 2 3 4 5 6))
==> 3
One save you can have on duplication of the recursive call:
(defun foo (l)
(if (null l) 0 ; if list is empty, return 0
(+ (if (> (car l) 3) 1 0) ; else +1 if condition is satisfactory
(foo (cdr l))))) ; plus the result from the rest

Resources