[Python-ideas] Does jargon make learning more difficult?

Steven D'Aprano steve at pearwood.info
Thu Aug 23 07:11:16 EDT 2018


On Wed, Aug 22, 2018 at 06:28:45PM -0500, Abe Dillon wrote:

[Steve -- that's me]
> > But whatever it is, do you still think it is obvious that people
> > will recognise "None" to mean a function without having to backtrack?
> 
> 
> It's not clear what you mean by backtracking at this point.

Yes, I accept that's not clear. Sorry.

What I mean is that moment of having to reinterpret what you're reading. 
I start to read code, see that its assigning None to a parameter, and 
then a moment later have to re-interpret what we just read: None is not 
the argument, but the body of the function which is the argument.

In linguistics that sort of thing is called a "garden path sentence" and 
research demonstrates readers take longer to comprehend them than 
sentences which don't require backtracking (re-interpretation).

https://en.wikipedia.org/wiki/Garden-path_sentence

Sometimes that's a good thing, if you're making a joke. But in general, 
they're not great for readability. Since your argument hinges on 
readability, that's a problem.


> cleanup=None
> with() requires no more backtracking than any other compound expression.
> cleanup=children.oldest().room doesn't tell you what kind of object is
> being assigned to cleanup. Is it a function? Who knows? Even if you know
> what
> 'children' is and what the 'oldest' method returns, you still don't know
> what's being assigned to cleanup without reading the entire expression.

But at no point in reading "children.oldest().room" do you have to go 
backwards and re-intepret what you thought you saw. Even if the 
expression involves right-associative operators:

    children ** oldest ** room

the worst that you have to do is defer thinking about children (push it 
onto the stack of short-term memory) until after you've thought about 
oldest**room.

Now human memory has a very shallow stack. We struggle to hold more than 
approximately "seven plus or minus two" items in memory at a time. And 
of course people often forget that ** is right-associative (I know I 
do). But syntactically, there's no mental backtracking required.

I'm not claiming that your suggested syntax is impossible in a LL(1) 
grammar like Python. I don't know. But I'm responding to your earlier 
assertion that it ought to always be obvious in context that you are 
looking at the body of a function, before you see the "with" keyword. As 
evidence for this assertion, you give examples where it is obvious:

    sort(sequence, by=card.suit with card)

Sure, any English speaker familiar with the English idiom "sort by ..." 
can probably guess the semantics. That's great.

But its not representative. We don't always have the luxury of 
expressions which read like English phrases:

    threading.Thread(target=None ...

looks like the target is None, not a function, and we don't realise its 
not until we keep reading and learn at the very end of the expression 
that everything we saw before that point was part of the function body.

It's great for English speakers that "sort by" appears in our code, but 
have a thought for those to whom it might as well be "pteg xb". Python 
is not just a language for English speakers, and if we're going to claim 
a readability advantage, we ought to at least acknowledge that not 
everyone will have that advantage, and not exaggerate the magnitude of 
that advantage by using words like "almost always".


> There has never been a guarantee that expressions evaluate left to right
> simply by virtue of the fact that an order of operations exists.

That's fine, because I never said they did. It would be pretty foolish 
of me if I did, given that exponentiation is right-associative, and that 
we have comprehensions and ternary if expressions.


> > sm = difflib.SequenceMatcher(isjunk=x == ' ' with x, ...)
> > The expression x==' ' doesn't look like a function to me.
> 
> 
> You don't think that perhaps that's because it's brand new syntax?
> x=='' doesn't look like a function because it's not a function.

I know that. But you stated:

    "I was trying to say that the context almost always gives
    away that the reader should expect a function."

The difflib example is a real, not made up, example that goes against 
that. The context "isjunk" sounds like it might be a flag, not a 
function, and the code x==' ' supports that interpretation right up to 
the moment you read "with x" part, at which point you have to 
re-interpret what you've been reading.


> You could play the same game with literally any compound expression:
> 
> >>> func = ", ".join
> 
> ", " doesn't look like a function to me!

Indeed. I don't deny that there are expressions where if you truncate at 
a certain point, the code up to that point looks like a valid (sub-)
expression of a different type:

    spam ∆ eggs

If you truncate just before the ∆ you get a valid subexpression "spam" 
which may not be the same as the expression "spam ∆ eggs". But there 
aren't many places in Python where after truncating just before ∆, you 
interpret "spam" one way, but if you truncate after the ∆, you intepret 
"spam" a different way. Normally spam is spam no matter what follows 
it. In your earlier example ", " is a string, regardless of whether you 
have read up to the dot or not.

Of course we could do this (LL(1) parser permitting) but the point I'm 
making is that this isn't a small change, and I don't think it will have 
the benefit you believe it will. The contrary: I think it will hurt 
readability, not help it.

I think the benefit of moving the body of the function to the front is 
less than you think, and the cost of moving the syntax which 
distinguishes it as a function to the end greater than you think.

I don't have objective evidence for these opinions, but I've tried as 
best as I am able to give the reasons why I believe this, and not just 
make it an assertion.


> If you honestly don't understand my position at all. [...]
> then I guess I've never met anyone quite like you.

I'm a unique and special snowflake.

https://i.imgur.com/W3ljlBg.jpg


> I don't
> know how to communicate my point of view any better than I already have.

I understand your position. I just disagree with it. 



> [Steven D'Aprano]
> > You are judging that from the perspective of someone whose native
> > language makes it easy to say "sorted by foo" (for some value of foo).
> 
> This argument is such a tiring distraction. Please stop. If it's all just
> random symbols to some non-english speaker, then
> It doesn't matter either way to them.

When you are claiming an advantage, if that advantage doesn't actually 
apply, then its not an advantage, is it? I'm not going to stop using a 
valid argument just because you don't like it.


> [Steven D'Aprano]
> > We shouldn't judge syntax proposals just on the cases that are carefully
> > chosen to showcase them at their best. Especially not trivial cases.
> 
> We can judge it by examining cases where it might be problematic, but
> there's no way to keep people from abusing
> coding constructs to produce unreadable code, so just throwing out random
> chunks of code like
> 
> a.b[c:d]-e**f(g, h=i) + {j & k, l*(m-n(o,p))} with e, k
>
> then saying "looks bad to me" offers no insight into the pros and cons of
> the proposal.

Good thing I didn't do anything like that.

Abe, you are attacking a strawman. I didn't give made-up deliberately 
awful code. I took existing code from the standard library, and 
translated it to your proposed syntax. These "random chunks of code" are 
a non-issue. I never suggested examples like that, and I haven't seen 
anyone else do so either.



-- 
Steve


More information about the Python-ideas mailing list