Why not allow empty code blocks?

Steven D'Aprano steve at pearwood.info
Sun Jul 31 11:31:42 EDT 2016


On Sun, 31 Jul 2016 08:18 pm, BartC wrote:

> On 31/07/2016 03:10, Steven D'Aprano wrote:
>> On Sun, 31 Jul 2016 04:46 am, BartC wrote:
> 
>>> No named loop variable to invent, create, maintain, and destroy. No
>>> range object to create, destroy etc. If you're looking for ways for a
>>> language to be more efficient, then why disregard this possibility?
>>
>> Who says I've disregarded it? Just because I've concluded that the
>> benefit fails to outweigh the costs doesn't mean I didn't think about it.
> 
> The costs are near zero: 

And the benefits even nearer to zero.

Our discussion about this topic has probably cost more time and energy than
this feature would save in a hundred years of use.


> at minimum, a syntactic construct such as: 
> 
>   repeat N:
> 
> that expands to:
> 
>   for _ in range(N):
> 
> The benefit is not so much performance, but being able to express
> something very easily and quickly.

I can express `for i in range(N)` very easily and quickly. It is the One
Obvious Way to do the job. The number of keystrokes is not excessive. I
don't have to think about whether I should use this or `repeat N`. I don't
have to stop and think "If I choose repeat N, will I have to change my mind
in the future?"

As Henry Ford said, you can have any colour you like so long as its black.

There is value in a minimalist syntax. Every syntactic feature has to pull
its weight. `repeat N` doesn't pull its weight. That's the value judgement
expressed by Python. Other languages are free to make other value
judgements.



>> (2) And even if it is significant, surely that's something that a keyhole
>> optimizer can detect without requiring the user to care one iota about
>> the difference? And indeed, that's EXACTLY what Python 3.6 (and probably
>> older versions) does: it optimizes out the comparison, and
>> unconditionally loops:
>>
> 
>> py> dis("while True: spam()")
>>   1           0 SETUP_LOOP              10 (to 12)
>>         >>    2 LOAD_NAME                0 (spam)
>>               4 CALL_FUNCTION            0 (0 positional, 0 keyword pair)
>>               6 POP_TOP
>>               8 JUMP_ABSOLUTE            2
>>              10 POP_BLOCK
>>         >>   12 LOAD_CONST               0 (None)
>>              14 RETURN_VALUE
> 
> In Python 2.7, the True value has be tested each time.

I'm not talking about 2.7. 2.7 is old and on its way out. It is hobbled by
the requirement of backwards compatibility.

Since you have a user-base of exactly one person, yourself, you don't have
to care about backwards compatibility. You can change your mind and remove
features or change them any time you like. Python cannot. For historical
reasons, there are probably a million lines of code out there which assume
that True and False are ordinary variables that may be assigned to. Even if
it is only a thousand, or a hundred, we still could not change that in the
2.x series. It's only in 3.x that we can make True and False constants.


But in 2.7, you can write:

    while 1:

or even:

    while "forever and ever, never stopping until the sun goes out":

to get the same effect.



[...]
>>> But dedicated forms (even if they just map to 'while' or 'for') wouldn't
>>> hurt. Syntax is free after all, and it's about expressing exactly what
>>> you mean.
>>
>> Syntax is not free!
>>
>> Syntax requires more code in the compiler. Somebody has to write it,
>> somebody has to maintain it, somebody has to test it, somebody has to
>> document it.
> 
> For language implementations, dedicated syntax is by far the easiest
> thing to code. Far easier that trying to detect certain patterns in the
> code later on.

*shrug*

The whole point of an optimizing compiler is that you don't have to detect
patterns yourself. The compiler does it. There's a whole science to writing
optimizing compilers these days, and they don't do it by hard-coding
dedicated syntax for each thing you want to optimize. That's very 1970s.


>> Every little feature increases the size of the compiler, both the source
>> and binary, and increases the chances of compiler bugs.
> 
> Support for dedicated endless loops is around 20 lines in my compiler:
> 
> http://pastebin.com/wXXVQFkJ
> 
> (Plus 3 or 4 more lines distributed elsewhere.)

That's 25 lines that you don't need. Plus of course another 50 or 60 lines
of tests (if you have tests), plus ten or thirty lines of documentation (if
you have documentation), plus a dozen or two discussions on StackOverflow
from people asking whether they should use "repeat forever" or "repeat
while True" (if you had any users, which you don't).

Bart, I'm not putting you down for having no users. But your judgement of
the pros and cons of a feature is biased one way because you only have to
please yourself. Python's philosophy is biased another way because Guido is
a strong (although sometimes a little inconsistent) believer in simplicity
of implementation and design.

And you know what? That's fine. It's *good* that there are language
designers with different ideas of what's valuable. That gives us a rich
eco-system of languages to pick and choose from. Can you imagine if
everyone thought the same way and valued the same things? We have *one*
language, and it would probably be COBOL.



> The first function is to parse the loop. The second to generate code,
> which is more complex because it supports extra loop controls which
> don't exist in Python.
> 
>> There are already
>> situations where compilers are too big (e.g. on embedded devices, or
>> memory- and storage-constrained machines like the RaspberryPy).
> 
> Are you serious? The Pi (even the first one that I've got lying around
> somewhere) has hundreds of MB of memory, a clock speed of 700MHz, and
> storage measured in GB.
> 
> My entire bytecode compiler is less than 0.3MB (and that includes all
> sorts of crap).

If you removed some of the crap maybe you could get it down to 0.1MB and be
able to run it on an embedded device with 200K of memory.

Does your 0.3MB include a library that provides as much functionality as
Python's std lib does? If not, you're comparing chalk and cheese.

The full Python installation is over 100MB and that's really a problem for
some people:

https://mail.python.org/pipermail/python-ideas/2016-July/041230.html

In that same thread, one of the lead Python devs Victor Stinner talks about
some of his work on embedded devices where he has a hard limit of 128MB for
*everything*: boot loader, kernel, OS, applications, etc.

Some years ago, the company I work for did some work for a Highly Praised
calculator manufacturer that was looking to fit a full Linux-based
installation onto a hand-held device. We were literally looking to shave a
few K off applications to get everything to fit. I'm told that after
spending heroic efforts to squeeze everything into the space provided and
still have everything work correctly *and fast*, and *after* having built
tens of thousands of the devices (complete with printed manuals and
packaging), a new manager took over and ordered the project canned and the
devices crushed and turned into landfill.

Capitalism at its finest.



> (Not quite so easy in an existing, established language, but that's
> another matter. But it does sound as though, even if we were discussing
> a totally new language, you still wouldn't be interested in such
> features.)

Not so. I've already told you that I was perfectly happy with Hypertalk,
which takes the opposite philosophy to Python. It has a plethora of syntax,
and is very verbose. I miss it terribly, I loved that language and the IDE
it came with.

But I wouldn't try to put syntax features from it into Python.




-- 
Steven
“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.




More information about the Python-list mailing list