atdef VAR=EXPR [, VAR=EXPR]*
Such a statement would readily cover the speed enhancement,
early-binding and shared state use cases for the default argument hack
Doing things this way however removes one of the chief benefits of the inject statement,
the ability to create multiple versions of the same function with different sets of shared data.
You earlier gave an example similar to this as an example of what the syntax
under your proposal would look like.
def example(arg):
"""Record and return arguments seen"""
atdef cache=set()
#do something
cache.add(arg)
return arg
under proposal 4 (inject as full blown function, usable like any decorator) it would look like this instead
@inject(cache = set())
def example(arg):
"""Record and return arguments seen"""
#do something
cache.add(arg)
return arg
but what if, later, you decided you needed 10 different 'example' functions each with its own cache as well
as the ability to make more.
under your proposal we would have to make extensive changes.
turning the code into
def make_example():
def example(arg):
"""Record and return arguments seen"""
#do something
cache.add(arg)
return arg
return example
example_list = [make_example() for i in range(10)]
this code is rather difficult to read and it is difficult at first glance to figure out what is actually happening
under proposal 4 the result would be much simpler. we could just remove the @inject and put that on in the
list comprehension, like so.
def _example_func(arg):
"""Record and return arguments seen"""
#do something
cache.add(arg)
return arg
example_list = [inject(cache=set())( _example_func) for i in range(10)]
make_example = lambda: inject(cache=set())( _example_func)
this is IMO far easier to read and understand.
Furthermore it gives the added benefit in that you can chose to run 'example' so that it uses
a true global variable, instead of an injected one.
--Alex