11 ms·
The high-level goals of python end up creating these little syntactic landmines that can get even experienced coders. My personal nomination for the worst one o
by aeturnum 5y ago
The high-level goals of python end up creating these little syntactic landmines that can get even experienced coders. My personal nomination for the worst one of these is that having a comma after a single value often (depending on the surrounding syntax) creates a tuple. It's easy to miss and creates maddening errors where nothing works how you expect.
I've moved away from working in Python in general, but I think the #1 feature I want in the core of the language is the ability to make violating type hints an exception[1]. The core team has been slowly integrating type information, but it feels like they have really struggled to articulate a vision about what type information is "for" in the core ecosystem. I think a little more opinion from them would go a long way to ecosystem health.
[1] I know there are libraries that do this, I am not seeking recommendations.
- macNchz 5y agoI’ve been writing Python professional full time for 8 years and still occasionally make the trailing-comma-tuple mistake. These days at least I’ll recognize and be able to find it quickly rather than wasting time. Can be caught with a linter, but not every codebase is readily linted.
- aylmao 5y agoThe lack of a static type-system is IMO what makes these one-character mistakes very annoying. The compiler can't tell you something is wrong, so you're just left to figure out why things are broken, just to realize it was the smallest of typos.
- aeturnum 5y agoI love how simple and forgiving Python is for small projects. The "trailing comma creates a tuple" situation comes out of, as far as I can tell, a desire to create maximally convenient syntax in the scenarios where tuples are intended. I think that's great for small code! I just wish that the core team would take that same zeal for a "pythonic" experience with small code and use it to develop more scaled-up systems for dealing with larger code bases. My idea is to enforce strong pre-conditions on function calls using type hints, but I am sure there are other ways to do it.
- iooi 5y agoIf you use mypy (as anyone should for any non-hobby Python usage) then Python has one of the strongest type systems available. Optional types, generics, "Any" escape hatches, everything you could want.
- aeturnum 5y agomypy is a great project and I agree that basically every project at scale should use it. However, I think you're wrong about the strength of the Python type system and what a good type system can "get" you. I think mypy both does an amazing job at static checking and that more powerful type systems go far beyond static checks and into changing how you structure and write code. The newly introduced "structural pattern matching" they just introduced[1] is an example of the kind of feature that could be usefully expanded by making type a first-class part of the Python runtime. Again - the dynamism of Python means teams can write amazing extensions to Python (like mypy), but that isn't a replacement for the core team having a plan for how they think typing information should be used at runtime. Their current answer seems to be "nothing," which disappoints me. [1] https://www.python.org/dev/peps/pep-0622/ https://www.python.org/dev/peps/pep-0622/
- yawaramin 5y agoWould mypy have caught any of the issues highlighted in the article?
- Too 5y agoNo. Mypy only cares about types, it would only have been caught if something was expecting tuple of certain length, otherwise not. The problem in the article is more related to syntax, not types, with the problem that both forms are valid syntax with different but still very similar outcome. Pylint on the other hand can find it with implicit-str-concat check enabled.
- jen20 5y ago> one of the strongest type systems available. This is simply not true - Python with mypy isn’t even as strong as Typescript, let alone Rust, F#, Haskell and so forth.
- tyingq 5y agoC lets me do this, and doesn't say much about it. char ch_arr[3][10] = { "uno", "dos" "tres" };
- anyfoo 5y agoC's type system is neither very static nor outstandingly helpful by today's standards, yes.
- yawaramin 5y agoOn the other hand a good type system doesn't: # let ch_arr = [ "uno"; "dos" "tres"; ];; Error: This expression has type string This is not a function; it cannot be applied.
- _ZeD_ 5y agoThis is not a good type system. It's a bad language where you can invoke functions without parentesis
- vmladenov 5y agoWhy should function arguments be delimited by parentheses? We don’t do that in Bash or Objective-C, for example
- _ZeD_ 5y agoto be able to detect the difference between "this expression is a function" and "this expression is the result of the computation of a function" the parentheses are not for function arguments, are for "invocation".
- yawaramin 5y agoCan you show an example of how they could be confused?
- 5y ago
- anyfoo 5y agoFully agreed. If python had a proper static type system, those typos would hardly matter, and you'd have the best of both worlds: Convenient, concise syntax, but still confidence in your code. I say "had a proper type system", but actually it turns out that it does have something like that: When I use python for anything else than a most tiny script now, I use "mypy"[1] which implements static typing according to some existing Python standard (whether that came about because of mypy or the other way around, I don't know). It is so, so good to have mypy telling me where I messed up my code instead of receiving a cryptic, weird runtime error, or worse, no error and erratic runtime behavior. Because not knowing that a particular type is unexpected and wrong, values often get passed along and even manipulated until the resulting failure is not very indicative of the actual problem anymore. [1] http://mypy-lang.org http://mypy-lang.org
- wiredfool 5y agoI’m not clear how a type system would pick up a missing comma in a list of strings, unless the type was specific enough that the contents of the list or the length was encoded in the type.
- anyfoo 5y agoTrue, in this particular case that would only help for fixed length strings, which is far from the encompassing case. I was thinking more generally and lost what the actual issue here is about.
- ehsankia 5y agoA lot of people in this thread are using this to make fun of Python, but the exact same issue exists in something like c++, here's some I fixed recently: https://github.com/UWQuickstep/quickstep/pull/9 https://github.com/UWQuickstep/quickstep/pull/9 https://github.com/tensorflow/tensorflow/pull/51578 https://github.com/tensorflow/tensorflow/pull/51578 https://github.com/mono/mono/pull/21197 https://github.com/mono/mono/pull/21197 https://github.com/llvm/llvm-project/pull/335 https://github.com/llvm/llvm-project/pull/335
- aeturnum 5y agoI didn't understand anyone to be saying that Python is the only language to have this flaw. Also, I personally don't mind this approach to string concatenation. I think it's a fine compromise between easy formatting and clarity. I was whining about a corner case of tuple construction - which as far as I know is not a feature of any other language.
- rstuart4133 5y agoA better compromise is to insist on this: ( "one", ( "a very very" "long long two" ), "three" ) And of course a,b should be syntactically invalid. It must be (a,b)
- hsbauauvhabzb 5y agoI’d rather a compile time error over an exception (or both), which in many cases can occur. I know mypy does this, maybe I should alias python=“mypy&&python”
- luhn 5y agoI feel like it's been pretty clear from day one that type hints are meant for static analysis with tools like mypy. It's not exclusive to that use and has a lot of other possible applications, but the primary goal has always static analysis.
- rbonvall 5y agoI think automatic string concatenation and singleton tuples were not introduced according to some high-level goal. They are just historical baggage. Automatic string concatenation comes from C, and the singleton tuple syntax probably just seemed like a good idea at first. In hindsight, singleton tuples are not common or useful enough to deserve their own syntax. If the way to create them was something like this: t = tuple.single("hello") we'd thing it's ugly or inconsistent, but definitely not confusing or bug-prone.
- hddqsb 5y agoOne place where singleton tuples used to be common is with the old "%"-formatting, specifically in the case where there is a single argument and its value might be a tuple: x = (1,2,3) #print("the value of x is %s" % x) # breaks if x is a tuple print("the value of x is %s" % (x,)) # works even if x is a tuple There is a readable way to create singleton tuples, without the sneaky trailing comma or a new function like tuple.single: tuple(["hello"]) The square brackets can be slightly annoying. I recall writing the following function to omit them: def tup(*args): return tuple(args) This basically lets you use the usual tuple syntax, just prefixed with the word "tup". The advantages are that you don't need a trailing comma for singleton tuples, and it's more obvious that a tuple is being created (it can be difficult to distinguish between tuple literals and parentheses used for grouping in a complex expression). I am reminded of a somewhat similar issue with empty set literals: {1,2} is a set, {1} is a set, but {} is a dict. The way to create empty sets is using set().
- deleted 5y ago[deleted]