[HN Gopher] Bringing the print statement back
       ___________________________________________________________________
        
       Bringing the print statement back
        
       Author : Myrmornis
       Score  : 95 points
       Date   : 2020-07-14 20:16 UTC (2 hours ago)
        
 (HTM) web link (lwn.net)
 (TXT) w3m dump (lwn.net)
        
       | softwaredoug wrote:
       | Seems to violate "There should be one-- and preferably only one
       | --obvious way to do it."
        
         | open-source-ux wrote:
         | _" There should be one-- and preferably only one --obvious way
         | to do it."_
         | 
         | This principle is often repeated for Python, but does it have
         | any bearing on reality today? With every release of Python (and
         | indeed for many other languages), new features give you even
         | more ways of doing things.
         | 
         | Python is 30 years old - it's no longer the small language it
         | may once have been, but is now chock-full of features. Maybe
         | once there was an "obvious way to do it", but I don't thing
         | this is true today.
        
         | enriquto wrote:
         | > Seems to violate "There should be one-- and preferably only
         | one --obvious way to do it."
         | 
         | Just as representing a vector of numbers as a tuple, a list, a
         | dictionary, a numpy matrix or a numpy array. And don't get me
         | started on multidimensional arrays.
        
         | solox3 wrote:
         | Says the line with two different hyphenating styles.
         | 
         | It's an Easter egg.
        
           | idoh wrote:
           | So pedantic but I love it. For the GP, what you are looking
           | for is them em dash (--) with no spaces around it, because
           | the dash is its own form of punctuation.
        
             | taylorlunt wrote:
             | Some style guides allow for surrounding the em dash with
             | spaces. It's a matter of preference.
        
             | kelnos wrote:
             | A double-dash is a perfectly valid substitute for an em
             | dash given that most (no?) keyboards have it on a key.
             | Seems like a waste of time to always have to look up an
             | escape code or copy/paste from somewhere when the intent of
             | "--" is clear.
        
               | idoh wrote:
               | I don't hold random comments on the internet to the
               | highest standard because I am not a monster. However they
               | are not equivalent and the em dash is a sign of extra
               | polish.
        
               | Veen wrote:
               | It's option-shift-hyphen on a Mac. And you can get at em
               | dashes on an iOS keyboard by long pressing the hyphen.
               | Not so difficult.
        
           | owl57 wrote:
           | These look like brackets, not binary operators. So, that's
           | one style, but a rather unobvious one, and also contradicts
           | PEP8, which says (as the very first thing in the section on
           | inline spaces!) to avoid whitespace immediately inside
           | brackets.
        
         | AlexMax wrote:
         | Sorry, but I think this is a poisonous, thought-terminating
         | cliche.
         | 
         | Python has had multiple ways of doing many things for a very
         | long time, and the longer you program in any language, the more
         | you realize there are often many solutions to a problem and the
         | "best" approach either depends on context or you realize there
         | is no one "best" approach and go on preference.
         | 
         | I think the idea should be judged on its own merits without
         | having to consult the Zen. That said, I seriously don't see the
         | point of it. Python 3 already forced everybody to convert all
         | their print statements to look like function calls, and now GVR
         | wants to bring the old style back as an option? It's just
         | parenthesis, what's the point?
         | 
         | If he wants to put that new parser to work, how about taking
         | another look at multi-line lambdas?
        
       | BiteCode_dev wrote:
       | Ruby does this and I hate it. It makes it very hard to quickly
       | parse code: you have to ponder every line to identify what is
       | what.
       | 
       | Parenthesis makes very clear what context you are in.
        
       | VWWHFSfQ wrote:
       | The only place I've ever liked function calls without parentheses
       | is Lua. But it only supports it with a single literal string or
       | table argument.
       | 
       | So, boo. Hiss.
        
       | mumblemumble wrote:
       | OK, so I sort of get it. I love ML style syntax. I love the way
       | that it supports great things like partial application.
       | 
       | What I do not like is TMTOWTDI. And I do not like Python
       | violating its own principles (namely, "explicit is better than
       | implicit"). As far as I am concerned, in Python, which does _not_
       | have partial application, function application is handled by a
       | special `(...)` operator that explicitly applies whatever
       | function comes before the parens to whatever is inside the
       | parens. Making the parens optional gives you two different ways
       | to apply a function - and, by extension, one more place for
       | people to argue about style - one of which is just an implicit
       | version of the other.
       | 
       | You've got to have a _way_ better reason to do that to a language
       | than just,  "Hey, isn't this cool? And also, I miss the Python 2
       | vs Python 3 wars, so wouldn't it be fun to give that pot another
       | stir for old time's sake?"
       | 
       | I get it, the change from a print statement to a print function
       | caused some pain. But it did bring some practical benefits, and
       | the transition is in the past now, and, to quote the Zen of
       | Python again, "special cases aren't special enough to break the
       | rules."
        
         | mumblemumble wrote:
         | Another thought: This would create ambiguities in the language
         | that would harm its readability. Maybe not as far as the
         | computer is concerned, but certainly as far as the humans are
         | concerned. Is                 print(1, 2, 3)
         | 
         | supposed to print                 1 2 3
         | 
         | or                 (1, 2, 3)
         | 
         | ?
         | 
         | What about                 print (1, 2, 3)
         | 
         | ?
         | 
         | Are they the same? Should they be different? I know what the
         | answer is in Python 3.8. A few weeks or months of programming
         | in a Python where parens are optional, though, and I wouldn't
         | be so sure anymore.
        
         | tetha wrote:
         | > You've got to have a way better reason to do that to a
         | language than just, "Hey, isn't this cool? And also, I miss the
         | Python 2 vs Python 3 wars, so wouldn't it be fun to give that
         | pot another stir for old time's sake?"
         | 
         | That was my first thought. Why would we turn a simple, binary
         | choice -- "< 3: statement, >= 3: function" into a big old...
         | maybe?
         | 
         | The binary choice hurts, because it dictates changes. Sure.
         | People dislike change, but it's easy to support.
         | 
         | However, there's one thing worse than change, and that's
         | inconsistency and uncertainty. like, in this case, going
         | "zoinks, your change wasn't actually necessary!". Except, now
         | we have both choices. So it'd be even more confusing.
        
         | riknos314 wrote:
         | This is on point.
         | 
         | I'm also going to throw another reference to PEP-20 in the mix
         | here: "There should be one-- and preferably only one --obvious
         | way to do it." This implies either forcing parens everywhere or
         | not using them at all. Paired with "explicit is better than
         | implicit", I'd say that points pretty clearly at using parens
         | everywhere.
        
         | jcfields wrote:
         | As they say, the road to Perl is paved with good intentions.
         | 
         | There are several languages that people like for this sort of
         | flexibility, but I think Python's relative rigidity has always
         | been one of its strengths.
        
       | flingo wrote:
       | This is insane, I love it.
       | 
       | How long until this is a library on pypi?
        
       | aardvark291 wrote:
       | Seems a bit early/late for April Fools.
        
       | cjhanks wrote:
       | I really hope they do not do this. In and of itself it is not a
       | problem, Ruby code is perfectly readable when the style is
       | consistent.
       | 
       | Software developers are often stubborn. The main result of this
       | change will be a mess of code which follows a mix of _all_ the
       | styles. That removes one of the greatest beauties of the Python
       | ecosystem, that there is a  "right way" to do things.
        
         | mumblemumble wrote:
         | Agreed. I deeply love the concept of Pythonic.
         | 
         | The Pythonic way to do it is (very) often not my favorite way
         | to do it. But, if I'm working in Python, I'm going to do it
         | that way, anyway. Because social factors matter, and choosing
         | your own convention rarely yields enough benefit to justify
         | choosing not to follow _the_ convention.
        
       | iovrthoughtthis wrote:
       | "I believe there are some other languages that support a similar
       | grammar (Ruby? R? Raku?) but I haven't investigated."
       | 
       | Poor effort tbh but I've been excited about new possibilities
       | before too.
       | 
       | Can anyone say which style of parser python used before and why
       | The bee PEG parser is more powerful. It's my understanding that
       | PEG parser are equivalent to RDPs.
        
       | ccmcarey wrote:
       | I don't see any benefits to this, Guido does a good job
       | mentioning many of the negatives .. and, aware of them all, I am
       | surprised he would push on. It seems an unreasonable increase in
       | complexity for no tangible gain.
        
       | rerx wrote:
       | I felt that the old print statement sometimes was handy when I
       | wanted to quickly throw some debugging lines into the code --
       | just less hassle with parentheses. But I wouldn't want any of the
       | ambiguity GvR's suggestion would bring.
       | 
       | For debugging comfort the print statement is half measures
       | anyway: Give us Julia's @show macro!
        
       | [deleted]
        
       | saiojd wrote:
       | I wish all languages just adopted ML syntax for function
       | application.
        
       | ris wrote:
       | > but I'll withdraw it if the response is a resounding "boo,
       | hiss"
       | 
       | Boo, hiss.
       | 
       | The parentheses-less function call is the second biggest obstacle
       | to ruby readability.
        
       | epicureanideal wrote:
       | This is more Ruby than Python. I specifically prefer Python more
       | because of its explicitness.
        
       | simzor wrote:
       | Hate the idea to be honest. In my opinion this will just bloat
       | the language, no need. Rather avoid the hundreds of different
       | standards like PHP.
        
       | enriquto wrote:
       | LOL, I totally love this!
        
       | tony wrote:
       | If you want to see some nice examples of PEP 617's (The new PEG
       | Parser) potential, see the draft of
       | https://www.python.org/dev/peps/pep-0622/
       | 
       | But `print 'hi world'` This would really spoil one of the nice
       | consistency things python 3 brought.
       | 
       | Callables without parenthesis to distinguish the arguments. Can
       | you imagine what this is going to do to readability on open
       | source projects?
       | 
       | This was back in June, and probably for the sake of conversation.
       | It got my (and a lot of others) attention, though. If that was
       | the case, mission accomplished.
       | 
       | I'm all for the new parser enabled in Python 3.9 (and switched on
       | by default in 3.10): https://www.python.org/dev/peps/pep-0617/
        
       | pavel_lishin wrote:
       | I loathe function calls without parentheses; it always looks
       | vaguely ambiguous to me.
        
         | enriquto wrote:
         | > I loathe function calls without parentheses; it always looks
         | vaguely ambiguous to me.
         | 
         | But then again, throwing and catching exceptions through
         | arbitrary depths along the call stack is perfectly clear and
         | neat.
        
         | fernandotakai wrote:
         | i took me a while to get used to `print()` but now that i'm
         | used to it, when i see py2 code i get... confused? it doesn't
         | look right.
         | 
         | same with `class Foo(object):`
        
           | pdonis wrote:
           | _> same with `class Foo(object):`_
           | 
           | That's still legal, and actually I prefer it even though it's
           | not required in Python 3, because explicit is better than
           | implicit.
        
       | geophile wrote:
       | What is the point? Why is this a desirable thing at all? TFA goes
       | directly into implementation and has not a word about why this is
       | desirable for readability, aesthetics, or any other criterion.
       | 
       | Seems like the sort of faddish syntactic sugar that they love in
       | Swift. Please, not in Python.
        
         | scrollaway wrote:
         | I think "the point", given the wording of the email, is to
         | showcase the power of the new parser; not implement it.
         | 
         | (I fucking hope)
        
           | kissgyorgy wrote:
           | This is the exact language Guide stopped being BDFL. STOP IT!
        
       | klyrs wrote:
       | The ambiguity of
       | 
       | foo (boo, hiss)
       | 
       | should immediately close the issue. What the heck is happening?
        
       | haecceity wrote:
       | >>> print (1, 2, 3)
       | 
       | Is that supposed to be a function call with a tuple or function
       | call with 3 integers?
        
       | corbet wrote:
       | See also the article (https://lwn.net/Articles/823292/) written
       | about this idea.
        
       | nurettin wrote:
       | > I believe there are some other languages that support a similar
       | grammar (Ruby? R? Raku?) but I haven't investigated.
       | 
       | Yes you did. And you want to take the good things from ruby. You
       | want no parentheses calls, block syntax instead of lambdas,
       | chainable map/filter/sort/reduce, accessor syntax, you want to
       | extend basic types so you can call methods on literals. You want
       | ruby all over you. Just admit it.
        
         | lizmat wrote:
         | Or Raku :-)
        
       | jeanvalmarc wrote:
       | If they'd done this right at the PY3K transition and _only_
       | allowed the function-call-without-parenthesis syntax for `print`
       | calls it could have been a good idea. But now that the community
       | paid the decade-long price to get print as a normal function why
       | backtrack?
        
       | kbd wrote:
       | The optional parentheses for any function Guido proposes is
       | similar to how Nim works. It's pleasant within Nim but seems too
       | TMTOWTDI for Python.
        
       | SiVal wrote:
       | return (boo, hiss)
       | 
       | There is something mature and responsible about a language that
       | tends to refuse a command if the meaning isn't obvious, forcing
       | you to make it obvious. If instead, you assign meanings to every
       | ambiguous statement, and to the inevitable exceptions and
       | exceptions to exceptions, you end up with JavaScript: "Oh, well,
       | too late now"-oriented design.
        
       | zaptheimpaler wrote:
       | Don't worry, its not coming back. Just goes to prove the old rule
       | - no one reads beyond the headline :)
       | 
       | ----
       | 
       | > Why is this being proposed? > > I think we would need a very
       | strong reason to consider this, > and so far I haven't seen any
       | justification other than "because > we can". >
       | 
       | (Guidos response below):
       | 
       | There was definitely something of that... I was looking at the
       | new PEG parser and realized that _if people wanted it_ this would
       | be easy to do. So I spent a pleasant hour or two coding it up to
       | my satisfaction.
       | 
       | But I was also trying to satisfy some demand. When Python 3 was
       | young, print becoming a function was one of the most frequent
       | complaints, and it's still occasionally seen on Twitter. I found
       | at least two StackOverflow issues about it, but the combined
       | upvote count was less than 100.
       | 
       | An early post in this thread reminded me that IPython has a
       | feature called "autocall" that allows exactly this syntax. I
       | don't know how popular it is. However, apparently there the form
       | `f x+1` ends up calling `f("x+1")` (i.e. stringifying the
       | argument), so introducing similar syntax in Python with different
       | semantics would hardly be helpful. (If someone wants to start a
       | debate on argument quoting, please start a new thread, so we can
       | lay this one to rest.)
       | 
       | All in all, it's clear that there's no future for this idea, and
       | I will happily withdraw it.
       | 
       | ----
        
       | marczellm wrote:
       | Check out xonsh which is an application of python + that sort of
       | idea to the problem space of shell scripting.
       | 
       | https://xon.sh/
        
       | dom96 wrote:
       | > I believe there are some other languages that support a similar
       | grammar (Ruby? R? Raku?) but I haven't investigated.
       | 
       | I'm amazed that Guido is not aware of Nim which does precisely
       | this. It works brilliantly too. It would be incredible if Python
       | becomes more like Nim (Nim itself having been inspired a fair bit
       | by Python).
        
         | [deleted]
        
       | Daishiman wrote:
       | Too ambiguous.
       | 
       | One thing I love about Python is that it's clear when I'm passing
       | a function/method as argument, or aliasing a class, or just
       | generally knowing when I'm calling something vs referencing it.
       | 
       | This is a no-go from the start.
        
       | eatonphil wrote:
       | When I program in Standard ML or F# I always use parentheses to
       | make it clearer that a function call is happening.
        
       | vasili111 wrote:
       | I do not like this idea. I think it is better to stick to one
       | standard of syntax and do not create several ways of doing same
       | thing without added significant benefit.
        
       | HALtheWise wrote:
       | One really nice feature from Wolfram Mathematica that few other
       | languages seem to have is a special prefix-only syntax for
       | single-argument function application. In Mathematica, it's f@x
       | ==> f(x), and it's really convenient because it prevents needing
       | to move your cursor to the end to put in a closing paren. Since
       | it only works for single-argument functions, there's no
       | ambiguity.
        
       | beervirus wrote:
       | Allowing this syntax for all functions and methods seems
       | ridiculous, especially with the problems Guido mentions (like how
       | the first argument can't begin with a paren or bracket, wtf). But
       | a limited version of this feature that's specific only to the
       | print statement seems fine. If the parser already has the
       | complexity to issue a warning like:
       | 
       | SyntaxError: Missing parentheses in call to 'print'. Did you mean
       | print(1, 2, 3)?
       | 
       | Then why not just have it DWIM?
        
       | D13Fd wrote:
       | I seriously do not see any worthwhile benefit in this, and
       | significant cost.
       | 
       | Benefits: You can use spaces instead of parenthesis. It's the
       | same number of characters and function arguments won't work with
       | spaces.
       | 
       | Costs: Python has to support this forever. Increased complexity.
       | More difficult to read code, because you could be doing the same
       | thing in multiple ways. More style guidelines to enforce.
       | Confusion among new programmers about why they can't use function
       | arguments without parenthesis. Confusion among new programmers
       | about why they would use spaces instead of parenthesis (or the
       | reverse).
       | 
       | Seriously, I do not see any reason why they would ever want to
       | add this in light of the seemingly obvious costs.
        
       | confeit wrote:
       | > Missing parentheses in call to 'print'. Did you mean print(1,
       | 2, 3)?
       | 
       | Yes, Python, I meant _exactly_ that! I 've never seen this error
       | message in error. Now you know what I mean, please fix it
       | automatically, I know you can do that. Heck, throw a single
       | warning if you really want to enforce this. I can ignore warnings
       | that I don't care about.
        
         | coldtea wrote:
         | Yeah, generally please second-guess me Python, like my old pal
         | Clippy did, what could possibly go wrong?
        
           | confeit wrote:
           | > You're flying! How?
           | 
           | > Python! I learned it last night! Everything is so simple!
           | Hello world is just: print "Hello, world!"
           | 
           | > SyntaxError: Missing parentheses in call to 'print'. Did
           | you mean print("Hello, world!")?
           | 
           | > I dunno... dynamic typing? _Whitespace?_
           | 
           | > Come join us! Programming is fun again! It's a whole new
           | world up here!
           | 
           | > But how are you flying?
           | 
           | > I just typed: imports antigravity as ag
           | 
           | > TypeError: imports() takes 2 positional arguments but 3
           | were given
        
       | coolreader18 wrote:
       | Nim does this, and the whitespace is significant[0][1]:
       | echo $foo         # is parsed as         echo($foo)
       | 
       | [..]                   echo(1, 2) # pass 1 and 2 to echo
       | echo (1, 2) # pass the tuple (1, 2) to echo
       | 
       | [..]                   proc optarg(x: int, y: int = 0): int = x +
       | y         proc singlearg(x: int): int = 20*x
       | echo optarg 1, " ", singlearg 2 # prints "1 40"
       | let fail = optarg 1, optarg 8 # Wrong. Too many arguments for a
       | command call         let x = optarg(1, optarg 8) # traditional
       | procedure call with 2 arguments         let y = 1.optarg optarg 8
       | # same thing as above, w/o the parenthesis         assert x == y
       | 
       | [0]: https://nim-lang.org/docs/manual.html#syntax-precedence
       | 
       | [1]: https://nim-lang.org/docs/manual.html#procedures-command-
       | inv...
        
         | gen220 wrote:
         | Is there a justification for this behavior?
         | 
         | This makes it quite hard to "sight-read" code with reasonably-
         | sized function names and arg lists:
         | do_some_thing_descriptive (some_arg_2, some_longer_arg)
         | 
         | [ ... other code ]
         | do_some_very_descriptive_thing(some_arg_2, some_longer_arg)
         | 
         | I imagine that each file would try to remain internally-
         | consistent with preferring one syntax over the other.
         | 
         | IMO, in scenarios where a module must remain internally-
         | consistent on its one-of-many-ways to do it, for the sake of
         | legibility, there should be only one way to do it. Although,
         | I'm open to hearing any good-faith arguments to the contrary!
        
       | gtrubetskoy wrote:
       | Python becoming Tcl
        
         | vasili111 wrote:
         | Unfortunately Python will not get the strength of TCL such as
         | metaprogramming with this change.
        
         | AlexandrB wrote:
         | Yup, this looks a lot like Tcl! But Tcl lets you compose code
         | at runtime using its string lists. I doubt Python will. So why
         | introduce another redundant syntax?
        
       | enitihas wrote:
       | This sounds like a bad idea. It creates more ambiguities in the
       | language, and will require people to remember a lot more. It
       | works in ruby because in ruby you can't assign a function to a
       | variable like
       | 
       | A = len
       | 
       | But you can in python.
       | 
       | It seems python is adding more and more implicit stuff in every
       | new release.
       | 
       | I think the day we can import braces from __future__ might not be
       | far away.
        
       | tandav wrote:
       | I would more like to support some kind of pipes, eg.:
       | 
       | 123 | add10 | str | print
       | 
       | UPD: Some of my workarounds (dont try this at home lol): [twitter
       | thread] https://twitter.com/tandavaya/status/1155925017848242176
        
         | drivers99 wrote:
         | Looks like forth (uses stack instead of pipes though). The
         | first line will define add10 (which is assumed to exist in your
         | example already, but I wanted to show how easy it was to
         | create). 123 puts 123 on the stack. add10 adds ten to the
         | number on the stack. "." prints (and removes) the top of the
         | stack. Don't have to convert it to a string in this case.
         | : add10 10 +         123 add10 .
        
         | geophile wrote:
         | Take a look at marcel: https://github.com/geophile/marcel. It
         | is a pipe-objects-instead-of-strings shell, implemented in
         | Python. But it is also an API allowing scripting from inside
         | Python, e.g.                   for file, size in
         | ls('/home/jao') | map(lambda f: (f, f.size)):
         | print(f'{file.name}: {size}')
        
         | bjourne wrote:
         | +1! I don't like your suggested syntax, but definitely,
         | something like that would be a great addition to Python.
         | Especially if it could be made to work with lists. Rough idea:
         | range(10) | @ + 2 | @ % 2 == 0 | print(@)
        
       | dasb wrote:
       | So, is this just a syntax change or is this adding a new
       | statement?
       | 
       | If it's the latter, does that mean that the execution environment
       | is part of the language itself, instead of, for example, C where
       | environmental stuff is only accesible through the standard
       | library and the language per se is little more than a context-
       | free grammar?
        
         | coldtea wrote:
         | > _does that mean that the execution environment is part of the
         | language itself_
         | 
         | Yes, that has always be the case with Python in my
         | understanding - there are lots of built-ins...
        
         | pdonis wrote:
         | _> is this just a syntax change or is this adding a new
         | statement?_
         | 
         | It's just a syntax change; "print 1 2 3" is still an expression
         | just like "print(1, 2, 3)".
        
       | dmitriid wrote:
       | Elixir has this. And now the linter puts parentheses back IIRC
       | because of syntax ambiguity _to the human_.
        
       ___________________________________________________________________
       (page generated 2020-07-14 23:01 UTC)