[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