I have written this up at
http://www.chaos.org.uk/~eddy/dev/toy/python2.html
and thence-linked locations. [The page also describes a fix to grail
0.5 which may be needed when reading the associated .py files.]
My proposal contains enough slack to allow for the following things
(among others) that some folk seem to want:
* namespaces that you can't modify once they have been initialised
* namespaces in which attribute-modification is type-checked
* hybrids of those with assorted degrees of control
* certain tools the functional programmers crave, notably a truly
faithful implementation of currie()
* some of the truly whacky `metaclass' proposals
and, of course, the stuff we're used to (notably class, albeit demoted
to a built-in) with minimal perturbation. The changes are, IMO,
straightforward and pythonic: they reduce the number of special
attributes the interpreter is obliged to know about and do *not* depend
on strange hacks or anomalies. They do perturb syntax.
I intend to push this proposal during IPC8. I would greatly appreciate
constructive comments in advance, if only to temper my enthusiasm ;^}
Eddy.
--
Those who have seen versions of my pages prior to 2000/Jan/17 should
note that I have simplified and clarified them somewhat of late.
I believe I have eliminated all risk of exploding heads. YMMV.
Unfortunately, unless I'm missing something, this is only true when you
know the call-signature of the function you are packaging. Without safe
tunnels, I can see no way of handling even the simple case of `provide
the first argument to a function given no knowledge of how many
arguments the caller is going to give it': the currie()d result has to
use *args in its argument-list, yet we need arguments which supply it
with the function to call and the given first argument; these have to
appear before the *args (unless something has changed and no-one has
told me), consequently they will be over-ridden by the first few
arguments passed in by the caller of the constructed function:
def currieone(func, one):
def result(*args, f=func, o=one):
return apply(f, (o,) + args)
return result
as safe tunnels would put it; if f and o precede *args (which they
currently must, as I understand it), the result is doomed because
lambda f=func, o=one, *args: apply(f, (o,) + args)
called with args (a, b, c) would bind a in as f (over-riding the default
supplied, func), b as o (ditto, one), leaving args = (c,), so it would
attempt to call a(b, c) where func(one, a, b, c) was our intent.
Can you show me a piece of valid python (using lambdas or otherwise)
which achieves this effect ?
Granted, it can all be done (one of the first toys I built in python) as
a class ... but I need stuff like it before I can implement class ...
and we get so much more out of liberalising the position of *args and
**kwds relative to the name=value parameters. Like, for instance, the
ability to have a function take arbitrarily many positional arguments
along with some keyword-arguments without the former and the latter
getting tangled up with one another - the things I call generators
commonly use (*bases, dict=None, meth=None, **what) ... unless dict and
meth keywords are used when the function is invoked, the function will
see them as None, no matter how many arguments are passed.
And, just for clarity, I don't particularly want this for the functional
tools (cute though I find them, fun though I find it to build them, and
useful though they are as sample things to check a system is powerful
enough to support) so much as for the expressive clarity of, for
instance,
def join(*strings, glue=' '):
return string.joinfields(strings, glue)
invokable as join('hello', 'there', 'all', 'you', 'pythoneers') or, if
different padding is wanted, join('in', "Tim's", 'style', glue='-'),
without having to put [] around the sequence of strings that aren't the
keyword-supplied glue.
Eddy.
Jeremy
Sigh. See Viper. Modules, packages, classes, instance,
raw objects, local scopes .. and some other scopes .. are all
'unified' in two ways:
1) Support for an 'environment' protocol supporting
unqualified name lookup
2) Support for qualified lookup [x.y]
In Viper, 'environment' is a fundamental abstraction
of the execution environment: there's an actual class interface
abstraction
for it. Qualified lookup is supported by ad-hoc polymorphism, more or
less
encapsulated in the 'getattr' 'setattr' 'hasattr' functions.
> * namespaces that you can't modify once they have been initialised
> * namespaces in which attribute-modification is type-checked
As you can see, in Viper, there are _two_ dual concepts
of namespaces. In both cases, the fundamental implementation involves
dictionaries, plus extra structure.
> * hybrids of those with assorted degrees of control
> * certain tools the functional programmers crave, notably a truly
> faithful implementation of currie()
not required: python lambdas subsume what can be done with
currying.
> * some of the truly whacky `metaclass' proposals
There are plenty of them :-)
See Viper. It already supports generic types, eg lists of
X for any type X. This is done fairly easily by making
ListOf a class with one attribute 'type'
ListOf(X) an instance with type = X
and that instance the type of a raw object with a normal list
as it's only attribute. Methods of the ListOf class have
two objects: the type object, (ListOf(X)), and the list instance (self).
These are both bound by the two stage lookup, so that a method
like
def append(typeobj, self, value):
if type(value) is not typeobj.type:
raise TypeError
else: self.list.append(value)
> I intend to push this proposal during IPC8. I would greatly appreciate
> constructive comments in advance, if only to temper my enthusiasm ;^}
The lookup mechanism in Viper is very powerful.
It is not necessarily 'right'. It might be useful to examine
a working implementation? After all, it more or less models
what C Python 1.5.2 does now, and just relaxes some restrictions
on what a type object can be.
[Viper raw objects can also be metamorphic -- that is,
change type dynamically -- the type is 'just another attribute']
--
John (Max) Skaller, mailto:ska...@maxtal.com.au
10/1 Toxteth Rd Glebe NSW 2037 Australia voice: 61-2-9660-0850
download: ftp://ftp.cs.usyd.edu/au/jskaller
> Can you show me a piece of valid python (using lambdas or otherwise)
> which achieves this effect ?
It hadn't occured to me you wouldn't know the arguments.
I always know the positional arguments (not necessarily the
optional ones) -- there's no other way to call a function :-)
--
John (Max) Skaller, mailto:ska...@maxtal.com.au
10/1 Toxteth Rd Glebe NSW 2037 Australia voice: 61-2-9660-0850
homepage: http://www.maxtal.com.au/~skaller
download: ftp://ftp.cs.usyd.edu/au/jskaller
> I always know the positional arguments (not necessarily the
> optional ones) -- there's no other way to call a function :-)
In python, some functions take `as many arguments as the user choses to
supply'. I may wish to take such a function, bind in an initial
sub-sequence of those arguments, yet still allow the result's callers to
supply arbitrarily many following.
An implementation of currie which can't cope with *args isn't pythonic.
Eddy.
--
Liberty's a glorious feast.