Redefine a scheme built-in, but only when used as an argument to a specific procedure?

156 Views Asked by At

How can I redefine the procedure and only when it is called as an argument to the procedure fetch?

For example:

; this `and` returns #f
(and #t #f)

; this `and` returns "and a b" 
(fetch (foo (bar (and "a" "b"))))

I would like to write a macro to do this, but I can't work out how to write a pattern that matches and anywhere in an arbitrary tree of arguments passed to fetch.

I am using Chicken and am happy to use as much of R7RS as Chicken supports.

1

There are 1 best solutions below

2
sjamaan On BEST ANSWER

One nitpick: and is not a procedure, it is syntax (think about it: evaluation is stopped as soon as the first #f is encountered).

But regardless of that, I don't think what you're trying to do is possible by overriding and. You'll need to convert fetch to be a macro. Instead of trying to scan the input and replacing and, I'd use an unhygienic let to override the meaning of and locally. A bit like this:

(define my-local-and ...)
(define the-real-fetch ...)

(define-syntax fetch
  (ir-macro-transformer
    (lambda (e i c)
      `(let ((,(i 'and) my-local-and))
         (the-real-fetch ,@(cdr e))))))

I'd really argue against this, though, because this will really mess with the user's expectations of what is happening. Perhaps you can explain a bit more about why you want to do this?