Nested Scheme Functions Not Returning Properly - scheme

I have created a function that can determine if a character is in a list. While it works fine by itself, it does not work properly when called by another function which is suppose to compare the elements of a list to several key words. I have also tried using the functions memq, memv, and member, but they fail as well. I would like to know what it is that is causing my program to not return #t and where I went wrong.
(define in?
(lambda (y xs)
(if (memq y xs) #t #f)))
(define det?
(lambda (xs)
(if (in? 'a xs) #t)
(if (in? 'an xs) #t)
(if (in? 'the xs) #t #f)))

There's no such thing (*1) as an explicit return statement in Scheme; a procedure just returns the value of the last expression. Chris has shown you alternatives with cond and correct, 2-armed ifs.
If you find yourself with conditionals returning #t and #f there's usually a more elegant alternative using boolean logic, in this case:
(define det?
(lambda (xs)
(or (in? 'a xs)
(in? 'an xs)
(in? 'the xs))))
and in? could be expressed as
(define in?
(lambda (y xs)
(and (memq y xs) #t)))
(*1) I was lying, of course. You can have this effet using call/cc or any variation thereof. It's an advanced subject and not appropriate for your situiation, but to give you a glimpse of what it would like:
(define det?
(lambda (xs)
(call/cc
(lambda (return)
(when (in? 'a xs) (return #t))
(when (in? 'an xs) (return #t))
(when (in? 'the xs) (return #t))
#f))))
Note that I use when, not if, since they are still one-armed conditions.

Your use of if is incorrect; only the last if actually does anything. (To help prevent these kinds of errors, Racket bans the use of one-armed if expressions.) Perhaps you would like to use cond instead?
(define (det? xs)
(cond ((in? 'a xs) #t)
((in? 'an xs) #t)
((in? 'the xs) #t)
(else #f)))
This macro-expands to the following ifs:
(if (in? 'a xs)
#t
(if (in? 'an xs)
#t
(if (in? 'the xs)
#t
#f)))
Notice how that's different from your series of if expressions.

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 Error Object Is Not Applicable

I am writing a Scheme function that detects if a word is in a list of words. My code uses an if statement and memq to return either #t or #f. However, something is causing the first parameter to return the error that the object is not applicable.
(define in?
(lambda (y xs)
((if (memq( y xs )) #t #f))))
Parentheses matter:
(define in?
(lambda (y xs)
(if (memq y xs) #t #f)))
so
you have double parentheses before if
you put memq parameters between parentheses
BTW, you can also express this as
(define in?
(lambda (y xs)
(and (memq y xs) #t)))

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