13 ms·
Bringing the print statement back
- flingo 6y agoThis is insane, I love it. How long until this is a library on pypi?
- enriquto 6y agoLOL, I totally love this!
- tech2 6y agoI remember this kind of thing from days gone by with coffeescript, and the absolute hell it caused. It may have been made worse by js being callback-heavy, but assuming I had a function: def bob(cb, *args): do some stuff... Then the call: bob somefn, 2, 3 Works. But I remember having hellish times tracking down issues when you missed a single comma. bob somefn 2, 3 Now you have bob being passed the result of evaluating the callback (early) with 2, 3 - and this is discovered at runtime. Ugh!
- gilbetron 6y agoThis is something I hated about Ruby (which is generally a pretty nice language) - Use parenthesis in your function calls ... or not! It's confusing, especially when used with other optional things in Ruby - different ways to pass in named values, for instance. It just confuses for no gain.
- war1025 6y agoI'd be all for bringing back the print statement since it's the main breaking change I run into when flipping back and forth between python 2 and 3. The idea of making parens optional for all function calls seems like just way too much though
- dathinab 6y agoFun, put please don't. It makes python less consistent as you can not use this in a chain and a view other positions.
- 978e4721a 6y agoJust add partial application and haskell lambda syntax. Many think think that python already lost almost everything that it was loved for initially. So why not change it more drastically
- Too 6y agoWhat's next? Make quotes around strings optional? Or commas between array elements?
- hoseja 6y agoI never understood what sort of person you need to be to so viscerally want your prints to be parenthesis-less when all other function calls do have parentheses. And moan about it so much.
- wwright 6y agoThis proposal seems very non-composable, by which I mean that the syntax does not integrate with a number of other features. He says that currently you can’t nest it in other expressions for example, and you can’t use it with arguments starting with a parenthesis. I personally like the aesthetic of it, but the non-composability makes it a UX mess in my opinion. Languages are a toolset for combining things, and when those tools just arbitrarily refuse to be combined (or combine irregularly), you end up bending over backwards to make the language get out of your way rather than getting a job done.
- imtringued 6y agoGroovy has this and it's only really meant to be used for DSLs. Think of something like build.gradle. You can try to use it everywhere but I feel there are way too many reasons to not do so.
- perlgeek 6y agoPlease not. Sincerely, a programmer from a language that allows this. (To elaborate: Perl and Raku allow this. It's not a bad idea on its own, but it comes with lots of tradeoffs that, IMHO, don't fit with the design of Python).
- cafard 6y agoIs this what Python really needs?
- beervirus 6y agoAllowing 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?
- pavel_lishin 6y agoI loathe function calls without parentheses; it always looks vaguely ambiguous to me.
- enriquto 6y ago> 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.
- SAI_Peregrinus 6y agoParentheses are only needed with infix notation. Pure prefix (like Unlambda) or pure postfix notation (like Forth) are unambiguous without them. Whether the resulting language is easy to understand is a far more complicated question.
- pavel_lishin 6y ago> Whether the resulting language is easy to understand is a far more complicated question. That's why I hate them. A programming language is primarily meant to be read by people. If I see something like thing noun object What's going on there? Is thing a function? Is noun? Am I passing two arguments to thing, or am I passing the result of invoking the function noun with the argument object? Hell, if I have something like verb action it certainly looks like I'm calling a function called verb with the argument action, but is the argument I'm giving to verb the actual function action, or the result of evaluating action? Yes, in any given language there's probably a single answer to all of these, but I bet it varies from language to language, and I'd really, really, really rather not waste calories by having my brain try to figure it out.
- fernandotakai 6y agoi 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):`
- 6y ago
- corbet 6y agoSee also the article (https://lwn.net/Articles/823292/ https://lwn.net/Articles/823292/) written about this idea.
- gtrubetskoy 6y agoPython becoming Tcl
- enitihas 6y agoThis 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.
- Izkata 6y ago> I think the day we can import braces from __future__ might not be far away. Behold, bython: https://github.com/mathialo/bython https://github.com/mathialo/bython
- readmodifywrite 6y agoI love that the example uses the exact same indentation format that Python already requires.
- tandav 6y agoI 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 https://twitter.com/tandavaya/status/1155925017848242176
- phyrex 6y agoI’ve used this in production: def thread_first(current_value, args): for funcargs in args: if isinstance(funcargs, list): func, *restargs = funcargs else: func = funcargs restargs = [] current_value = func(current_value, *restargs) if current_value is None: break return current_value It’s modelled after clojure’s ‘->’. Your example would be thread_first(123, [add10, str, print])
- drivers99 6y agoLooks 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 6y agoTake a look at marcel: https://github.com/geophile/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 6y ago+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 6y agoSo, 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 6y ago>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 6y ago> 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 6y agoElixir has this. And now the linter puts parentheses back IIRC because of syntax ambiguity to the human.
- softwaredoug 6y agoSeems to violate "There should be one-- and preferably only one --obvious way to do it."
- enriquto 6y ago> 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 6y agoSays the line with two different hyphenating styles. It's an Easter egg.
- idoh 6y agoSo 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.
- kelnos 6y agoA 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 6y agoI 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 6y agoIt’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.
- VWWHFSfQ 6y agoThe 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 6y agoOK, 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."
- lmm 6y agoI don't think having two different syntactic ways to write the the same thing - at a purely syntactic level - is a violation of TMTOWTDI. After all, Python already lets you write: f(a) f((a)) (f)(a) (f)((a)) etc. and those all mean the same thing, and no-one finds this confusing.
- jacquesm 6y agoI don't see why they couldn't just leave the old print statement in place so it wouldn't break as much code as it did.
- kevin_thibedeau 6y agoIt was an inconsistent albatross of a special case. The whole point of 3 was to break things that were bad ideas.
- moreaccountspls 6y ago
- cjhanks 6y agoI 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 6y agoAgreed. 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.
- ris 6y ago> 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 6y agoThis is more Ruby than Python. I specifically prefer Python more because of its explicitness.
- tony 6y agoIf 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/ 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/ https://www.python.org/dev/peps/pep-0617/
- geophile 6y agoWhat 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 6y agoI 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 6y agoThis is the exact language Guide stopped being BDFL. STOP IT!
- klyrs 6y agoThe ambiguity of foo (boo, hiss) should immediately close the issue. What the heck is happening?
- nurettin 6y ago> 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 6y agoOr Raku :-)
- kbd 6y agoThe optional parentheses for any function Guido proposes is similar to how Nim works. It's pleasant within Nim but seems too TMTOWTDI for Python.
- dom96 6y ago> 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 6y ago[deleted]
- Daishiman 6y agoToo 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.
- vasili111 6y agoI 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.
- D13Fd 6y agoI 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 6y ago> 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 6y agoYeah, generally please second-guess me Python, like my old pal Clippy did, what could possibly go wrong?
- confeit 6y ago> 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
- lucb1e 6y agoFrom https://xkcd.com/353/ https://xkcd.com/353/ I'm not sure whether to take this as an in-joke (knowing the reference is part of the fun) or poor attribution (credits should be given where they're due).
- BiteCode_dev 6y agoRuby 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.
- lucb1e 6y agoCan't say that I hate it, exactly, but it does make it significantly harder to get into Ruby code when you're not exposed to it daily. Can an amateur woodworker complain their tools are too hard to use if others have no trouble with it and are more productive than with the alternative? Maybe? So rather than saying that I don't like it, I think what I'd like is some (semi-)objective way of figuring out whether the advantages are worth it. I'm inclined to say it's not worth it, but I don't know.
- ccmcarey 6y agoI 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 6y agoI 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!
- saiojd 6y agoI wish all languages just adopted ML syntax for function application.
- simzor 6y agoHate 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.
- haecceity 6y ago>>> print (1, 2, 3) Is that supposed to be a function call with a tuple or function call with 3 integers?
- lucb1e 6y agoWell that's the point they're making: it's a downside that you can't call a function with a tuple as first argument. So it's supposed to be an argument, hence the space, but the interpreter is blind for that and takes it as 3 arguments. And frankly, I'd say the interpreter is right: anything else would leak to really freaky bugs that I don't with upon any beginning programmer. This also kind of makes me conclude that the whole idea is folly, it just causes ambiguity and doesn't really server any purpose whatsoever.
- jeanvalmarc 6y agoIf 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?
- SiVal 6y agoreturn (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 6y agoDon'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. ----
- nurettin 6y agoI remember him being present in the github issue tracker before they moved to bugs.python.org. His presence was next to useless when people were reporting problems about the async library. What went on was like; he made comments on his suspicions, someone who actually knows what's going on made a pull request without even commenting on his ramblings. Again and again for years. Now he's looking for validation hacking the parser.
- HALtheWise 6y agoOne 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.
- tzot 6y agoIn any case, this can be done now with a helper class used as a decorator. >>> class At: __slots__= 'fun', def __init__(self, fun): self.fun = fun def __matmul__(self, arg): return self.fun(arg) def __call__(self, *args, **kwargs): return self.fun(*args, **kwargs) >>> @At def square(x): return x*x >>> square(2) 4 >>> square@2 4
- jfkebwjsbx 6y agoThere is nothing nice about it. Not even in a REPL. Preventing a simple move of the cursor does not justify complexity and yet another way to apply a function.
- coolreader18 6y agoNim 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 https://nim-lang.org/docs/manual.html#syntax-precedence [1]: https://nim-lang.org/docs/manual.html#procedures-command-invocation-syntax https://nim-lang.org/docs/manual.html#procedures-command-inv...
- gen220 6y agoIs 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!
- iovrthoughtthis 6y ago“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.
- deleted 6y ago[deleted]
- aardvark291 6y agoSeems a bit early/late for April Fools.
- marczellm 6y agoCheck out xonsh which is an application of python + that sort of idea to the problem space of shell scripting. https://xon.sh/ https://xon.sh/
- eatonphil 6y agoWhen I program in Standard ML or F# I always use parentheses to make it clearer that a function call is happening.
- shikoba 6y agoYou shouldn't. It add complexity for the reader. It's always clear what is the function and what are the arguments.
- eatonphil 6y agoI disagree. The funny thing is that in Standard ML and F# it's less common to pass arguments solely through currying anyway. The standard libraries in both use tuples. I have always felt as a reader that this and camel-case makes code easier to read.