python hack of the day -- "listable" functions

William Tanksley wtanksle at dolphin.openprojects.net
Fri May 14 16:08:41 EDT 1999


On Thu, 13 May 1999 22:50:34 GMT, Stefan Franke wrote:
>On Thu, 13 May 1999 20:15:32 GMT, wtanksle at dolphin.openprojects.net (William
>Tanksley) wrote:

>>On Thu, 13 May 1999 19:50:35 GMT, Stefan Franke wrote:

>>>but that's only syntactic sugar. Imagine an 'operator' |..|, which marks a
>>>sequence argument in an expression and maps the whole expression to it.
>[...]

>>[...] it's a modification of the way a function operates.  In the above 
>>example, we're forcing '*' to operate on the members of the list, 
>> we're not changing the list.  

>I think function application with $ does follow the rewrite rule

>    f(x, y, $[z1, z2, ..., zn], a) ->
>   $[f(x, y, z1, a), f(x, y, z2, a), ..., f(x, y, zn, a)]

Okay, then let x and y be lists.  What is the result of

f($x,$y)?  Is it something like x cross y, or does it have as many
elements as the shortest of x or y (or the longest)?

>I think an Implementation in Python itself is not possible. However, it
>could be done with some minimal support on a meta object protocol level.
>Assume

>1) we had an aditional builtin type 'dollar', so we could write
>>>> x = $[1, 2, 3, 4]
>>>> type(x)
><type 'dollar'>
>>>> x
>$[1, 2, 3, 4]
>>>> 2*x+1
>$[3, 5, 7, 9]
>>>> undollar (x)
>[1, 2, 3, 4]

>2) Python had a hook that allows us to customize function application. On each
>function call - to builtin as well as user functions - the function 'apply' is
>called. Assigning to apply allows us to change the interpreter behaviour
>completely. So we could do

>    __apply__ = apply
>    apply = my_apply

It wouldn't be "apply", really.  But carry on...

>and implement the above rewrite rule (sorry, code not tested  ;-) with :

># Leaving keyword arguments out of consideration
>def my_apply(f, *args):
>    # Look for the first dollared argument, if there is any
>    i=0
>    for arg in args:
>        if type(arg) is types.DollarType:
>            # Dollared argument found at index i
>            seq = undollar(arg)
>            # Build argument sequence for the mapping on seq's elements
>            arg_seq = map (lambda x, args=args, i=i: args[:i] +(x,) +args[i+1:],
>                           seq)
>            # On each f(as) call, the whole my_apply machinery gets applied
>            # recursivley, if there are any following dollared arguments in
>            # args behind index i
>            return $map (lambda as, f=f: f(as), arg_seq)
>        i=i+1
>    else:
>        # Apply f on args with the builtin apply 
>        return __apply__(__apply__, ((f,) +args))

>Of course, each function call in my_apply calls my_apply recursively, but only
>once, since there are no dollared arguments involved.

Now, consider this.

x = o.verb(a,b,c)

You've created a language feature where the action of the verb depends not
on the single object it's attached to, but on EACH of the parts of speech
in its parameter list.

After that change, Python wouldn't be object oriented.  It'd be grammar
oriented.

Let that one sink in for a while.

Ouch.  Has anyone done work on how to do that?  It's polymorphism, but
with the action depending on every parameter rather than just one.

Of course, you didn't mean it that way -- you meant it to just allow
repetition.

>They'll-propably-stone-us-for-using-$-in-Python-even-if-it's-only-an-illustration-ly
>yr's

RUN AWAY!

>Stefan
>PS: I love the abstraction level of these operations. I never had a look at APL,
>J or K before, so I guess I have to.

They're worth it.  May I suggest J?  APL is very nice, but hard to learn
because you have to learn a new way of typing (if you wind up using it
regularly the expressiveness makes it all worthwhile, I'm told).  J is
similar, but entirely ASCII.  K is different, and although it's a
facinating approach it's a bit more of a hybrid with conventional
languages, so it's easy to be sloppy and work the way you've always worked 
(a bad thing when you're learning a new language because it's different).

J also adds some concepts officially which APL only implies, such as a
formal concept of parts of speech (noun, verb, adverb, adjective, gerund,
and so on) or a formal definition for certain formerly meaningless
combinations of functions (called "forks" and "hooks").

-- 
-William "Billy" Tanksley
"But you shall not escape my iambics."
           -- Gaius Valerius Catullus




More information about the Python-list mailing list