Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass `and` as a function in Racket?

For the following code:

(foldl and #t '(#t #f))

Racket returns:

and: bad syntax in: and

I know and is not a function. And I can circumvent this problem using lambda:

(foldl (lambda (a b) (and a b)) #t '(#t #f))

I have 2 questions here:

  1. and is not a function. Then what is it? Is it a macro?

  2. My solution using lambda seems ugly. Is there a better way to solve this problem?

Thank you.

like image 416
Ben Avatar asked Jul 29 '13 08:07

Ben


1 Answers

It is a conditional syntactic form, or it might be implemented as a macro that expands to some core syntax form, which is treated as a special case by the compiler/interpreter.

The list there in Racket's docs includes if as a special form but doesn't include and, so the latter most probably is implemented in terms of the former. But R5RS does list and as a syntactic keyword. So, best we can say, it's either a special syntax, or a macro.

It is easy to re-write any and form (and a b c ...) as an if form, (if a (if b (if c #t #f) #f) #f).

lambda is fine by me, but you can also use every from SRFI-1 (or Racket's andmap):

(every identity '(#t #f))

should return #f.

edit: except, as Joshua Taylor points out, calling your lambda through a function like foldl does not short-circuit. Which defeats the purpose to calling the and in the first place.

Another thing is, in Racket's foldl the last argument to lambda is the one that receives the previous result in the chain of applications; so the implementation should really be

(foldl (lambda (a b) (and b a)) #t '(#t #f))
like image 184
Will Ness Avatar answered Oct 06 '22 09:10

Will Ness