[Python-3000] Adaptation vs. Generic Functions

Guido van Rossum guido at python.org
Sat Apr 8 17:29:30 CEST 2006


On 4/8/06, Phillip J. Eby <pje at telecommunity.com> wrote:
> Naturally, if your goals are more modest, dealing only with actual
> arguments, no expressions, no operators other than 'isinstance()', no
> ability to apply boolean logic to the conditions (e.g. "isinstance(arg1,A)
> and isinstance(arg1,B)", or perhaps "not isinstance(arg1,C)!"), then the
> logic for an interpreter is indeed much simpler.  In that case, you can
> just use a series of dictionaries that each argument is checked against,
> one at a time, and you can build those dictionaries in a straightforward
> way at registration time.

Yes, I'd like to explore this approach first: (a) Java and C++ seem to
get quite a bit of mileage out of it; (b) I'm not sure that *all*
if/else tests at the top of a function should be frowned upon; the
ones that do type tests are usually the most suspect.

Of course, there are applications for more general predicates (like a
dungeons&dragons game dispatcher) but to me they all seem a bit
specialized to me.

> In that approach, the lookup loop could look something like:
>
>      reg = self.root_registry
>      for arg in args:
>          for cls in type(arg).__mro__:   # not exactly, but sort of
>              if cls in reg:
>                  reg = reg[cls]
>                  break
>          else:
>              raise NoMatch  # (or fall back to default)
>
>      # reg is now a function or a placeholder indicating ambiguity

I was thinking of something like this (nested dicts) as a strategy to
deal with hundreds of registered methods. But I'm not sure if it
matters in practice give that this code is only executed once to fill
up the cache. I see more timing tests in my future... :-)

> You wouldn't actually use __mro__, in order to avoid the unstable dominance
> hierarchy problem, but you get the gist.  If you use RuleDispatch and
> restrict what operations you use, you'll actually get almost exactly the
> above; it's just that RuleDispatch may not evaluate the args in strictly
> left-to-right order, depending on how "good" an argument is for
> dispatching.  (RuleDispatch evaluates the "goodness" of expressions (such
> as arguments) by how well they fan out and flatten the dispatch tree, so it
> may decide that the last argument is in fact a better thing to check first.
>
> This approach of course has more hash table lookups than your approach, so
> these are all tradeoffs to be considered, and more importantly,
> measured.  But in general I tend to see this space through the lens of
> "arbitrary boolean expressions" and thus may occasionally intuit wrong
> answers for the more limited scope you're contemplating here.  Actually, I
> keep feeling like you're "cheating" because you can get away with so little
> code -- and I keep having to remind myself that it's because there are so
> many things that the cached type tuple approach cannot.  (The approach
> which you are using, and which other folks wrote papers about, prior to the
> Chambers & Chen paper on using dispatch trees to handle arbitrary predicates.)

I'm not sure if it's worth the complexity. Also, responding to stuff I
snipped that you wrote about access to ASTs is incredibly far in the
future; it's too close to macros or extensible syntax, which I am
explicitly ruling out from Python 3000 (I'm saying this so we don't
have to engage in an endless discussion).

> Anyway, I just got home from a 6+ hour flight, and I'm probably not being
> very coherent right now, so I'm going to go get some sleep.  :)

And I have a 4-year-old next to me playing Elmo so I'm going to give
my family some time! :-)

--
--Guido van Rossum (home page: http://www.python.org/~guido/)


More information about the Python-3000 mailing list