Search code examples
macrosschemechicken-schemer7rs

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


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.


Solution

  • 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?