[e-lang] Protocol tests are necessary (was Re: Rename Guard,
ValueGuard)
Kevin Reid
kpreid at attglobal.net
Sat Sep 3 09:01:11 EDT 2005
On Sep 3, 2005, at 0:59, Dean Tribble wrote:
> I'm confused about what "ExtendedGuards" are. If they are the guards
> that
> add the infrequently-used operator overloadings,
Yes.
> On Fri, 2 Sep 2005, Kevin Reid wrote:
>> On Sep 2, 2005, at 8:10, Mark Miller wrote:
>>> Kevin Reid wrote:
>>>> I haven't thought of a decent name for Guard, though; just
>>>> ExtendedGuard, SugaredGuard, FancyGuard, etc., which might be true
>>>> but
>>
>> However, I think it will eventually be important to preserve the
>> guard's ability to override those operations to be more than that; for
>> example, the guard resulting from this expression can be much more
>> efficient if IsAny (previously discussed for replacing the ==-pattern)
>> can implement | to define a new IsAny guard instead of an or-guard:
>>
>> accum none for item :notNull in dataSource { _ | IsAny[item] }
>
> This looks completely unfamiliar to me. Can you explain?
Context:
'none' is a (hypothetical) guard which accepts no values.
'accum' is a pragma-enabled syntax for accumulating/reducing/folding.
accum INITIAL-VALUE LOOP-EXPR { _ RIGHT-SIDE-OF-CALL-EXPR }
In this case, it is sugar for, approximately,
{
var result := none
for item :notNull in dataSource { item := item | IsAny[item] }
result
}
Functionally,
reduce(def _(a, b) { return a | b },
none,
filter(notNull, dataSource))
If dataSource were, say, [0, 1, null, -1], this would yield none |
IsAny[0] | IsAny[1] | IsAny[-1].
What I was trying to point out:
If the guard's | is custom, then this can yield the O(1) guard
IsAny[0, 1, -1]
whereas if the only way to request compositions of guards does not ask
the guards themselves, the result will be
any[none, IsAny[0], IsAny[1], IsAny[-1]]
which is an O(N) test in the size of dataSource.
>> This requires a well-defined way to ask an object if it is an
>> ExtendedGuard. I have some further thoughts on how to implement this
>> type of test which I hope to post soon.
>
> A general principle in OO is that any such manual type test is a "bad
> smell in code", and signifies a bad design pattern. There are always
> exceptions, but that's a pretty good heuristic. If we see a lot of
> type
> testing, that means our type hierarchy is bad because we are unable to
> get
> polymorphism via message dispatch.
In order to use 'plain' messages in this way, the client and the
polymorphic target must have an agreed set of messages to support. The
solution of this form is to make ExtendedGuard the protocol for all
guards, so that any object which recieves a guard knows that it
supports or/1 (as in my examples above) and will get either typical or
custom behavior.
However, in a *distributed* system, this is insufficient, because
global agreement is not feasible. What if the original ExtendedGuard
doesn't cover some operation we want later?
(In a local system, the operation would be added to all (typically one)
ExtendedGuard implementations and its callers modified to use it when
appropriate.)
I'll switch to a better example:
We have the basic Slot protocol, and Lamport Slots
(org.erights.e.elib.slot.makeLamportSlot). Clearly, Lamport slots are
not the only kind of extended slot one might want - and other
extensions for change notification (or a New, Improved! version of
EverReporter/EverReactor) might even happen to use some of the same
message names, so __respondsTo is not feasible.
Use cases for testing if a slot is a Lamport slot:
* GUI inspector. Show the value of the slot, and request updates if
possible.
* It's either a Lamport slot or $SPECIALIZED_OR_IMPROVED_PROTOCOL
slot, and we want to use the best protocol it supports, whatever that
is.
My current hypothesis is that for E to be usable for the large
heterogenous distributed systems it was designed for, it is *NECESSARY*
to have a well-defined "do you support this protocol" query protocol.
Your thoughts?
--
Kevin Reid <http://homepage.mac.com/kpreid/>
More information about the e-lang
mailing list