Arc Forumnew | comments | leaders | submitlogin
2 points by waterhouse 5158 days ago | link | parent

The reason it doesn't work is that in the code

  (let rec (fn (x) (rec x)))
the "rec" inside (fn (x) ...) refers to the global value of "rec". One might conceivably change the semantics of "let" so that this didn't happen, but then I'd be annoyed because, as rocketnia says, you wouldn't be able to say (let x (+ 1 x) ...). Also, "let" expands to a call to "fn", and one of the things about functions is that you should be able to take a function, rename one of its arguments (and all its uses in the body of the function), and get the same results:

  ; to use akkartik's example
  (let rec (fn (x) (rec x))
    (rec 3))
  ; expands to
  ((fn (rec)
     (rec 3))
   (fn (x)
     (rec x)))
  ; which should be the same as
  ((fn (meh)
     (meh 3))
   (fn (x)
     (rec x)))
There is an alternative semantic for functions, known as "dynamic scope", in which it does matter what names you give to your arguments, and your original "rec" example would work. The thing we have instead of "dynamic scope" is called "lexical scope". I think most people agree that lexical scope is better, though sometimes they encounter particular cases where they want dynamic scope; Common Lisp allows you to declare variables "special" with forms called "defvar" and "defparameter", while Racket/Scheme provides "parameters". Some people (aw and maybe others) have worked out ways to import Racket/Scheme's parameters into Arc; search this forum for "defvar", "implicit", "dynamic", or "parameter".

Now, it is possible to create local recursive functions without using assignment. If you want to do something like "letrec" without assignment, basically you pass the let-environment as extra arguments to your local functions:

  ;The following function is the same as factorial:
  (fn (n)
   ((fn (fact)
      (fact fact n))
    (fn (fact k) ;the "fact" function
      (if (is k 1)
          1
          (* k (fact fact (- k 1)))))))

  ;The following function is the same as "even":
  (fn (n)
    ((fn (even odd)
       (even even odd n))
     (fn (even odd n) ;the "even" function
       (if (is n 0)
           t
           (odd even odd (- n 1))))
     (fn (even odd n) ;the "odd" function
       (if (is n 0)
           nil
           (even even odd (- n 1))))))
The above examples are paraphrased from SICP: http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-26.html...


1 point by akkartik 5158 days ago | link

Ooh, thanks for the connection with dynamic scope.

-----