Using foldr with the or logical operator in Scheme - scheme

I'm attempting to run the following bit of code in Scheme using Dr.Racket
(foldr or #f '(#f #f #f #t))
Now, I expected this to work because
(foldr + 0 '(1 2 3))
Worked just fine, returning 6.
But when I try to run it with the logical or I get "or: bad syntax in: or"
What am I doing wrong? Also, is there an alternative method to calculate the or of a list without using folds, perhaps?

In the specific case of folding or, you should use ormap. You can pass in identity (or even values ) as the function to use with ormap.
> (ormap identity '(#f #f #f #f #t))
#t
> (ormap identity '(#f #f #f #f #f))
#f
In general, you can only fold functions, not macros, and or is a macro because it has short-circuiting behaviour.

My Scheme is fairly weak, but if I'm not mistaken, or is a macro, not a function, so you can't pass it around in higher-order calls. You can wrap it in a lambda, however, leading to the less-pleasant looking:
(foldr (lambda (a b) (or a b)) #f '(#f #f #f #t)) => #t
If you know the number of arguments in advance, it's worth noting that or takes zero or more arguments:
(or) => #f
(or #f) => #f
(or #t) => #t
(or #t #f) => #t
(or #f #f #f #f #f) => #f
Otherwise, you'll need a more experienced Schemer than me to provide the answer.

Related

Evaluating a list of booleans?

I've got a list that I want to evaluate the truth of, but (unless I'm missing some built-in aspect of Racket/Scheme) I need to convert it to a Boolean to do that.
For example, I have
'(#t and #f)
I need
(function '(#t and #f)) ;in order to return...
>#f
I've tried (eval '(and #t #f) but get this error message:
and: unbound identifier;
also, no #%app syntax transformer is bound in: and
I have code in place that converts '(#t and #f) into '(and #t #f) so that shouldn't be an issue, as far as I'm aware.
(define (Evaluate-WFF lst)
(match lst
((list a b c)
(list (reorg b)
(reorg a)
(reorg c)))
(_ lst)))
When I try to eval from this, I get the error message stated earlier.
Depending on what language you're using you might need to provide a namespace, as per the docs. In #lang racket this is how to do it:
(define-namespace-anchor a)
(define ns (namespace-anchor->namespace a))
(eval '(and #t #f) ns)
=> #f

All: A Function Returning True if and only if All Elements of a List are True

I am looking for a built-in function in Racket that will return True iff all the items in a list are true.
I tried:
(define (all lst)
(when
(equal? lst '())
#t)
(if (not (car lst))
#f
(all (cdr lst))))
Giving error:
car: contract violation
expected: pair?
given: '()
A couple of testcases:
(all '(#t #f #t)) ; #f
(all '(#t #t #t)) ; #t
Could you please either fix it or point me to the built-in function?
(I googled, but got no meaningful result)
You've already accepted another answer that explains a nice way to do this, but I think it's worth pointing out what was wrong in your attempt, because it was actually very close. The problem is that true from the when block is completely ignored. It doesn't cause the function to return. So even when you have the empty list, you evaluate the when, and then keep on going into the other part where you call car and cdr with the same empty list:
(define (all lst)
(when ; The whole (when ...) expression
(equal? lst '()) ; is evaluated, and then its result
#t) ; is ignored.
(if (not (car lst))
#f
(all (cdr lst))))
A very quick solution would be to change it to:
(define (all lst)
(if (equal? lst '())
#t
(if (not (car lst))
#f
(all (cdr lst)))))
At that point, you can simplify a little bit by using boolean operators rather than returning true and false explicitly, and clean up a little bit by using empty?, as noted in the other answer:
(define (all lst)
(or (empty? lst)
(and (car lst)
(all (cdr lst)))))
You were actually very close at the start.
If you're looking for a builtin solution, you'll probably want to take a look at andmap, which applies a predicate over an entire list and ands the results together.
You could use this to implement all very simply.
(define (all lst)
(andmap identity lst))
By using identity from racket/function, all will just use the values in the list as-is. Instead of using identity explicitly, you could also use values, which is just the identity function on single values, so it's a somewhat common idiom in Racket.
There are two kinds of lists: empty ones and pairs.
Therefore we have the following structure:
(define (all xs)
(cond
[(empty? xs) ...]
[(pair? xs) ...]
[else (error 'all "expected a list, got: " xs)]))
Since all elements in the empty list are true, we get:
(define (all xs)
(cond
[(empty? xs) #t]
[(pair? xs) ...]
[else (error 'all "expected a list, got: " xs)]))
If a list begins with a pair, then all elements of the list are true,
if both the first element of the list and the rest of the elements of the list are true:
(define (all xs)
(cond
[(empty? xs) #t]
[(pair? xs) (and (first xs) (all (rest xs)))]
[else (error 'all "expected a list, got: " xs)]))
Note that part of the problem in your program is the use of when.
The result of
(when #t
'foo)
'bar
is 'bar. The construct when is only useful if you are using side effects (such as caused by set! and friends).
All is a higher order folding function. Scheme refers to these as "reductions" and reduce is available in SRFI-1
In Gauche Scheme:
(use srfi-1)
(define (all list-of-x)
(reduce (lambda (x y)
(and x y))
#t
list-of-x))
Will return #f or a value that evaluates to true. For example:
gosh> (all '(1 2 3))
1
If that's OK, then we're done. Otherwise we can always get #t with:
(use srfi-1)
(define (all-2 list-of-x)
(if (reduce (lambda (x y)
(and x y))
#t
list-of-x)
#t
#f))
And then wind up with:
gosh> (all '(1 2 3))
#t

Scheme - logical operator procedures

I know Scheme and other Lisp dialects include logical operators such as 'and' and 'or', but, since I am currently learning Scheme, I am trying to program my own logical operators. So far my attempts at 'or' have been successful (at least so far as my testing has shown me). My logical or operator is the following:
(define (logical-or a b)
(if a true b))
I am trying to program a logical operator for 'and' that also returns a boolean, but I keep getting stuck. I have tried any number of combinations, but I will just list the following one, which doesn't return a boolean:
(define (logical-and a b)
(if a b false))
Any hints or help welcome.
As Uselpa's answer and the leppie's comments mentioned, the operators and and or don't return #t but the value that was not #f that decided the outcome of the form. Thus
(and 'these 'are 'all 'true 'values) ; ==> values
(or 'these 'are 'all 'true 'values) ; ==> these
The logical operators and and or are short circuiting so they are not procedures. Imagine this procedure:
(define (first-true-value lst)
(and (pair? lst)
(or (car lst)
(first-true-value (cdr lst)))))
(first-true-value '()) ; ==> #f
(first-true-value '(#f #f)) ; ==> #f
(first-true-value '(#f #f hello)) ; ==> hello
If you replace and and or with your versions the procedure will never stop evaluating the recursion.
We know we can rewrite and with if. (and) is #t, (and a) is a and (and a b ...) is (if a (and b ...) #f). We could do this with th easiest Scheme macros, syntax-rules:
(define-syntax logical-and
(syntax-rules ()
((logical-and) #t)
((logical-and a) a)
((logical-and a b ...)
(if a (logical-and b ...) #f))))
We can also do or the same way. (or) is #f and (or a b ..) is (if a a (or b ...)):
(define-syntax logical-or
(syntax-rules ()
((logical-or) #f)
((logical-or a b ...) ; NB: zero elements match "b ..."
(if a a (logical-or b ...)))))
There is a problem with this one since it uses a twice.. Try (logical-or (display "hello")). It will evaluate (display "hello") and thus display the text twice. To fix this we need to wrap the value in a let:
(define-syntax logical-or
(syntax-rules ()
((logical-or) #f)
((logical-or a b ...)
(let ((tmp a))
(if tmp
tmp
(logical-or b ...))))))
If you try the same it will only display "hello" once. Lets try writing my initial procedure with the new macros:
(define (first-true-value lst)
(logical-and (pair? lst)
(logical-or (car lst)
(first-true-value (cdr lst)))))
;; and we test them:
(first-true-value '()) ; ==> #f
(first-true-value '(#f #f)) ; ==> #f
(first-true-value '(#f #f hello)) ; ==> hello
Your logical-or does not always return booleans either:
> (logical-or #f 2)
2
As #leppie says, anything not false (#f) is true in Scheme; try experimenting a little with the build-in or function:
> (or 1 2)
1
> (or #f 2)
2
> (or #t 2)
#t
> (or 1 #f)
1
> (or #f #t)
#t
so the definition in Scheme would be:
(define (my-or a b)
(if a a b))
Likewise, for and:
> (and 1 #t)
#t
> (and 1 #f)
#f
> (and 1 2)
2
> (and #f 2)
#f
> (and #t 2)
2
so the definition is
(define (my-and a b)
(if a b a))
If you want to only return booleans, then you'd code
(define (logical-or a b)
(cond
(a #t)
(b #t)
(else #f)))
(define (logical-and a b)
(if a
(if b
#t
#f)
#f))
This works for 2 values, but since the build-in and and or operators allow any number of parameters (even 0) and only evaluate their parameters if necessary the real definitions are a little more complicated.

How to check if a list contains only #t

I was trying with the following code in racket and MIT scheme, surprise me that the compiler throw err
(foldr and #t '(#t #t #f))
Is there any way to use reduce/fold way to check if a list contains only true or false?
I know a lambda can do the job, but it really make we wonder why this is not a valid code.
I remember I can do it in Haskell.....
TIA.
and is a macro, so it doesn't have a value by itself. Specifically, it short-circuits evaluation, and using it as you tried to will not make any sense. For that reason, Racket has andmap which you can use in such cases. (Other implementations have similar functionality under different names -- for example, srfi-1 uses every.)
And is a macro and can not be used as a function. Put it in a function:
(foldr (lambda (a b) (and a b)) #t '(#t #t #f))
This works in guile:
(primitive-eval (cons 'and '(#t #f)))
One thing that might be off is that in Racket and Scheme, true values are anything other than #f. Since your question asks for booleans, the following will be more discriminating:
#lang racket
(define (boolean-true? x) (eq? x #t))
(define (only-contains-#t? l)
(andmap boolean-true? l))
For example,
> (only-contains-#t? '())
#t
> (only-contains-#t? '(#t #t #t))
#t
> (only-contains-#t? '(#t #t true))
#f

Using AND with the apply function in Scheme

Why doesn't the following work?
(apply and (list #t #t #f))
While the following works just fine.
(apply + (list 1 3 2))
This seems to be the case in both R5RS and R6RS?
and isn't a normal function because it will only evaluate as few arguments as it needs, to know whether the result is true or false. For example, if the first argument is false, then no matter what the other arguments are, the result has to be false so it won't evaluate the other arguments. If and were a normal function, all of its arguments would be evaluated first, so and was made a special keyword which is why it cannot be passed as a variable.
(define and-l (lambda x
(if (null? x)
#t
(if (car x) (apply and-l (cdr x)) #f))))
pleas notice that this is lambda variadic!
apply example (and-l #t #t #f)
or you can use it via apply procedure(as was asked)
for example (apply and-l (list #t #t #f))
both options are ok...
and is actually a macro, whose definition is outlined in R5RS chapter 4. The notation "library syntax" on that page really means it is implemented as a macro.
Section 7.3, Derived expression types gives a possible definition of the and macro:
(define-syntax and
(syntax-rules ()
((and) #t)
((and test) test)
((and test1 test2 ...)
(if test1 (and test2 ...) #f))))
Given this defintion, it is not possible to use and as a function argument to apply.
In the Scheme dialect MIT/GNU Scheme, you can use the function boolean/and instead of the special form and.
(apply boolean/and (list #t #t #f)) ;Value: #f
Also, for the record, I couldn’t find any equivalent function in Guile Scheme’s procedure index.
(Other answers have already explained why the special form and won’t work, and shown how to write your own replacement function if there isn’t already such a function in your dialect.)
If you REALLY wanted to have a function pointer to a function that does and, and you don't mind behavior different than the "real" and, then this would work:
(define and-l (lambda (a b) (and a b)))
Which you can apply like this:
(apply and-l (list #t #f))
The two caveats are:
All of the args get evaluated, in violation of the definition of and, which should have shortcutting behavior.
Only two arguments are allowed.
I've stumbled across the same problem and found an elegant solution in Racket.
Since the problem is that "and" is a macro and not a function in order to prevent the evaluation of all its arguments, I've read a little on "lazy racket" and found that "and" is a function in that language. So I came up with the following solution where I just import the lazy and as "lazy-and":
#lang racket
(require (only-in lazy [and lazy-and]))
(define (mm)
(map number? '(1 2 3)))
(printf "~a -> ~a\n" (mm) (apply lazy-and (mm)))
which yields
(#t #t #t) -> #t
try this:
(define list-and (lambda (args) (and (car args) (list-and (cdr args)))))
then you can use apply to list-and!
You could also use
(define (andApply lBoo)
(if (not (car lBoo)) #f
(if (= 1(length lBoo)) (car lBoo)
(andApply (cdr lBoo)))))
I also bump into this problem playing with PLT-Scheme 372, I have digged into the behavior of and-syntax, and figure out the follow code which works just as if one would intuitively expect (apply and lst) to return, but I haven't done exaustive test.
(define (list-and lst)
(cond
((null? lst) '())
((not (pair? lst)) (and lst))
((eq? (length lst) 1) (car lst))
(else
(and (car lst)
(list-and (cdr lst))))
)
)
Welcome to DrScheme, version 372 [3m].
Language: Textual (MzScheme, includes R5RS).
> (eq? (and '()) (list-and '()))
#t
> (eq? (and '#f) (list-and (list '#f)))
#t
> (eq? (and 'a) (list-and (list 'a)))
#t
> (eq? (and 'a 'b) (list-and (list 'a 'b)))
#t
> (eq? (and 'a 'b '()) (list-and (list 'a 'b '())))
#t
> (eq? (and 'a 'b '#t) (list-and (list 'a 'b '#t)))
#t
> (eq? (and 'a 'b '#f) (list-and (list 'a 'b '#f)))
#t
I've also figured out another mind-trapping workaround. I call it mind-trapping because at first I don't know how to turn it into a function... Here it is (only a demo of my intuitive idea):
Welcome to DrScheme, version 372 [3m].
Language: Textual (MzScheme, includes R5RS).
> (eval (cons 'and (list ''#f ''#f ''#t)))
#f
> (eval (cons 'and (list ''a ''b ''c)))
c
But later I asked a question and got the answer here: Is it possible to generate (quote (quote var)) or ''var dynamically? . With this answer one can easily turn the above idea into a function.
(define (my-quote lst)
(map (lambda (x) `'',x) lst))
(cons 'and (my-quote (list 'a 'b 'c)))
=> '(and ''a ''b ''c)

Resources