Looking at Pauan's implementation of import (http://arclanguage.org/item?id=14707) I was reminded of his comparison of extend[1] and message-passing a couple of months ago (http://arclanguage.org/item?id=14261) and how I considered it bogus. Now that there's an implementation of message-passing, let's redo the comparison[2]: (def clone(x) ; (def clone(p)
(annotate 'heir (obj val (table) ; (object parent p
parent x))) ;
(defcall heir h ; call (fn (k default)
[or rep.h!val._ ; (or self<-k
rep.h!parent._]) ; (self<-parent k default)))
(defset heir(h key value) ; set (fn (k (o v))
(= rep.h!val.key value)) ; (set-attribute child k v))
(extend keys(x) (isa x 'heir) ; keys (fn ()
(keys rep.x!val)) ; (keys child))
(extend vals(x) (isa x 'heir) ; ;; ?? [3]
(vals rep.x!val)) ; ))
As others[4] predicted, message passing does require multiple method signatures, and that's largely why the claimed huge line-count savings have evaporated. Both approaches now seem roughly equivalent. Some scenarios will gain you a few lines on the left; others will save a few on the right. Even the case in the original comparison is gone, making the two sides seem even more similar. It's mostly just moving parens around. (http://arclanguage.org/item?id=14314)I was skeptical at the time partly because there seemed no attempt to make the comparison fair. Here I've tried to make both versions do the same thing as much as possible. There's no need for iso on the left because a default comparison of recursively comparing reps serves us. There's no fill-table because it just works once you have set. There's no each because coerce takes care of it, and because it'd also have to be defined on the right to iterate over the parent. I want to acknowledge: message-passing does provide things extend doesn't. You can hook into an existing type, or a single instance, without needing to create a new type. But this superficial comparison distracted me from the true advantages. I'm adding several new hooks in wart because of Pauan's explorations of message-passing: isa lets me hook into new types, write lets me influence how they're printed at the repl. Just bringing slices to arc is worth the journey. --- If it's down to subjective preferences, would I use message-passing in arc? Since it seems to provide no advantage or hook that I can't reimplement in isolation I'm happier giving each such hook its own top-level def. Collecting overrides for an existing type in one second place (in addition to the original implementation) seems to provide no organizational gains. I think the tie-breaker is coerce. There's no way to nicely override it using message-passing since you could dispatch on either source or destination, and it would be a wart as the only top-level override. I'd rather give up on overriding instances, and embrace extend :) --- [1] The original comparison used wart, but that proved just a distraction. Wart has redundant keyword args for clarity but otherwise looks the same as extend. [2] ..with the same grotesque ascii table :) [3] Pauan, does ar support vals? Or is there no need? [4] rocketnia? Others as well? I can't find it now. I think it came up at least twice. |