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

Steven D'Aprano steve at pearwood.info
Tue May 31 09:22:25 EDT 2016


On Tue, May 31, 2016 at 05:56:11PM +0900, Stephen J. Turnbull wrote:
> Paul Moore writes:
>  > On 31 May 2016 at 04:08, Steven D'Aprano <steve at pearwood.info> wrote:
>  > > How do you feel about an arrow operator?
>  > >
>  > > T -> TypeVar()
>  > > x -> Symbol()
>  > > T -> type(bases, ns)
>  > > Record -> namedtuple(fields)
>  > 
>  > I like this.
> 
> Well, it's cuter than Hello Kitty, what's not to like?  But ...
> 
> It give me no clue what it's supposed to mean.

That's harsh. No clue *at all*?

It shouldn't be so difficult to see an arrow as assignment. Even if you 
can't *guess* what it means, at least it should be easy enough to 
understand and remember once explained. The arrow operator represents a 
value "moving into" a name, or a name becoming a value:

x <- 999  # move 999 into the slot called "x"

x -> 999  # x becomes 999

As you yourself pointed out, R uses <- as the assignment operator (as do 
OCaml, F#, but not Pascal, as it uses := instead). I've seen plenty of 
pseudo-code using <- as the assignment operator, and *lots* of 
whiteboard discussions using arrows in either direction for assignment. 
I've never had somebody claim to be perplexed or confused by what I mean 
if I write `foo -> value`.

So I think there are plenty of clues, even if the arrow points the wrong 
way for R users.

There's another analogy here that will help:

x -> spam()  # copy 'x' to the RHS

I don't expect anyone to intuit what -> does, but I think that it will 
be easy to learn and memorable -- more so than @ for decorators, ^ for 
bitwise xor, or {} for dicts.

Of course Python cannot use <- because it's ambiguous with (less than) 
(unary minus), e.g.: `x<-f()` could mean either `x <- f()` or 
`x < -f()`.


> In math the forward
> arrow is often used to name a function type (including the domain
> preceding the arrow and the codomain following it in the name),
> although what the parentheses and their contents mean, I don't know.
> The codomain type is the value of TypeVar()?  What's that?

I don't think that the average Python programmer is going to be thinking 
of domains and codomains when they see an arrow :-) Do you think that 
was a problem for C++ ?

But if it makes you happy, perhaps => instead :-)


> In Pascal and R, the reverse arrow
> 
>     T <- TypeVar()
> 
> is used to mean assignment (which you could read as "T receives
> TypeVar()", but the implicit argument on the RHS is a double-take for
> me in both syntaxes -- the argument to TypeVar is not optional!

And neither is the `self` argument to methods. But we learn that self is 
implicitly provided as if by magic :-)

Another similar example of magic is decorator syntax:

def decorator(func):
    ...

which again is not optional and gets provided implicitly by the 
interpreter.

The thing is, regardless of whether we use a symbol or a keyword, the 
functionality here is going to be magical. That's its point: it is to 
avoid the need to write the name twice.


> IIRC, we have two syntaxes in Python itself that take the name of an
> identifier and reify it as a string (ie, inject it into a namespace):
> def and class.

Plus:

- import spam
- from module import spam
- for spam in ...
- @decorator
- and of course regular assignment.

So there's a nice mix of keywords and symbols.


> I know you don't think a keyword works for you, but
> either the recently reraised "def <name> = <type-expr>" or perhaps
> "type <name>: <type-expr>" make more sense to me right out of the box.

Don't think of the RHS as necessarily a type expression. Guido has 
already given one other example:

x = sympy.Symbol('x')


This is a proposal to solve the general problem of passing a name from 
the left hand side to the right just prior to doing an assignment, 
regardless of what the purpose of that name is. So "type" is right out: 
the motivating use-case might be TypeVar, but this isn't limited to 
types by any means.

I could probably learn to live with 

def x = sympy.Symbol()

if I really needed to, put it looks strange to use def for defining 
something which isn't necessarily a function. And it's a tad wordy: four 
extra keypresses, in order to avoid three.

But most critically, "def x =" doesn't really suggest copying the "x" 
onto the RHS in any way.


> Another problem is that none of these syntaxes (including the keyword-
> based ones) provides a clue as to whether the type is a distinct type
> or a type alias.

The type will be whatever TypeVar returns. That's no different from the 
status quo `T = TypeVar('T')`.



-- 
Steve


More information about the Python-ideas mailing list