1
votes

In Racket it is possible to define a procedure and constants inside of another procedure, for example like this:

(define (a a-list)
  (define something 10)
  (display a-list)
  (cond
    [(empty? a-list) (display "done")]
    [else
      (display a-list) (newline)
      (a (rest a-list))]))

Printing the list and then taking away the first element, then printing the list again and so on until the list is empty.

In the example procedure a value something is defined to be 10, for whatever reason. When the procedure recurses, does Racket define the value again, or is it intelligent enough to notice, that this definition does not change?

Also it would probably be on the stack space of the previously called procedure, if this is not optimized and it would consume some more memory per recursive step, depending on what something is defined as. For example lets say a million numbers in a list, but never changing numbers. Obviously if things inside that definition depend on the list given as parameter, it cannot so simply be optimized.

If this is not optimized, is it a good idea to not have too many define forms inside a recursive function, or only the ones, which consume little space? Putting them outside of the procedures would make them accessible from other procedures though, even if only the one procedure ever uses them.

1

1 Answers

1
votes

The define expression is evaluated every time the procedure is invoked. Consider this example:

(define (test1)
  (define x (begin (display "Hello from test1 ") 10))
  x)

(test1)
=> Hello from test1 10
(test1)
=> Hello from test1 10
(test1)
=> Hello from test1 10

If you want a value inside a procedure to be evaluated only once (when the procedure itself is created), you can put it in a scope outside the procedure, it'll still be accessible because a lambda defines a closure over its lexical environment:

(define test2
  (let ((x (begin (display "Hello from test2") 20)))
    (lambda () x)))

=> Hello from test2
(test2)
=> 20
(test2)
=> 20
(test2)
=> 20