Arc Forumnew | comments | leaders | submitlogin
2 points by rocketnia 3282 days ago | link | parent

I think you might have made a slight mistake translating 'alet. Here's a minimal fix:

   ;Anaphoric let
   (mac alet (args . body)
  -  `(with ,args
  +  `(with (this nil ,@args)
        (assign this ,(last body))
        ,@(butlast body)
        (fn params
          (apply this params))))
The code probably seemed to be working, but it was actually setting a variable 'this from the surrounding scope rather than its own 'this.

In a way it's fitting to bring that up, because 'alet-fsm is designed to modify the 'this from the surrounding scope....

Er, speaking of which, your translation of 'alet-fsm is pretty surprising. (You're assigning a bunch of nonlocal variables, and you're even redefining a global macro at run time, which is usually too late because the program has already been macroexpanded. Furthermore, instead of returning the first state of the FSM, you're returning the implementation of a macro.) I'll start from the original Common Lisp code:

  (defmacro alet-fsm (&rest states)
    `(macrolet ((state (s)
                  `(setq this #',s)))
       (labels (,@states) #',(caar states))))
While Arc doesn't have (macrolet ...), in this case we can achieve something very close by just making this macro global, since it has no local dependencies.

  (mac state (s)
    `(assign this ,s))
What (labels ...) does in Common Lisp is introduce some local variables that hold functions, in such a way that every function's definition can see every other function. To keep my code simple to read, I'm going to resort to a utility from Anarki that achieves the same kind of scope, namely (withr ...):

  (mac alet-fsm states
    `(withr ,states
       ,car.states))
The expansion of (withr (a (fn ...) b (fn ...) c (fn ...)) ...) is something like this:

  (with (a nil b nil c nil)
    (assign a (fn ...))
    (assign b (fn ...))
    (assign c (fn ...))
    ...)
Note how the local variables are introduced in a (with ...) scope that fully surrounds the (fn ...) expressions, so all the variables are in scope for all the functions.