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."
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.
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.
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.
> 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.
If Python wants to come closer to a functional style of programming, then they should allow inline lambda functions which span multiple lines and still follow the normal syntax (i.e., escaping newlines would be cheating).
I 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.
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.
I 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.
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.
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.
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?
"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.
> 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.
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.
Parentheses 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.
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.
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.
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.
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
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!
> 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.
I 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!
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}')
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.
+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:
This 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.
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?
(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).
Well 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.
[+] [-] mumblemumble|5 years ago|reply
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|5 years ago|reply
What about
?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.
[+] [-] riknos314|5 years ago|reply
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|5 years ago|reply
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.
[+] [-] tetha|5 years ago|reply
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.
[+] [-] jacquesm|5 years ago|reply
[+] [-] raverbashing|5 years ago|reply
There is no reason to not require parenthesis. No reason.
This is what I hate about Ruby, not having parenthesis gets a bit confusing and adds a couple of gotchas
Print statement is no more. It is gone. It went to meet its maker. Forget about it
Doing away with parenthesis is not syntactic sugar, it's the watermelon seeds that get in the way
[+] [-] amelius|5 years ago|reply
[+] [-] lmm|5 years ago|reply
[+] [-] Karuhanga|5 years ago|reply
[+] [-] zaptheimpaler|5 years ago|reply
----
> 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|5 years ago|reply
[+] [-] enitihas|5 years ago|reply
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|5 years ago|reply
Behold, bython: https://github.com/mathialo/bython
[+] [-] D13Fd|5 years ago|reply
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.
[+] [-] softwaredoug|5 years ago|reply
[+] [-] AlexMax|5 years ago|reply
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?
[+] [-] open-source-ux|5 years ago|reply
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.
[+] [-] solox3|5 years ago|reply
It's an Easter egg.
[+] [-] enriquto|5 years ago|reply
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.
[+] [-] tony|5 years ago|reply
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|5 years ago|reply
[+] [-] fernandotakai|5 years ago|reply
same with `class Foo(object):`
[+] [-] SAI_Peregrinus|5 years ago|reply
[+] [-] enriquto|5 years ago|reply
But then again, throwing and catching exceptions through arbitrary depths along the call stack is perfectly clear and neat.
[+] [-] cjhanks|5 years ago|reply
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|5 years ago|reply
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.
[+] [-] corbet|5 years ago|reply
[+] [-] geophile|5 years ago|reply
Seems like the sort of faddish syntactic sugar that they love in Swift. Please, not in Python.
[+] [-] scrollaway|5 years ago|reply
(I fucking hope)
[+] [-] klyrs|5 years ago|reply
foo (boo, hiss)
should immediately close the issue. What the heck is happening?
[+] [-] coolreader18|5 years ago|reply
[1]: https://nim-lang.org/docs/manual.html#procedures-command-inv...
[+] [-] gen220|5 years ago|reply
This makes it quite hard to "sight-read" code with reasonably-sized function names and arg lists:
[ ... other code ] 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!
[+] [-] confeit|5 years ago|reply
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|5 years ago|reply
[+] [-] tech2|5 years ago|reply
[+] [-] ris|5 years ago|reply
Boo, hiss.
The parentheses-less function call is the second biggest obstacle to ruby readability.
[+] [-] tandav|5 years ago|reply
123 | add10 | str | print
UPD: Some of my workarounds (dont try this at home lol): [twitter thread] https://twitter.com/tandavaya/status/1155925017848242176
[+] [-] phyrex|5 years ago|reply
[+] [-] geophile|5 years ago|reply
[+] [-] drivers99|5 years ago|reply
[+] [-] bjourne|5 years ago|reply
[+] [-] gilbetron|5 years ago|reply
[+] [-] jeanvalmarc|5 years ago|reply
[+] [-] perlgeek|5 years ago|reply
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).
[+] [-] haecceity|5 years ago|reply
Is that supposed to be a function call with a tuple or function call with 3 integers?
[+] [-] lucb1e|5 years ago|reply