One test of dynamic languages is to try and set attribute values on an object dynamically (e.g., without knowing until runtime which attributes need to be set). Below, we compare a simple example in Python, a fairly dynamic language, to Factor:
class Foo(object): a, b, c = None, None, None obj = Foo() d = { "a" : 1, "b" : 2 } obj.a = d.get("a") obj.b = d.get("b") obj.c = d.get("c") print obj.a # 1 print obj.b # 2 print obj.c # None
We might directly translate the previous example to Factor code, using slot accessors to set attributes on the tuple instance:
TUPLE: foo a b c ; foo new H{ { "a" 1 } { "b" 2 } } { [ "a" swap at >>a ] [ "b" swap at >>b ] [ "c" swap at >>c ] } cleave [ a>> . ] [ b>> . ] [ c>> . ] tri
But, it's much better if you don't need to know ahead of time which attributes a class has (i.e., needing to write code to handle each attribute). In Python, you might instead set each value dynamically using the setattr
function:
for name, value in d.items(): setattr(obj, name, value)
We can use the set-slot-named word from the db.types vocabulary to do the same from Factor:
USING: assocs db.types fry kernel ; : set-slots ( assoc obj -- ) '[ swap _ set-slot-named ] assoc-each ;
Note: theset-slot-named
word (and theoffset-of-slot
word that it uses) should probably be moved to theslots
vocabulary.
We can simplify the previous example using our newly created set-slots
word and try it in the Factor listener:
( scratchpad ) TUPLE: foo a b c ; ( scratchpad ) foo new ( scratchpad ) H{ { "a" 1 } { "b" 2 } } over set-slots . T{ foo { a 1 } { b 2 } }
Very nice! I did something similar, a while ago.
ReplyDeleteprobably slower since it uses mirror's introspection.
http://paste.factorcode.org/paste?id=1068