Sportalcraft
Sportalcraft

Reputation: 265

Syntax and variables in Scheme

obviously, this code should fail : (define or 5)

but I was wondering why does this code fail to run :

(define apply 
    (lambda (x y f)
        (f x y)
    )
)
(apply #f #t or)

(or #f #t), would work as expected.

I'm not defining any new variable with a saved name, only passing the function or as an argument.

and (apply 1 2 +) on the other hand works...

Upvotes: 3

Views: 155

Answers (2)

alinsoar
alinsoar

Reputation: 15783

When you want to redefine special forms you need to use thunks, otherwise the arguments get evaluated, while the arguments of the special forms are evaluated in the order imposed inside the special form.

Instead, to get the same behavior as the semantics of the special forms you can force and delay the argument evaluation by using thunks. For example,

(define (or-sp-form a b) (if (a) 'ok (b)))

and call such a function like

(or-sp-form (lambda () false) (lambda () true))

Defining a special form like that, it can now be passed as argument to other functions like

(f or-sp-form)

and take care inside f to pass delayed arguments to or-sp-form.

Upvotes: 1

Dan D.
Dan D.

Reputation: 74645

or is a special form. It isn't a function. So it can not be passed like that as an argument. Rather than (apply #f #t or), you must use:

(apply #f #t (lambda (a b) (or a b)))

(define or 5) does not fail. It shadows the or special form. Some implementations may not allow redefinition either within a module or of given symbols. So when asking about Scheme it is important to specific the implementation.

This is because special forms can only occur in the first position. Special forms are implemented as macro expansions. For example: (or a b) => (let ((v a)) (if v v b))

Upvotes: 3

Related Questions