[Python-ideas] Quick idea: defining variables from functions that take the variable name
Brendan Barnwell
brenbarn at brenbarn.net
Tue May 31 14:13:30 EDT 2016
On 2016-05-30 20:08, Steven D'Aprano wrote:
> How do you feel about an arrow operator?
>
>
> T -> TypeVar()
> x -> Symbol()
> T -> type(bases, ns)
> Record -> namedtuple(fields)
>
> In general:
>
> name [, name, ...] -> callable(...)
>
> where "callable" is some expression, e.g. a name, a dot lookup, etc.
>
> # okay
> name -> sympy.Symbol()
I don't like this that much, because it looks odd to have the
expression on the right without the argument. The syntax doesn't make
it at all clear how the T gets used on the RHS.
> Using the arrow operator with arbitrary expressions on the
> right will be a SyntaxError:
>
> x -> y + 1
> my_name -> spam*f()
> my_name -> f() or g()
>
> I reject that third example as it is unclear whether both f and g, or
> only f, get the name as first argument.
>
> But this is allowed:
>
> my_name -> f(g()) # like f('my_name', g())
So. . . what exactly will be allowed? Above you said the RHS would be
"a name, a dot lookup, etc.". If you can't do it with at least dot
lookups I don't see much point; you'd definitely want to be able to do
this to create names from method calls. But it could get confusing to
start splitting the expression syntax into portions that are allowed in
this new "name-passing" syntax and portions that aren't.
> The hard case
> -------------
>
> Assignment target(s) is not a plain name.
>
> spam[2].eggs().attr -> Symbol()
>
>
> I'm going to take the cowards way out and just say "we don't allow
> that".
That seems like the best way out. :-) It seems like the main purpose
of this is as a shortcut to create an object with a simple, readable
name. That goal isn't served by trying to assign some complicated
expression.
Anyway, I still have a problem with solutions like this that separate
the name from the expression in which it will be used. It seems crude
to restrict this syntax to cases where the outermost callable takes the
name as its first positional argument only. What if we want to pass the
name by keyword or something? Or what if you want to do `f(g())` as in
your example, but pass the name argument to g instead of f?
Because of that, I'm more inclined towards something that involves a
placeholder in the actual expression (as someone else suggested
elsewhere on this thread). Something like:
Symbol(def x)
An expression could contain at most one "def name" token, and the
result of the entire expression would be assigned to that name.
I acknowledge that this particular syntax isn't ideal, because the "def
x" could be difficult to see in a complicated expression (although
syntax highlighting would mitigate that). The construct could perhaps
be introduced by a keyword to call out its unusual behavior:
assign Symbol(def x)
I'm just making up "assign" right now, not actually saying that's what
should be used. Maybe some existing keyword could be repurposed. The
upshot is that, to my eye, any solution that pulls the "name" argument
out of the expression where it's used is to going to A) be confusing;
and B) painfully restrict the use cases to those where the RHS is a very
simple expression into which the name can be inserted at an
easily-definable place. So I incline towards solutions that "tag" the
name in-place in the expression, rather than pulling it out.
--
Brendan Barnwell
"Do not follow where the path may lead. Go, instead, where there is no
path, and leave a trail."
--author unknown
More information about the Python-ideas
mailing list