[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