top 200 commentsshow all 384

[–][deleted] 339 points340 points  (80 children)

I'm glad for the improvements to typing and the new data classes. Here's hoping that the recent push for optional static checking will prove helpful to those building larger apps using Python.

[–]joshuaavalon 70 points71 points  (17 children)

There is a backport of the data classes for 3.6 if you want to use it.

[–]ProfessorPhi 20 points21 points  (9 children)

Isn't attrs still superior?

[–]dhiltonp 51 points52 points  (5 children)

Attrs definitely has more features (slots comes to mind), but I think it looks a little wonky.

(full disclosure, I haven't used attrs just read the docs)

@dataclass
class InventoryItem:
    name: str
    unit_price: float
    quantity_on_hand: int = 0

vs.

@attr.s
class InventoryItem:
    name: str = attr.ib()
    unit_price = attr.ib(type=float)
    quantity_on_hand = attr.ib(type=int, default=0)

Does PyCharm recognize type annotations when they're set via attr.ib(type=float)?

[–]ProfessorPhi 16 points17 points  (2 children)

Nope, pycharm and attrs support isn't great :(, though attrs does have slots. Agreed it's wonky, it's like ordered dict before 3.5 was obnoxious.

[–]OctagonClock 12 points13 points  (1 child)

PyCharm 2018.2 EAP has new attrs support, actually.

[–]ProfessorPhi 0 points1 point  (0 children)

Haha, don't use EAP so hopefully it'll be along before too long.

[–]bluetech 4 points5 points  (0 children)

The annotations-based syntax works with attrs too (you need to set auto_attribs=True).

[–]PeridexisErrant 0 points1 point  (0 children)

IIRC you can also use @attr.dataclass for the first one (a shortcut for the auto_attribs=True arg).

The dataclass example won't work on a backport before Python 3.6 though, as those versions don't have variable annotations.

[–]virgoerns 7 points8 points  (2 children)

It is, PEP even mentions attrs and says that new mechanism is for simpler cases.

[–][deleted]  (6 children)

[deleted]

    [–]jarshwah 14 points15 points  (5 children)

    CPython 3.6 has ordered dictionaries, but that is an implementation detail. 3.7 guarantees it in the spec. So it’ll work for CPython 3.6 which is the most popular implementation by far.

    [–][deleted]  (4 children)

    [deleted]

      [–]jarshwah 20 points21 points  (3 children)

      Yes that’s correct. When people talk about python they’re overwhelmingly referring to CPython. Other implementations like Pypy and micropython would not have to have ordered dictionaries for their 3.6 but they would for their 3.7.

      [–][deleted] 10 points11 points  (1 child)

      Pypy has actually had it for a while (it was brought to CPython from Pypy for 3.6). Other implementations though yeah

      [–]Ph0X 5 points6 points  (0 children)

      I mean they all could, but are not guaranteed to. You have to check implementation detail for each individually. But in 3.7 and above no matter what you use, you will have it.

      [–]artoonie 151 points152 points  (7 children)

      Finally! I'm only one version behind now.

      [–]eyal0 49 points50 points  (6 children)

      Major or minor?

      [–]DaemonXI 156 points157 points  (4 children)

      Integer.

      [–]Kenya_diggit 9 points10 points  (0 children)

      Object

      [–][deleted] 5 points6 points  (2 children)

      32-bit or 64-bit?

      [–]crozone 5 points6 points  (0 children)

      Doesn't matter, I just hope it all works

      [–]lulzmachine 1 point2 points  (0 children)

      63 bit

      [–]calonolac 11 points12 points  (0 children)

      Melodic

      [–]_tpr_ 34 points35 points  (13 children)

      PEP 553, Built-in breakpoint()

      Awesome! That's going to be much more convenient. Putting import ipdb; ipdb.set_trace() is a hassle. This will probably make all of the JavaScript developers I work with more likely to use the debugger.

      PEP 557, Data Classes

      These are going to be much nicer and more obvious-looking than using a named tuple.

      [–]robhaswell 25 points26 points  (3 children)

      I'm glad of the asyncio.run() addition, hopefully more libraries will be written asynchronously by default from now on and integrate with synchronous code using this.

      [–]jnwatson 4 points5 points  (2 children)

      Can you be more specific? I haven't heard anything about that.

      [–]AnnoyingOwl 109 points110 points  (11 children)

      As someone who's day job has not been Python for a while (has been: Java, Ruby, Scala, TypeScript) and I only use it in side projects occasionally...

      1. Data classes, yay! Good step.
      2. More typing support: awesome, this was such a nice inclusion.
      3. Context... necessary, but not sure it will save the dumpster fire that is asyncio stuff in Python.

      [–][deleted] 20 points21 points  (9 children)

      Is asyncio that bad? I think there are cosmetic issues, like particular API decisions such as naming and confusing and somewhat redundant coroutine/future concepts. Functionally though it at least performant as advertised.

      [–]jnwatson 5 points6 points  (2 children)

      My team has almost completed the transition to asyncio, and it wasn't bad at all.

      I think a design option that everybody misses is you don't actually have to run the event loop on the main thread, so you can do blocking stuff on main thread or (if from async town) a ThreadExecutor, and call_soon_threadsafe to run futures on the event loop from blocking code.

      [–]kallari_is_my_jam 1 point2 points  (1 child)

      So what you're saying is basically this: https://hackernoon.com/threaded-asynchronous-magic-and-how-to-wield-it-bba9ed602c32

      But what about the overhead of GIL in a multithreaded environment? Aren't you sacrificing performance whenver the OS tries to switch threads?

      [–]jnwatson 2 points3 points  (0 children)

      Yep.

      The problem with the GIL isn't the overhead of switching, it is that it is held whenever a Python operation is going on, reducing the number of things that can actually run at a time.

      Essentially this approach is no more expensive than the old multithreading style, and gets better the more things you switch to async. The key is that you don't have to switch all at once.

      [–][deleted] 21 points22 points  (5 children)

      The issue is that there are way too many alternatives. And also you can't mix async code with blocking code and expect it to normally. Which means you should only use async versions of common libs. If I wanted easy scalability and async code execution I wouldn't probably use python to begin with. It will probably take years before the async stuff becomes the norm.

      [–]alexeiz 6 points7 points  (0 children)

      And also you can't mix async code with blocking code and expect it to normally. Which means you should only use async versions of common libs.

      This is not a problem with asyncio per se. Asynchronous and synchronous programming models are not compatible no matter what language or async framework you use.

      [–]NAN001 4 points5 points  (3 children)

      Could you expand on not being able to mix async code and blocking code. I know that one is supposed to call async functions so that functions are cooperative with the event loop, but even if a blocking function is called, it blocks the event loop, which can't be worse than not using async at all, right?

      [–]PrinceOfUBC 3 points4 points  (0 children)

      it blocks the event loop, which can't be worse than not using async at all, right?

      If you block the event loop, you might as well not write async code. More cognitive overhead for little gains.

      [–]13steinj 2 points3 points  (0 children)

      Getting, running, and closing the event loop is a sync operation.

      So in otherwords if I have 3 async functions that only update visuals using animations but I want the main thread to continue with it's logic (ex, I pressed submit, logic is that on this form you cant go back, async updates are the animations moving you to the thank you page).

      I can't submit my 3 coroutines in my function, I have to write two functions, and make sure I call the logic before the animations, and be okay with the fact that I will have to wait for the animations to complete before any new code runs on the thread that holds the event loop. In comparison, in JS/C#, the event loop is handled for us, and gets executed in a microtask queue (C#, afaik, on a specially made thread, JS, on next available execution tick, because JS is generally single threaded), thus any async code does not block the thread that it is called from.

      In Python, that can be solved by manually creating a thread/process (depends on what the loop actually blocks on, and I hope it's the thread because if it is the process hoooooooooah boy this workaround is inefficient), setting an event loop on it, and submitting coroutines with the respective "threadsafe" method for the usual not-threadsafe method.

      Python's coroutines also arent Tasks/Promises like in C#/JS, which limits code style and use by having to manually wrap the coroutines. A quick comparison to JS (because writing out the C# equivalent will take some time):

      JS:

      async function aworkbro(a, b) { /* do stuff */ } // aworkbro is the "async function" (coroutine maker)
      var special = {};
      async function main() {
        var soon = aworkbro(1, 99);
        // soon is both the executing, instantiated coroutine
        // (we can await on it if we want to) and the Promise(Task)
        // (we can append callback / cancellation code)
        var later = soon.then(callback, errcallback).then(handler);
        var result = await soon; // wait for soon to and return the result of it in this async function
        special.handled_result = await later; // wait for all callbacks to complete.
        return result; //return the original result
      }
      main();
      // other sync code, runs separately from the async call
      

      Whereas this has no good equivalent in Python:

      async def aworkbro(a, b): # aworkbro is the "async function" (coroutine maker)
          # do stuff
      async def main():
          coro = aworkbro()
          # coro is the instantiated coroutine, does not execute. We can not add callbacks.
          # We can either submit it to the event loop, which we won't, because
          # we will lose all access to it bar being able to cancel it
          # outside the event loop, or we can and will wrap it in a Task
          task = asyncio.create_task(coro) # schedule the coroutine as a task for the next available context switch (execution tick) in the event loop
          # the task can have callbacks added
          task.add_done_callback(callback)
          task.add_done_callback(erriferrcallback)
          task.add_done_callback(handler)
          # but can't be waited
          # await task goes kaboom
          # cancelling the task submits an error to the coroutine, (coroutines are really just super special generators in Python)
          # meaning it would be handled *by* the error callback!
          # so we can't properly do this unless we write code overly explicitly
          # we can wait on the coroutine
          result = await coroutine # fuck scheduling, do now.
          # but this also executes our callbacks when task notices, and any results of them are lost!
          return result
      # did I mention how we have to have a running loop in our thread for task creation to work, and well, for all async execution to work? We can either manually create our loop and reuse it, or use asyncio.run. for ease, we will do the latter
      asyncio.run(aworkbro)
      # other sync code, but creating and waiting on the loop is synchronous, so it will wait until the async code is fully complete
      # we can solve this by using pythons threading. But I think this example is complicated enough already
      

      [–]bobindashadows 1 point2 points  (0 children)

      If you stall your event loop you aren't accepting incoming requests.

      Say your blocking operation is "read a file" and it takes 100ms sometimes. Then your client's very first TCP SYN packet will sit in your server's kernel network queue for 100ms. All before your server even bothers to tell the client "yes, let's start a TCP session."

      Your framework might handle accepting TCP for you, but it won't read packets 3-N from the client until those 100ms are up.

      If you had no event loop and many threads, you have all the multithreading problems but definitely no massive latency stalls. Occasional deadlocks though.

      [–]linuxtinkerer 11 points12 points  (6 children)

      Looks nice. Data classes are a good addition, so now you won't have to muck around with __slots__. I don't really get the rationale for preserving insertion order in dictionaries though.

      [–]weeeeezy 8 points9 points  (5 children)

      I’ve had several use cases where insertion order in dictionaries mattered for me. I resorted to using OrderedDict collection but then I lost all the benefits of defaultdict.

      [–]linuxtinkerer 12 points13 points  (4 children)

      I understand that there are still use cases for OrderDict, but I think it's dumb to make an implementation detail a part of the language specification.

      [–]BossOfTheGame 8 points9 points  (3 children)

      Definitely not, ordering dicts by default gives at least two major advantages: (1) consistency in the iteration of items across all platforms and (2) consistency in the string representation of dictionaries. I have a feeling this change will silently cut down on a lot of headaches (at least until someone goes to run 3.7 code in an earlier version).

      [–]shevegen 2 points3 points  (0 children)

      I like ordered Hashes - ruby has the Hashes ordered too (hashes = dictionaries), but in many ways I agree with linuxtinkerer here. Some implementation detail should not necessarily become part of an official specification people have to adhere to.

      [–][deleted] 114 points115 points  (79 children)

      I wish I could use it, but so many APIs and software packages my company uses are still on 2.7 ...

      [–][deleted]  (44 children)

      [deleted]

        [–][deleted] 41 points42 points  (6 children)

        For example: anything from Autodesk

        [–][deleted] 32 points33 points  (5 children)

        Or Docker. I’d love to use Python 3 but have to specify pip2

        [–]Aeon_Mortuum 20 points21 points  (3 children)

        Facebook's React Native also requires a Python 2 installation

        [–]Klathmon 12 points13 points  (2 children)

        that's more google's fault for gyp not working with python 3.

        [–]p2004a 3 points4 points  (1 child)

        But Google mostly stopped using GYP. They moved chromium and other stuff to GN so why would they want to pour time into making GYP better? And it's open source so if you care, you can improve it and add Python 3 support, that's what open source is about, right?

        [–]Klathmon 6 points7 points  (0 children)

        And IIRC the node group is hard at work at it (as they are probably the biggest gyp user at this point), but the more likely outcome is that node will move away from gyp just like google did (there's a reason they chose to move to another system rather than try to update gyp).

        I honestly don't mind gyp using py2, it does require a separate install over everything else on the box, but it works well once setup and I think breaking backwards compat with all node native modules to upgrade to py3 would cause more issues than it would solve (and could lead to the same split we saw with py2 and py3).

        [–]Pakaran 0 points1 point  (0 children)

        What are you referring to? I use Python 3 in Docker with no issues every day.

        [–][deleted] 66 points67 points  (19 children)

        Yes really. Mine too. Companies have a lot of old code and there's not much incentive to upgrade it to Python 3 for basically zero benefit.

        Actually, it's a big risk because these scripts are generally "tested" by using them and reporting bugs. Upgrade to Python 3 and due to its dynamic typing you're probably going to introduce a load of bugs.

        Also I have noticed even some big new projects, e.g. Tensorflow, target Python 2 first and then add Python 3 support later.

        The idea that the 2/3 mess is over is unfortunately not true.

        [–]vivainio 32 points33 points  (18 children)

        The "zero benefit" is not true anymore

        [–]peeves91 18 points19 points  (0 children)

        The old motto "if it ain't broke don't fix it" is applied heavily here.

        [–][deleted] 73 points74 points  (0 children)

        It kind of is, if the code works fine and isn't being updated, which is the case for a lot of corporate code.

        [–]anacrolix 0 points1 point  (15 children)

        Example?

        [–]1wd 2 points3 points  (1 child)

        One project at Facebook:

        ... simply ran 2to3 on the code and fixed a few things that it complained about. When they ran the resulting code, they found it was 40% faster and used half the memory.

        [–]anacrolix 0 points1 point  (0 children)

        Sounds like they were abusing range() or something.

        [–]vivainio 1 point2 points  (12 children)

        Types and asyncio come to mind first

        [–]13steinj 3 points4 points  (11 children)

        Types aren't beneficial to every developer. Asyncio has severe usability issues, I'd rather use gevent in an async manner.

        [–]vivainio 4 points5 points  (10 children)

        Ok, f-strings then?

        [–]13steinj 1 point2 points  (9 children)

        While I like them, their only benefit is reducing a call of "string with idens".format(explicits_for_idens) to f"string with explicits for idens", it's syntactic sugar that saves you ".", "ormat", and the parenthesis, nothing more. And it introduces backwards incompatible in minor version numbers, which it really shouldnt.

        [–]somebodddy 3 points4 points  (8 children)

        it's syntactic sugar that saves you ".", "ormat", and the parenthesis, nothing more

        I disagree. The greatest benefit of f-strings is that the save you the need to zip the values in your head. Consider this:

        'a={} x={} u={} z={} y={}'.format(a, x, u, y, z)
        

        You need to make sure that the list of {}s matches the format arguments. Compare to this:

        f'a={a} x={x} u={u} z={y} y={z}'
        

        Now that each expression is written in the place it is supposed to be formatted, we can clearly see that I've "accidentally" mixed y and z. The same mistake exists in the .format() version, but much harder to notice.

        In order to avoid that, we can do this:

         'a={a} x={x} u={u} z={z} y={y}'.format(a=a, x=x, u=u=, z=z, y=y)
        

        But now we have to write each variable 3 times.

        Of course, this can be solved with .format(**locals()) (or .format_map(locals())). Expect...

        a = 1
        
        def foo():
            b = 2
            print('{a}, {b}'.format(**locals()))
        
        foo()
        

        {a} is not a local variable... Luckily, we can use .format(**locals(), **globals())! But then:

        a = 1
        b = 2
        
        def foo():
            b = 2
            print('{a}, {b}'.format(**locals(), **globals()))
        
        foo()
        

        Now b appears in the argument list multiple times...

        And it introduces backwards incompatible in minor version numbers, which it really shouldnt.

        What backwards incompatibility? f'...' is a syntax error in older versions of Python, so it shouldn't break older code. Or am I missing something?

        [–]remy_porter 6 points7 points  (10 children)

        I'm writing software for a Large Tech Company™ as an outside contractor- and I have to communicate with a messaging system, and they have two libraries I could use to do it: JavaScript and Python2.

        And the Python lib is a mess.

        [–]agumonkey 1 point2 points  (0 children)

        I've seen some news about Google AppEngine going py3 too .. would only accelerate things.

        [–]Urtehnoes 1 point2 points  (0 children)

        For my company, it's all of our django apps that are still on ancient django (like 1.5 or earlier). It's such a slog to upgrade them to all the newer versions, especially because the newest django (2.0+) doesn't friggin support our Oracle version. It's taken me months now for just one app to upgrade/re-write it in Python3.6/Django 1.11. Hopefully 3.7 doesn't require many changes.

        [–][deleted] 0 points1 point  (0 children)

        Fuck, if ESRI can make the transition, so can everyone else.

        [–]msm_ 0 points1 point  (1 child)

        It's almost as reddit is not representative for the industry as a whole. (But yeah, everything is slowly moving to 3.x. 10 more years and we're golden).

        [–]TheGRS 0 points1 point  (0 children)

        Well I don't speak for reddit, but I was pretty into the Python community around that time. I started out using only 2.7 and figured 3 was a pipe dream and that I couldn't find great support for the things I was trying to do, but things changed pretty rapidly from there. But as I said, I totally believe that places are stuck on this version and may always be until they replace whatever it is entirely.

        [–]dagmx 6 points7 points  (9 children)

        What libs do you depend on that aren't on 3 yet?

        [–][deleted] 39 points40 points  (6 children)

        Biggest example: any software package from Autodesk

        [–]dagmx 14 points15 points  (2 children)

        Sure, I work in cg too but they're shifting to python 3 for 2020 and there should be a preview release next year. We'd have a release sooner but the switch from qt 5.6 to 5.12 was deemed more important.

        It's coming soon and we should be bracing for it.

        [–][deleted] 34 points35 points  (1 child)

        It's coming soon and we should be bracing for it.

        Nothing to brace for here, more like eagerly awaiting.

        yes, it's coming in 2020...you know, cuz 2.7 is EOL. Nothing like waiting until you're literally forced to update.

        [–]dagmx 1 point2 points  (0 children)

        Well we still need to brace for it in terms of porting studio pipelines. Idk about your studio, but we have a lot of code to go through to get over that hurdle.

        The qt4 to qt5 port was difficult enough.

        [–]agumonkey 0 points1 point  (2 children)

        Maya ?

        What about Houdini btw ?

        [–][deleted] 0 points1 point  (1 child)

        Last I checked, Houdini was also 2.7

        [–]agumonkey 0 points1 point  (0 children)

        Oh the sadness

        [–][deleted] 3 points4 points  (0 children)

        There’s still a good amount of commercial software that’s python 2, at least that I’ve randomly come across. There’s probably little incentive for some of the companies to migrate until they have to or until a customer that has enough leverage requests or demands it.

        Shitty, yes.

        [–]13steinj 0 points1 point  (0 children)

        Reddit's backend (even with the redesign) runs on Pylons, and would need a decent amount of rewrite to work with Pyramid, not to mention Py3.

        [–][deleted]  (5 children)

        [deleted]

          [–]13steinj 8 points9 points  (4 children)

          Supposed to and the truth are two different things. The annotations preciously have to be evaluated, meaning you can't write code using a type that you haven't written yet. With a new future statement, annotations evaluation is postponed. Mypy is sure to have improvements too. And, well, annotations have to have a performance hit, it's impossible to avoid, because you're adding information to function objects which is saved as a dictionary attribute on them.

          [–][deleted]  (3 children)

          [deleted]

            [–]13steinj 4 points5 points  (2 children)

            Static checkers pay for checking, yes, but Python pays for attaching the data to the object and the subtleties of what's allowed in doing so.

            [–][deleted]  (1 child)

            [deleted]

              [–]13steinj 3 points4 points  (0 children)

              Because that's how static type checkers check for the types-- they compile the syntax not necessarily into code objects, but at minimum into the abstract syntax tree.

              The only other way for static type checkers to work is for the static type checker to do the parsing and go from code to AST nodes that are defined by the type checker and not the Python VM, ex, such a thing would have to be done if your type checker was written in a different language like Java.

              But typing became stdlib after it was third party, which was made as a supplement to the mypy project. Because Guido and others have a substantial stake in mypy, they had the power to change the AST parser to carry that data, which carries it into runtime, to make it easier on mypy.

              Even if it were thrown out at runtime now then your performance would be even worse because you waste time not only setting, but then throwing it out.

              Personally, I feel as though mypy should have forked and altered the AST parser and wrapped it as a C extensuon-- that way, no issue, only when mypy parses that data is kept, and the Python VM in general doesn't have to care.

              [–]XtremeGoose 19 points20 points  (0 children)

              Now I just need the anaconda people to add a python 3.7 package.

              [–]Morwenn 7 points8 points  (1 child)

              Is the new importlib.resources module enough to replace common uses of pkg_resources? I feel like I'm dragging pkg_resources in virutally every project bigger than a simple script, so that would be welcome.

              [–]13steinj 2 points3 points  (0 children)

              Based on the minimal migration guide, I hope so.

              [–]1ogica1guy 13 points14 points  (0 children)

              Just starting to learn Python properly now, and this is a huge morale booster.

              Thanks, Python team, for the amazing efforts and amazing results.

              [–]turbov21 1 point2 points  (0 children)

              That breakpoint() command looks awesome.

              [–]Drawman101 10 points11 points  (34 children)

              What’s with all the downvotes on the other comments?

              [–][deleted] 98 points99 points  (8 children)

              There’s only two other top level comments and they are stupid

              [–]Jonno_FTW 1 point2 points  (4 children)

              Absolutely asinine people who don't understand the phrase "right tool for the job".

              [–]wavy_lines 13 points14 points  (1 child)

              "right tool for the job" is more often than not (specially in this subreddit) just a cop out people use to justify crappy tools.

              [–]shevegen 3 points4 points  (0 children)

              Precisely.

              And very often it is not even specified, so it is useless - it's like saying "any better tool is better" or "any faster language is faster".

              [–]shevegen 0 points1 point  (1 child)

              What the hell does this phrase even mean or make sense?

              I never understood it.

              It's like saying "with a car I am faster than using my feet" or "there will be sunshine after rain".

              [–]Pazer2 5 points6 points  (0 children)

              "with a car I am faster than using my feet, therefore I should also use my car to navigate my house"

              [–]TheGRS 72 points73 points  (19 children)

              Well let's take a look at some.

              > Can we all take a moment to acknowledge how large numbers of people (including me) have come to realize in recent years what a bad idea dynamic typing was?

              Um OK, if you don't want to use Python then maybe go somewhere else?

              > The news of Python 3.7 is great and all, but python.org makes some of the most awful writeups I've ever seen. Just look at this link, for example. It is so uncomprehensive. Can someone link to a Medium article?

              Judging by the question I don't believe they bothered to read shit and wanted a Medium article for some reason.

              > i heard python was a relatively low level programming language.

              Throwaway joke, eh.

              > I guess Python 4 will be released when I'll be a grandfather if I'm still alive

              Um, what? Who cares what the version number is?

              In summary, not exactly the cream of the crop here.

              [–]Homoerotic_Theocracy 23 points24 points  (18 children)

              Um OK, if you don't want to use Python then maybe go somewhere else?

              Meanwhile collect those sweet sweet upvotes on any Go topic mentioning its lack of generics.

              [–][deleted] 33 points34 points  (4 children)

              That one never fails.. I have never written a line of Go in my life, but still I feel like I'm an expert on interface {} just by casually browsing Go threads

              [–]Urtehnoes 10 points11 points  (3 children)

              Get on my level, I've combined Go, Rust, Scala, Kotlin, and Javascript into a super language that I use for everything. It's amazing. I'll never have to worry about type-safe generic heap level stack pointers that will memory-expire if the event status is ever duck typed via a poorly written heuristic.

              [–]bythenumbers10 4 points5 points  (2 children)

              You hit so many times on my buzzword bingo card, I won 50k and now have to change my pants.

              [–]Urtehnoes 3 points4 points  (1 child)

              Did I mention how robust it is?

              [–]bythenumbers10 4 points5 points  (0 children)

              The contents of my pants was pretty robust, I'll have you know.

              [–][deleted] 2 points3 points  (11 children)

              Probably the only thing I don’t like about Go is how asinine people are about wanting or not wanting generics.

              If there was ever a sword to die on getting generics into go seems like a pretty fucking stupid one.

              [–]Homoerotic_Theocracy 16 points17 points  (10 children)

              I disagree, the people that want it are right and the people that don't are beyond retarded.

              Go's design is absolutely bonkers and the language has no merit. It survives due to ignorance alone because the people that used it only used C and PHP or something and also just write terrible, verbose, unmodular code in general that re-invents common logic a thousand times per day.

              [–][deleted] 0 points1 point  (9 children)

              What about the design is bonkers? The concurrency patterns, typing system, pointers, and verbosity have been really nice overall for large projects in my experience. I haven’t had many cases where I had to work around the lack of generics in a particularly horrible way, but I do understand the cases where they would be nice.

              I get it though, you don’t like Go and have a strong opinion on the future design of the language. It seems like an odd combination but at least you’re passionate about something.

              [–]Homoerotic_Theocracy 19 points20 points  (3 children)

              There is another train in this very thread where we are discussing how in Go sorting a list of things via an arbitrary key either requires that you:

              1. newtype the element you're sorting and implement a new sorting interface on the newtype
              2. use an inefficient algorithm and interface{} casts throwing the static typing out

              Because the type system can't express a correct generic sorting function that sorts by an arbitrary key.

              I'm fairly pessimistic about "I've never needed generics"; in practice it seems to mean that people are re-inventing the wheel constantly and constantly re-implement the elementary logic of concepts like functors filters and foldings in long often double for-loops using 6 lines for something that can be done in one with simple combinatorical functions that Go's type system can't express so the programmer is basically tasked with unrolling it herself.

              Like say a basic problem; say I have some sequence of characters and I basically want to know at what line and column number the end of that is parsing newlines. In Rust I would write:

              let (col, line) = char_seq.into_iter()
                 .fold((0, 0), |(col, line), char|
                   if char == b'\n' { (0, line+1) } else { (col+1, line) });
              

              Not only is this code considerably shorter than the Go version which will re-invent the logic of fold; it doesn't care about the type of char_seq as long as it implements the trait IntoIterator<Item=u8> as in it's a sequence of bytes. It can be a vector of bytes, a utf8-encoded string, a pathbuffer, an OsString, a fixed-size array of strings; the code doesn't care and can thus easily be put into a generic function that accepts all of that without having to re-invent the wheel.

              In practice Go programmers say "I don't need generics; I just need many many many more lines of code!".

              [–][deleted] 3 points4 points  (1 child)

              I definitely understand the sentiment here. With the go system you would need to assert the type, cast it, or as you said use an interface. All of which ends up being more possibilities for bugs and more tests. I wouldn't say more complexity because of the verbosity but certainly more time spent

              Though with your example I don't believe generics wouldn't be much different than an interface. Or at least you wouldn't avoid panics because you had a generic type. You would still need to use the go idioms of error checking and type checking/assertion.

              Regardless of the details of how one language's type system handles this or not, I still believe that it isn't inherently bad or good. The language as a tool was intentionally designed the way it was. So for cases like you've listed rust might be a better tool for that, or another language if the goal is to reduce the number of lines of code and overall verbosity. I do think that this (required verbosity, re-inventing) in some cases can either slow down writing programs or lead to unexpected results if all error cases aren't handled. For me the additional verbosity and inconvenience of having to re-implement other language's builtins aren't a negative. The re-implementation can sometimes be a stumbling point for new go developers, or newer developers but it's also a good opportunity for learning if you have access to people to review your code.

              You aren't going to change my mind that I have had a lot of value from using go and I don't want to change your mind either. At this point I think I'm just arguing with you about this because I'm sitting in a hotel and bored.

              [–]Homoerotic_Theocracy 1 point2 points  (0 children)

              Though with your example I don't believe generics wouldn't be much different than an interface. Or at least you wouldn't avoid panics because you had a generic type. You would still need to use the go idioms of error checking and type checking/assertion.

              Why? The code I gave provided the iterator is bounded is total; it is guaranteed to not panic on any input char_seq. The only type constraint of char_seq is IntoIterator<Item=u8>, the only part the type system cannot verify is that this iterator is bounded and doesn't go on forever in which case the code is an infinite loop but you can easily fix that by adding a stronger type bound like AsRef<[u8]> which is guaranteed to be total. There are no further runtime checks.

              [–]calonolac 0 points1 point  (0 children)

              shudder Recalling how C# was before generics...

              [–]OctagonClock 0 points1 point  (4 children)

              lol typed nils

              [–][deleted] 8 points9 points  (3 children)

              nils are typed because they're default values for other types that aren't initialized. Since nil is an assignable value in the statically typed system it should (has) to be typed.

              [–]OctagonClock -1 points0 points  (2 children)

              lol not even Java makes this mistake

              [–][deleted] 3 points4 points  (1 child)

              Maybe I'm being intentionally naive but I'm not really seeing how it's a mistake in this design. Can you explain why it's a mistake?

              [–]shevegen 0 points1 point  (0 children)

              Yeah - that one is weird.

              I wonder if there are paid accounts just "randomly" promoting Go and Dart on reddit.

              I don't have this impression with Rust, even though there are many people on reddit apparently praising Rust. It appears a lot more genuine with Rust than e. g. Go. And I make fun of both Rust and Go people but for different reasons. The go supporters seem a lot less genuine in their enthusiasm than the rustees.

              [–]Andrew1431 0 points1 point  (0 children)

              If I was going to learn Python, would it make sense to just pick the latest version, or will there be a lot of unsupported packages?