Arc Forumnew | comments | leaders | submitlogin
Dynamically building (and calling) functions?
3 points by comatose_kid 6110 days ago | 9 comments
In a data file, I have a list of shapes. As I traverse this list, I would like to call one (or more) routines specific to the type of shape.

For example, for a 'sphere' object, I would want to call 'sphere-intersect' and 'sphere-normal' while I might want to call 'plane-intersect' and 'plane-normal' for a 'plane' object.

Ideally, I'd like to just call 'intersect' with the object and automatically call the appropriate intersection routine (eg, sphere-intersect).

This could be solved by storing the function name within the object description. I'd rather not, since I would then have to modify the format of the data file any time I changed the corresponding function names in the source.

I'm new to lisp-like languages in general, so this may be a basic question, but how would I approach this in arc?



3 points by sacado 6110 days ago | link

You can use one hash table per type of shape (that would be called a class in many other languages :). For example, a hash called sphere and one called plane. Each of these hashes would have an entry whose key is the generic name of the function (intersect, etc.) and whose value would be the implementation of the function for that type.

Thus :

  (= sphere (table))
  (= plane (table))

  (= (sphere 'intersect) (fn (sphere . rest) ...)
  (= (sphere 'normal) (fn (sphere . rest) ...)
  (= (plane '...
Then, you could put all these hashes in another englobing hash, whose keys would be the names of the types and the values their associated table :

  (= classes (table))
  (= (classes 'sphere) sphere)
  (= (classes 'plane) plane)
Finally, if x is your object and (car x) gives you its type, you can call its intersect function this way : (withs (type (car x) class (classes type) function (class 'intersect)) (function x))

If you have parameters, they must be added after x in the last line. Basically, that's it. But there are many other possibilities if you don't like this one for any reason. And anyway, maybe someone else will give you a better one.

Edit : changed circle with sphere

-----

6 points by kennytilton 6110 days ago | link

And once that is working and it starts to get irritating, you are ready for mac, the anti-irritant. create a file called clos.arc and:

  (mac defmethod (gf-name ((self type)) . body)
     (w/uniq (class)
       `(let ,class (ensure-class ',type)
           (= (,class ',gf-name)
              (fn (self) ,@body)))))
...or something in that general ballpark, I just banged that in over a neat Johnny Walker.

-----

3 points by kennytilton 6110 days ago | link

I would like to emphasize the bit "once that is working"... it can be a bit much to get the whole mechanism working at the same time as developing the macro. So get the flow going from a text file being read in to the correct function being called for that shape and maybe do a few shapes until you are sure the beast is about right, then do the macrology. Especially if a macro is in a separate file (as it should be) and you are not reloading the whole shebang each time you run, you'll go nuts running old code even after changing the macro if you just reload the macro-defining file. Add to that the fact that the mechanism itself will be a moving target... well, I like to divide and conquer these deals.

-----

2 points by comatose_kid 6110 days ago | link

Thanks Kenny and Sacado. I'll try to digest your code/ideas later this evening.

-----

3 points by drcode 6110 days ago | link

at 6AM? For shame, Kenny :)

-----

2 points by kennytilton 6110 days ago | link

You don't like a little nightcap before turning in?

-----

1 point by sjs 6109 days ago | link

As long as he wasn't just waking up... ;-)

-----

2 points by greatness 6110 days ago | link

instead of using (car x) to store the object type is there a way to use annotate to do it? I'm kind of confused on how that works.

-----

1 point by sacado 6110 days ago | link

Yes annotate is the arcish way to do so I think. Just do (= x (annotate x 'sphere)) and after that (type x) would give you what you want.

-----