Home > Software design >  Can I replace a Racket's function with my custom function of the same name? Doable?
Can I replace a Racket's function with my custom function of the same name? Doable?

Time:07-07

In the following code I defined my own a-hl with which I mean to replace the direct call of append in my code. It does not really replace it as it uses append under the hood (see the comment):

#!/usr/bin/env racket
#lang racket/base

(require racket/file)

(define (a-hl l e) (append l (list e)))  
(define content (list "https://youtu.be/FVaVLpSHw38 Road to the Arnold" "https://www.youtube.com/watch?v=hlTfA42b_uI MIT Bitcoin Expo 2022: Breaking Through - Lightning Panel"))
(define arr (list))
(for ((l content)) 
  ;(set! arr (append arr (list (regexp-replace* #rx" .*" l "")))))
  (set! arr (a-hl arr (regexp-replace* #rx" .*" l "")))); works just as well but it is shorter
  
(for ((e arr)) (display e))

The code works fine. But when I attempt to define my own append, (define (append l e) (append l (list e))) and that use it,

(for ((l content)) 
  (set! arr (append arr (regexp-replace* #rx" .*" l ""))))
  
(for ((e arr)) (display e))

Racket freezes. Is it at all doable to replace a Racket's function with my custom function of the same name?

CodePudding user response:

You can define your own versions of functions, and doing that only affects code in your module or modules which require that definition from it.

Whether you should do that for definitions like append, is a different question: doing so is a good way of setting snares and traps for the unwary. Probably it is something to do only if you really understand the consequences of doing it and if you are in the process of building a language which is semantically very different than the standard Racket languages.

In this case it looks like the unwary person caught in the trap was you. Your definition of append is:

(define (append l e)
  (append l (list e)))

That is a definition which will clearly both not terminate, and use unbounded memory in the process of not terminating.

Your problem seems to be that you think that the version of append called by the definition is Racket's one. It's not: that's not how define works, not in this case and not ever. In a form like

(define (<name> ...)
  ... <name> ...)

or equivalently

(define <name>
  (lambda (...) ... <name> ...))

Then (assuming there are no intervening bindings of <name>), <name> refers to the thing you are defining.

CodePudding user response:

You can use Racket's require's only-in clause to give your own name to a binding from a module, and use that:

#lang racket

(require (only-in racket/base [append builtin-append]))
(define (append l e) (builtin-append l (list e)))
(writeln (append '(1 2 3) 4)) ; (1 2 3 4)

or use local-require to import it only inside your function:

(define (append l e)
  (local-require (only-in racket/base [append builtin-append]))
  (builtin-append l (list e)))
  • Related