Search code examples
functionschemeracketredefinition

Redefining a fuction used to define this function in Scheme


I think the title is a bit weird but, for example, is there a way to redefine the addition in Scheme so that (+ arg1 arg2) gives arg1 + arg2 + 1?

I can create a new function @:

(define @ (lambda args (+ (apply + args) 1)))

such that (@ 42 13) gives (42 + 13 + 1). But is there a way to do something which would look like:

(define + (lambda args (+ (apply + args) 1)))

but of course without the error since, here, it says that + is undefined?


Solution

  • In R7RS version of Scheme we have imports so here we can do it:

    #!r7rs
    
    (import (except (scheme base) +)
            (rename (scheme base) (+ base:+)))
    
    (define (+ . args)
      (apply base:+ 1 args))
    
    (+ 1 1) ; ==> 3
    

    In R6RS version its the same except (scheme base) is (rnrs base) Racket has something very similar:

    #lang racket
    
    (require (only-in racket/base [+ base:+]))
        
    (define (+ . args)
      (apply base:+ 1 args))
    
    (+ 1 1) ; ==> 3
    

    In R5RS report Scheme and older the report allows a user to redefine a procedure to extend the features of it, but it is a violation that it for the defined types would result in different results than the original scheme report version would. Thus redefining + like this is a violation and not portable Scheme. It might work in some implementation, but the wording is done such that a smart Scheme compiler can do constant folding and expect the correct result from supported types.

    #!r5rs
    
    (define + 
      (let ((r5rs:+ +))
        (lambda args
          (apply r5rs:+ 1 args))))
    
    (+ 1 1) ; ==> 2 or 3, perhaps an error