Ouija: A Scheme Interpreter in Flash

Today I’m releasing to you, the world, my Scheme interpreter in Flash. This is in no way a polished thing, so don’t expect a ton, but it is pretty cool in my opinion. In the past few months I’ve created a few flash prototypes with it because it lets me develop significantly faster than with just plain ActionScript.

Please note while reading this that the company that I was once employed at is no longer, and I am currently looking for employment. So, if you are reading this and saying to yourself, “Wow, I wish I could hire someone that could make me a Scheme interpreter in Flash”, you are in luck!

Anyway, here’s a REPL for you to play with, the top portion is interactive while the bottom is persistent, allowing you to put code there which remains when you refresh or come back later. The REPL does have it’s problems, but it’s good enough to let you play with it. The SWF file that you’re hitting is loading REPL.oui when it starts, but only because the SWF name is REPL.swf. If you download REPL.swf and rename it Test.swf, it will attempt to load Test.oui at runtime.

The differences between this and the Lisp Interpreter I made a while back are as follows:

  • Scheme syntax instead of Common Lisp
  • Closures work
  • Continuations
  • FULL ACCESS TO THE WHOLE FLASH8 RUNTIME, this allows you to do graphics, sound, animation and anything else you can do with Flash normally
  • In AS2 as opposed to AS3; I did this due to the flexibility for AS2 over AS3, and my hope is to port it very shortly.

So if you know Scheme already you can start messing around with things like

(define a '(1 2 3 4))
(apply + a)

The next step is doing things with the Flash side.

(define pic (create-clip))
(set! (_x pic) 200)
(load-image pic "ouija.jpg")
(set! (_scale pic) 50)

So now you have a movieClip on the stage with an image loaded into it and sized to 50%. Normally in Flash we’d have to call a load command and set up an event to fire when it was loaded so that we could start doing things with it, but because we’re using Scheme, we actually can halt execution of code until the image is loaded (this is the default behavior, but we can still utilize the event-driven method by using threads). We can do the same thing with tweening.


(transition 24
(pic
('_x :to 300)
('_rotation :to 360)))

When you’re done messing with the image you can remove it like this


((=> pic 'remove-movie-clip))

This is the basic method of interacting with the Flash API. In Flash a movieclip has a method on it called removeMovieClip. By calling (=> pic ‘remove-movie-clip) we are getting that method, and by wrapping it in an extra set of parenthesis we are calling it (note that the dashes from remove-movie-clip are removed and the letter immediately following the dash is capitalized when the method is looked up. This is because Ouija is case-insensitive where as ActionScript is case-sensitive).

Now, audio is another case where I don’t have any “nice” ouija methods written. So in Flash you’d have to write.


var song=new Sound();
song.loadSound("song.mp3")
//yes there is an mp3 called song.mp3 on my server
//and I'm pretty sure the writer isn't going to sue me
//for putting it up there.
song.onLoad=function() { song.start(); }

So translated directly into Ouija it would look like this

(define song (make-instance *sound))
;the * at the beginning is to make the first letter caps
((=> song 'load-sound) "song.mp3")
(set! (=> song 'on-load) (lambda () ((=> song 'start))))

And then to stop it


((=> song 'stop))

In all, there are quite a lot of things you can do and ideas to play with. I’m sure there are a ton of broken things, but I figure if I don’t release this thing now, I never will.

Also if you’re interested you can check out this site I created in Ouija (here is the source code, also note that the version of the SWF contains some extras not in the REPL). After I finished this version I hand-compiled it so that it would run more quickly on the pre-Intel Mac versions of the Flash Player and then we updated some things. That version is here. After that, the company shutdown.

Alright, so here’s a list of functions and constants in Ouija.

Constants

  • t or #t : the true boolean
  • nil or #f : unlike Scheme, Ouija uses the Common Lisp nil as both false and the end of a list, #f is also defined, but it is a reference to the NIL object
  • _root : this is a reference to the root MovieClip of the running flash
  • pi, 2pi, pi/2, pi/3, pi/4, pi/6, pi/12 : pi and common fractions of pi

List Functions

  • (cons a b) : creates a cons cell
  • (car a) (cdr a) (caar a) (cadr a) (cdar a) (cddr a) : these can also be used with set!, (set! (cadr a) 5)
  • (list 1 2 3 4 5) : creates a list
  • (list* 1 2 3 4 5) : creates a list with the last cell being a dotted pair, in this case (1 2 3 4 . 5)
  • (append list1 list2 …) : returns new list with list1 appended to the beginning of list2
  • (append! list1 list2 …) : destructive version of above
  • (reverse lst) : reverses list
  • (reverse! lst) : destructive version of above
  • (map fn lst …) : return new list by applying fn to each element of lst, can take multiple lists
  • (for-each fn lst) : like map, but only for side-effects, doesn’t return a list
  • (map-append fn lst) : like map only it appends instead of consing
  • (filter fn lst) : returns new list filled with elements that didn’t return NIL when passed to fn
  • (foldl fn init lst) : left fold
  • (foldr fn init lst) : right fold
  • (compose fn1 fn2 …) : returns a function composed of the arguments
  • (nth index lst) : returns the nth element in list, also works with set!
  • (nthcdr index lst) : like about, but returns whole cons cell
  • first, second ….. tenth : also works for set!
  • (copy-list lst) : return copy of list
  • (last lst) : returns the last cons cell in the list
  • (butlast lst) : returns a copy of the list without it’s last element
  • (length lst) : returns the length of the list, also works for arrays
  • (getarg prop-list key) : returns the value of the associated value in a prop-list
  • (filter-out-keys prop-list remove-list) : returns new prop-list with specified keys removed
  • (member value list) : finds value in list, returns the rest of the list

Math Stuff

  • = + - * / < > <= >=: all take multiple parameters
  • max min
  • sqrt cos sin tan acos asin atan atan2 floor ceiling round expt modulo truncate quotient remainder

String Stuff

  • (->string arg) : converts argument to string
  • (mkstr arg1 arg2 …) : converts each arg to a string and concatenates them all
  • (string-append arg1 arg2 …) : like mkstr, but it assumes all args are strings already
  • (format ctrl-string arg1 arg2 …) : only supports ~a ~n ~x and ~~.

Object Stuff

  • (make-instance class arg1 arg2 …) : creates a new instance of a class
  • (=> obj ’slot) : returns property of an object, works with set!
  • (create . prop-list) : creates object ex: (create :name “Chuck Loads” :age 30 :sex ‘male)
  • (array arg1 arg2 …) : creates array
  • (with obj . body) : allows you to execute code in the scope of the given object

Normal Scheme Stuff

  • if lambda eq? equal? quote and or when unless push! pop! inc! dec! not let (normal and named) fluid-let call/cc let/cc dynamic-wind display newline
  • cond (use t instead of else)
  • define : can be used to define curried functions as well (define ((add a) b) (+ a b))

Predicates

  • boolean? number? atom? pair? list? symbol? keyword? procedure? null? zero? negative? positive? odd? even?

Flash Stuff

  • (create-clip) : create movieclip, optionally takes parent clip
  • (create-textfield) : creates textfield, optionally takes parent clip
  • ((=> clip ‘line-style) 1 0 100) : need to do this or something like it to draw on the clip
  • (draw-rect clip x y width height)
  • (draw-line clip x y width height)
  • (draw-rounded-rect clip x y width height radius)
  • (draw-circle clip x y r)
  • (transition frames . data) : see the example
  • _visible _alpha _x _y _xscale _yscale _scale _rotation _width _height : function accessors for movieclip properties
  • (return-click) : waits for user to click on something and then returns a reference to what was clicked.
  • (get-timer) : return ticks since swf started
  • (update-stage) : updates stage during execution of a function
  • (display-layout parent . children) : creates a movieclip and textfield hierarchy, example below


(display-layout image-content
(movie-clip (:id mc :_visible #f)
(text-field (:id title
:font "ITC Franklin Gothic Demi" :size 26
:auto-size "left" :text-color 0×5f2c1f
:embed-fonts #t :selectable #f
:_x 26 :_y 20
:text (=> content-data 'title)))
(text-field (:id body
:font "ITC Franklin Gothic Book" :size 14
:auto-size "left" :text-color 0×333333
:multiline #t :word-wrap #t :embed-fonts #t
:_x 280 :_y 60 :_width 260
:html-text (=> content-data 'text)))
(movie-clip (:_x 30 :_y 65
:src "test.jpg")))))

Other stuff

  • (eval val) : evaluates symbol, value or s-expression
  • (load file) : loads and executes Ouija code from a file
  • (read) : only works in repl, gets value from user
  • (read-from-string str) : parses string into symbol, number or s-expression
  • (gensym) : create symbol
  • (defmacro (name . args) . body) : Common Lisp style macro; Ouija does not do Scheme macros
  • (thunk . body) : same as (lambda () . body)
  • (amb arg1 arg2 …) : you should know what this does; if not, look it up
  • (amb-assert test)
  • (amb-collect . body)
  • (random (&optional n)) : returns random number
  • (random-char) : return random character
  • (random-string (&optional length)) : returns random string
  • (thread fn) : calls fn in a separate thread
  • (sleep seconds) : waits for a certain amount of time before execution is resumed
  • (dotimes (i times) . body) : standard CL dotimes
  • (dolist (i lst) . body) : standard CL dolist
  • (in-parallel fn1 fn2 …) : executes each function in a “thread”, then returns a list of the results
  • (map-in-parallel fn lst) : like map, only it does each in a “thread” instead of sequentially

Next Steps…?

So I’ve reached a fork in the road with my current project and am trying to figure out which path to take. I’m hoping that writing this will help me reach a conclusion.

For the past several months I’ve been building a Scheme interpreter (originally a Lisp one, but the I converted) in Flash. The differences between my this one and the previous ones are as follow.

  • Scheme instead of Lisp, this allowed me to focus on a smaller subset of commands to implement, not just my favorite ones at the time.
  • Ability to interact with the full underlying Flash Player, which allows me to mess with graphics and all those other things that you’d actually expect from an interpreter built on Flash.
  • Nifty things like continuations and optimized tail-calls, allows me to implement things in this interpreter quicker and with significantly less code that if I were implementing it in ActionScript.

So anyway, I’ve gotten to the point where I’m quite happy with what I have and I’m trying to figure out what to do next. So my options are.

  • Release it to the world as is. Probably with source code too. See who’s interested and what ideas they may have with how to make it better. The other possibility is to release it in some sort of interactive tutorial form which would let people with little or no Scheme/Lisp experience (or maybe no Flash experience) to play with it and see the power and possibilities.
  • Abstract all the ActionScript code (it is all AS2 right now since that gave me the greatest flexibility) to a level where I’m defining the interpreter in a smaller subset of Scheme and ActionScript bytecode. This would hopefully allow me to then to create a compilers specific to different VM’s such as AS3 or SilverLight or something.

    I haven’t fully thought this one out yet, but it’s currently the most attractive of the paths because it seems the most interesting and most challenging. This would then probably wind up leading into the option above.

  • The last of the options is to use the interpreter in a CMS/Web-Framework that I created a proof-of-concept for a few years back. The basic idea was if you had the same language available on the client-side as you did on the server-side, and if that language was good enough to allow you to abstract over the atrociousness of HTML and CSS, then you would be able to create higher-level web-app designs that could be altered in real-time without ever talking to the server.

    This seems like a really cool idea to me, especially if it was combined with a continuations, but in the end it would just be another web framework, and I don’t even really do any website building. I think this is only interesting to me because it allows you to show programmers and non-programmers some of the magic that Lisp lets you do (this is something that really excited me about my POC, because people that knew enough about the web would say things like “You can’t do that!!”)

Yeah, so this didn’t help me too much. They all seem to have their merits. I know this isn’t the flame-bait that my last post was, but any input would be greatly appreciated.

I chose Scheme over Common Lisp

I know this may seem like heresy, but it’s the truth. A few weeks ago I made the choice to move from Common Lisp (I had been using the Allegro implementation for about 2.5 years) to PLT Scheme.

I don’t want to go on and on like I know have reached some level of enlightenment that CL users haven’t, but I would like to briefly list some of my feelings about the switch.

What I like better about Scheme even though I once mentioned it as a reason why I wouldn’t

  • Functions and variables in the same namespace
    This always seemed like the move from a Lisp-1 to a Lisp-2 was a positive thing. You wouldn’t have to worry about having a variable that clashed with the name of a function, but it seems like was only an issue of having way too many functions with crazy names all over the place. The big problem that it creates is that you have to use FUNCALL to execute a function store in a variable, you have to use #’ to pass a function to an applicative, and you have to treat functions different than variables in general. (If you want to see something really scary try looking at the Y Combinator implemented in Common Lisp)

    I’ve found that in Scheme my code is more elegant, tends to be far more functional and the only real concession I’ve had to make is that i can’t call a variable LIST (like any one ever actually does that, even in CL people use LST or LIS).

    I should also mention that I’ve read that as of R6RS Scheme will be case-sensitive by default, which would allow you to use case conventions to separate variables from functions if you so desired.

  • The define syntax
    Whenever I used to try and read Scheme code I found myself overwhelmed by the define statement. Not only was it significantly different looking that the defun, defparameter, and let statements that I was used to, but that they were used differently, they were nested all over the place, functions created inside other functions and other odd things that made my brain hurt.

    As it turns out, for me, using (DEFINE (square x) is way more natural for lisp than (defun square (x), since in the end it’s the same syntax as that way that you call the function. Also by using Swindle (an add-on to PLT-Scheme) you have the syntactic-sugar available for currying.


    (define ((add a) b) (+ a b))

    winds up being compiled to

    (define (add a) (lambda (b) (+ a b)))

    Like I said above I find now that my Scheme code is way more functional than my CL code ever was and I think this is a big part of it, I wind up using recursion and folds all the time instead of the doTimes, doList, while and loop constructs that I used to use. As much as this was a bit hard to get used to, it wound up being way more readable and concise than the iteration constructs.

  • Continuations
    Ever since I heard of continuations I was intrigued, but they aren’t available in CL. All the reading that I did as to why mentioned that the reason for this is that it was essentially a GOTO statement, and that THROW and CATCH were available. Also, the feeling that I got was that unless you’re doing a continuation-based webserver that they are just an interesting toy that’s fun to play with.

    Turns out that I find it hard to believe that I lived without continuations before (the same feeling that I had when I discovered closures). The AMB and AMB-COLLECT macros wind up being particularly useful for permutations. The following code collects a list of all lists with lengths from 1-4, where each item in the list is 1-4.


    (define (make-list n)
      (if (positive? n) (cons (amb 1 2 3 4) (make-list (- n 1)))
          null))
     
    (amb-collect
    (make-list (amb 1 2 3 4)))

    this is pretty cool too.


    (define (between a b)
      (if (<= a b)
          (amb a (between (+ a 1) b))
          (amb)))
     
    (let ((a (between 2 9))
          (b (between 2 9))
          (c (between 2 9)))
      (amb-assert (= (+ (* a a) (* b b)) (* c c)))
      (list a b c))
     

    Continuations and the AMB macro are probably going to need their own post. I should also mention that the understanding of CPS-style coding has forever change the way I code javascript and actionscript.

The only other thing that I going to mention is that I really enjoy APPEND! being the destructive version of APPEND instead of the CL NCONC, there are tons of examples like this. These kinds of decisions made by the Scheme crowd actually make a ton of sense, where as when trying to learn CL was kind of like memorizing history.

The only thing that still bugs me about Scheme is the separation of #f from NIL. I know I shouldn’t have a problem with this since it makes tons of sense, but it still bothers me that when I’m using recursion, instead of (IF LST , I’m forced to write (IF (NOT (NULL? LST)).

That’s all I have for now. Let the angry comments begin.

Excuses, excuses.

So I have to admit that I’m ashamed for not having written anything here in the past few months. I’ve been working on a project that was responsible for creating most of my past posts, whenever I found something I thought was interesting or cool in a solution, I would write about it. Anyway, I’m past the point where I’m solving interesting problem, and now spend most of the time trying to fix bugs, change syntax, write documentation, and other things that don’t have any real clever solutions.

There are a few things that I’ve been dealing with. If anyone is interested in hearing more about any of these topics let me know:

  • Common Lisp vs Scheme, why must I choose sides?
  • Why is everyone an idiot? why can’t flash halt execution until something happens?
  • XML single-handedly set software back 50 years
  • Continuation Passing Style and why it is awesome

This is the lamest post I’ve written so far, but I’m posting it to spite myself.

__resolve

In AS2, the __resolve property is a really cool feature that allows you to do some pretty cool stuff. It is a property that can be set on any object (it needs to be set to a function to actually work), and in doing so you force the object to call that function whenever a property is requested from the object that is not defined (which is different than being set to undefined). This winds up being useful in a few situations. The first I’ll discuss is Symbols, then Keywords, and a makeshift variable name misspelling catcher. So here we go, I’m going to start kinda slow and proceed by trying to do something that most people probably have no interest in doing. As a side note, anyone interested in doing this sort of thing is AS3 needs to look into the Proxy object.

Say you want to create a variable. Easy,

var a=10;

Ok, now say you want to create two variables that point to the same thing. Well if you do

var a=10;
var b=a;

They are both set to 10, but if you do

a++;

Now a is 11 and b is still 10.
The problem is that numbers (as well as strings and booleans) are primitives; what we need is an object so we do

var a=new Object();
a.value=10;
var b=a;
a.value++;

Now magically a.value and b.value are both set to 11.

Ok, so now what I want to be able to do is have a way so that variable a actually points to b, not to the value that b is presently pointing at, but to b. This is where Symbols comes in. In Lisp and Scheme a symbol is an object that has a name and a value (in lisp it can also have a function, but we’re not going to get into that now). So if I want to have symbol A point at symbol B I just say:

(setf a 'b)
(setf b 20)
(print a) ;;prints the character B
(print (symbol-value a))
;; prints 20 since A evaluates to B and the value of B is 20
(print (eval a))
;; this does the exact same thing for the exact same reason

So in flash now I want to be able to write code that looks like this

Symbols.a.value=Symbols.b;
Symbols.b.value=10;
trace(Symbols.a.value) //traces [b]
trace(Symbols.b.value) //traces 10

Made it this far? Good. So to get this type of functionality I first need an class for a symbol. It needs to have a name, a value and a toString function so that when it traces it identifies itself instead of just outputting “[object Object]”. Here goes..

Symbol=function(name)
{
  this.name=name;
  this.value=null;
}
Symbol.prototype.toString=function()
{
  return "["+this.name+"]";  
}

Yeah, I still use the prototype method for creating classes because it rules. Maybe I’ll write a post about that sometime (one of the biggest reasons is that there’s a weird bug in the AS2 Class file method that has to do with closures not working correctly).

Now what we want is a way to create these symbols automatically so that we can just call Symbols.Hello and it will be there. This is where we use the magical __resolve property.


Symbols=new Object();
Symbols.__resolve=function(symbolName)
{
  var newSymbol=new Symbol(symbolName);
  Symbols[symbolName]=newSymbol;
  return newSymbol;
}

The Symbols object gets created here, and then when we request a property from Symbols it either has it or it doesn’t, if it does it simply returns it, but if it isn’t there the function attached to the __resolve property is called with the parameter being the string representation of the property name you requested. We simply then create a new symbol with that string as the name, then we attach it as a property to Symbols, the property name being the name we’ve just requested.

And there you have it. Now we have Symbols in flash.

Keywords in Lisp are like symbols only they evaluate to themselves; that’s quite easy to do with the Symbol code above. I’ve had more need to be able to create strings automatically as if they are objects which is the code I’m going to show you here.


Keywords=new Object();
Keywords.__resolve=function(name)
{
   return name;
}

This simply allows you to use object instead of strings for things like event names, library item names, etc. The nice thing about this is that if you use Keywords then instead of strings in your code and you have 1000 cases where you use Keywords.SomeThing and the string needs to change from “SomeThing” to “SomeThingElse” you can simply add the code

Keywords.SomeThing="SomethingElse";

And you’re done. (or you could do a find and replace but hey, we’re learning about __resolve now).

or as I mentioned with library items you could do something like this

Library=new Object();
Library.__resolve=function(name)
{
  return name;
}
MovieClip.prototype.AttachItem=function(name)
{
  var depth=this.getNextHighestDepth();
  return this.attachMovie(name,name+depth,depth);
}
 

Then you can write code like

_root.AttachItem(Library.Button);

Lastly, as I mentioned before I enjoy writing my flash code without creating class files for it. This gives me a lot of extra freedom, but I don’t get the compiler checking my code to make sure that I’m not calling a variable that doesn’t exist which can sometimes cause some very difficult to track down bugs, especially when it’s late and your eyesight is shot. Here’s the code i use:

_global.__resolve=Object.prototype.__resolve=function(name)
{
  trace("Error:requested undefined property "+name);
  return undefined;
}
_root.__resolve=function(name)
{
  return _global[name];
}

This traces out an error whenever a property is called that isn’t available just as a warning. This winds up being quite helpful for me during development, and then I remove it when finished. Technically, you’d think that you’d only need the Object.prototype.__resolve=… part, but it creates some problems with how flash works. Seems as though when you request something it first checks the _root for it, and then _global, and if it’s not found then it returns undefined. If you were to just set up the Object.prototype it would seem to work fine until you called

var arr=new Array();

Then it would tell you that Array is undefined since Array is not a value that’s defined in the _root, but actually in _global. Flash seems to check _root first, then _global, but if we set up just the Object.prototype it doesn’t, so we need to also set up _global (which oddly enough doesn’t extend Object), and then create a __resolve method on _root to check _global.

So there you have it, a bunch of stuff that’s interesting to know, but probably completely useless unless you’re doing something like, I don’t know, say writing a Lisp interpreter in flash.

Note:This is not the way that I implemented Symbols in the Lisp interpreter I posted here on the site. This concept is used in a new one that I’m working on that allows for full interoperability with Flash.

JavaScript/ActionScript prototype-based OO

Here is a diagram I found that illustrates quite clearly how prototype-based OO works. Learning how this works not only gives you a better idea of how OO works in JavaScript and ActionScript, but will also allow you to do other magical things such as changing the type of an object on the fly.

AS3 Lisp Source

So I got asked a few times to post the source for the AS3 Lisp. I have and it’s here. Please keep in mind:

  • I wrote this a year and a half ago and didn’t know AS3 or Lisp very well
  • I never intended to release the source so I apologize if anyone is offended by any class names, variable names, function names or comments
  • I have since figured out a way better way to handle symbols in the system and it would really clean up a ton of stuff
  • Some one over at YCombinator News noticed that closures don’t seem to work and for that I apologize, if I were rewriting this (which I kinda am just in a different form) I would definitely make closures works since I now realize how important they are to Lisp

Lisp Interpreter in AS3

So back when Adobe released the Flash 9 Pre-Alpha I took the opportunity to learn AS3 by indulging in one of my favorite pastimes, writing a Lisp interpreter. And what’s even more odd than coding a Lisp interpreter for enjoyment is that when I had it to a point where it was somewhat working, I came up with an actual use for it. Anyway, going into the actual use I found for it is another story that has to do with the interesting bonus you get when you can run the same code on the server as you can on the client. So here’s the link and here’s the list of stuff that seems to work. Update: I posted the source for this, check out the entry here.

  • mapcar
  • apply,funcall
  • every
  • reduce
  • find-if
  • remove-if,remove-if-not
  • prog1,prog2,progn
  • push
  • pop
  • incf
  • decf
  • while
  • until
  • when
  • unless
  • with-output-to-string
  • multiple-value-list
  • multiple-value-call
  • multiple-value-prog1
  • multiple-value-bind
  • nth-value
  • dotimes
  • dolist
  • cons
  • rplaca,rplacd
  • list
  • member
  • reverse
  • append
  • list-length
  • car,cdr
  • last
  • nth,nthcdr
  • first,second……tenth
  • caar….cddddr
  • +,-,*,/
  • expt
  • mod
  • rem
  • random
  • 1+,1-
  • floor
  • ceiling
  • truncate
  • round
  • print
  • princ
  • format
  • null
  • zerop
  • plusp,minusp
  • oddp,evenp
  • listp,atom
  • symbolp
  • numberp
  • keywordp
  • stringp
  • quote
  • backquote,unquote,unlist
  • setq,set
  • setf(car,cdr,symbol-value)
  • defvar,defparameter
  • if,cond
  • and,or
  • eval
  • defun,defmacro
  • lambda
  • let,let*
  • do,do*
  • destructuring-bind
  • macroexpand
  • macroexpand-1
  • intern
  • symbol-name
  • symbol-value
  • symbol-function
  • macro-function
  • gensym
  • values
  • values-list
  • =,/=,eq,equal
  • <,<=
  • >,>=
  • not

The Bind-Case Macro

So I’m working on a compiler that compiles Lisp-like code (half lisp half scheme) down to AS2 code. The first thing I had to do was convert the code into cps-style which required that I walk the code structure and manipulate the code. After trying a few different methods I wound up creating the BIND-CASE macro which combines the case/cond statement with a destructuring-bind. It winds up working like this:


(bind-case o
           ((=defun name args &rest body)
            ;the =defun makes sure that
            ;the value in that position is DEFUN
            (print "It's a defun statement"))
              
                          
           (((method &rest args) &rest rest)
            (print "It's some non-defun function call"))
  
           (otherwise
            ;the otherwise is nothing other than
            ;a bind to a single variable called OTHERWISE
            (print "it's something else")))

The macro takes the first argument and tries to bind it to the forms listed in the macro. It tries them in order and if one succeeds then it evaluates the body of that test, inside the body all of the variables from the form are available. Also any symbol that begins with an = requires that the value in that position is equal to the symbol name in that slot (without the = of course).

This macro wound up being quite useful and was way cleaner than the previous method of using DEFMETHOD and nested TYPECASE statements.

Anyway, without further adieu here’s the code. Let me know what you think or if you have any ideas to make it more useful, or if there was something that already did this that I totally overlooked.


(defun starts-with-= (a)
  (and (symbolp a)
       (eq (char (symbol-name a) 0) #\=)))
 
(defun remove-= (a)
  (intern (subseq (symbol-name a) 1)))
 
(defun convert-dbind (a)
  (let (match)
    (labels ((fn (v)
                 (typecase v
                       (cons
                        (cons (fn (car v)) (fn (cdr v))))
                       (otherwise
                        (if (starts-with-= v)
                            (let ((erv (remove-= v)))
                              (push `(eq ,erv ',erv) match)
                              erv)
                          v)))))
      (values (fn a) match))))
 
(defmacro bind-case (val &rest args)
  (let ((rtn (gensym)))
    `(catch ',rtn
       (or
        ,@(mapcar #'(lambda (a)
                      (destructuring-bind (db &rest body) a
                        (multiple-value-bind (b match)
                                               (convert-dbind db)
                          `(ignore-errors
                            (destructuring-bind ,b ,val
                              (and ,@match
                                   (throw ',rtn
                                        (progn ,@body))))))))
            args)))))

Stack Trampoline in Actionscript

So I’m rewriting this post because I got off on a tangent before, so here’s the deal.

Clearly state the problem: I work in Actionscript a ton. I love recursion. Flash will only let you recurse 256 levels before crashing. We need a way to run code recursively as deep as we need to without crashing the player and without filling up the call stack. In short we need tail-call optimization.

Tail-call optimization is quite a simple concept.
Look at this code it’s just a really stupid way to add two numbers

function StupidAdder(a,b)
{
    if(b==0) return a;
    return StupidAdder(a+1,b-1);
}
trace(StupidAdder(10,20));

This works fine, unless the second number is over 256 (oh and don’t make the second number negative it won’t work either).
The big problem here is that even though we are calling return Adder(a+1,b-1); Flash still keeps the stack frame for the whole function around even though it’s no longer necessary. The only thing we need to remember is that when we get to the end that we need to return the final value to the trace statement. So anyway I wrote this code that adds two methods to each function you create.


_global.Function.__proto__.TailCall=function()
{
    arguments.unshift(this);
    throw(arguments);
}
_global.Function.__proto__.WithTailCall=function()
{
    arguments.unshift(this);
    var c=arguments;
    var rtn=null;
    while(c)
    {
        try
        {
            rtn=c.shift().apply(null,c);
            c=null;
        }
        catch(v)
        {
            c=v;
        }
    }
    return rtn;
}

This uses a try catch block to pop the stack and then call the next function needed. When a normal value is returned it just gets passed directly to the original requester. Now we can call our StupidAdder function like such.


function StupidAdder(a,b)
{
    if(b==0) return a;
    StupidAdder.TailCall(a+1,b-1);
}
trace(StupidAdder.WithTailCall(10,256));

And there you have it, completely unnecessary in this case, but a nice little gem to have in your back pocket for that one time you want to run a function that recurses 1000 times.

« Previous Entries