[Python-ideas] Quick idea: defining variables from functions that take the variable name

Steven D'Aprano steve at pearwood.info
Wed Jun 1 14:22:16 EDT 2016


On Tue, May 31, 2016 at 02:08:08PM -0400, Émanuel Barry wrote:

> I think that the idea of implicit call or magically inserting items at 
> the front (or any arbitrary position, for that matter) isn't going to 
> work. For it to work, we need to address cases such as those:

I thought I had.


> x -> foo("bar")("baz") # is this foo("x", "bar")("baz") or foo("bar")("x", "baz") ?

Syntax error.

> x -> foo() # is this foo("x") or foo()("x") ?

foo('x')

> x -> foo # hmm, are we doing foo("x") here, or should this be a syntax error?

Syntax error.


> x -> foo(?, "bar") # this is foo("x", "bar")
> x -> foo(?) # foo("x")
> x -> foo(?, "bar", ?) # is this foo("x", "bar", "x") or a syntax error?
> 
> This looks fine. What about this, though?

Not too keen on a placeholder, mostly because I think YAGNI. Until 
somebody points out some real-world use-cases where the callable expects 
the name to be given in something other than the first position, I'm not 
too worried about supporting arbitrary positions. All the actual 
use-cases I've seen have the name as the first argument.


> a, b, c -> foo(?) # probably foo(("a", "b", "c")), right?
> a, b, c -> foo(?, "bar", ?, "baz", ?) # is this foo("a", "bar",  "b", "baz", "c") or a syntax error?

Another YAGNI.


> In the face of ambiguity, refuse the temptation to guess and throw a 
> syntax error in all ambiguous cases. Oh wait, that's how Python works 
> right now - every case is ambiguous for that.

Under my proposal, there's no ambiguity. Any ambiguous cases will be a 
syntax error.

The rule is simple: the right hand side must be a "simple" expression 
that ends with being called, similar to the rules for @decorator syntax. 
And then the left hand name is substituted for the first parameter.

If you don't like that, okay, but I don't think there's any ambiguity, 
any more than:

@functools.wraps(func)
def function(x, y):
    ...

is ambiguous.


> The main point is that 
> there's no way this is going to fly if there isn't an explicit way to 
> declare the implicitness

I'm afraid I don't know what that means.


> - at that point I'd rather hand-roll my own 
> function (which I can probably customize to fit the needs of my 
> module). Something like:
> 
> def set_global(func, name, *args, **kwargs):
>     globals()[name] = func(name, *args, **kwargs)

What makes you think the variables are always globals?


> In fact, I would go for some decorator magic (I love decorators):
> 
> def call_with_name(func):
>     fn, args, kwargs = func()
>     return fn(func.__name__, *args, **kwargs)
> 
> @call_with_name
> def x():
>     return namedtuple, (fields,), {}
> 
> There you go, and you only typed the name once, in the function definition. Magic enough for you?

Are you suggesting this actually works? When I try it, I get:

NameError: name 'fields' is not defined

so I think there's something you've forgotten. Besides, I *really* don't 
think that:

@call_with_name
def T:
    return Typevar, (), {}


is an improvement over:

T = Typevar('T')

but feel free to use it in your own code.



> I love syntactic sugar and Python's magic, and this would be just fine 
> for me. And, as everyone knows, code is read much more often than it 
> is written. As such,
> 
> x -> foo()
> 
> is easier to write, but much harder to read

Harder to read than the decorator you give above?

I bet that if Python didn't have a multiplication operator, and somebody 
suggested adding * for multiplication, there would be a flood of 
rejections saying

"Oh sure, 10*x is easier to write, but it's much harder to read 
than x+x+x+x+x+x+x+x+x+x. * is too confusing and magical."

Heaven help us if somebody suggested ** for exponentiation...

*wink*


> turning the fun of 
> writing something that works using compiler magic into a maintenance 
> hell.

Maintenance hell. Right. Because that's not even slightly a gross 
exaggeration.


[...]
> I also think that adding new syntax might become an attractive 
> nuisance, where people use it all the time everywhere 

Yeah, I can see it now. 

y -> x + 1  # Oh wait, that's a syntax error
print(x -> 'Hello world!')  # Oh, that's a syntax error too

I cannot imagine how you think people will be able to use this syntax 
"all the time everywhere". If anything, this syntax could be rejected as 
being too limited and not useful enough, rather than because it can be 
applied everywhere.



-- 
Steve


More information about the Python-ideas mailing list