Earlier quoted context omitted.
> Nearly every big fix in an API is technically a breaking change if you want to be pedantic. A fix is not a breaking change in the API, because “breaking” refers to expected behavior (so, yes, code that relies on a bug can be broken by a fix; presumably, if you've coded to an observed behavior differing from the spec you are aware of having done so.)
There is even a name for that https://www.hyrumslaw.com/ The solution clearly can't be to never ever fix bugs though. But depending on the kind of bugs (especially when they are of the "gotcha"/"UX" kind) often it's better to just create a new API version with the corrected behaviour and keep existing software apply handle the old behaviour the best they could. But clearly for many many other kinds of bugs (security…
Go Replaces Interface{} with 'Any'
421–430 of 481 posts
Re: Go Replaces Interface{} with 'Any'
#422Earlier quoted context omitted.
I’ve used all those languages. It’s far easier to make sense of a non trivial go code base I’ve never seen before than any of those.
It's far easier for you . It definitely isn't for me or in general . Thank you for answering the list of languages though. Makes me wonder what the concrete points are for, since I really have a different opinion. Maybe our minds just work very different; :)
1. Some languages on your list are very flexible, and that allows them to be written in a very readable form with great discipline. People tend to not have great discipline thought, for various reasons: their bosses are pushing them to go faster and cut corners, they aren't experienced enough yet, etc. I'd say that python and typescript/javascript fall into this category.
2. I think inheritance is the devil, and a more functional style is better (by functional I mean first class functions, passing parameters, etc not purely typed). Java/Groovy fall into this category, they overuse inheritance and things like dependency injection with xml or annotations rather than far easier to read function calls with parameters.
3. Then there is haskell :) Haskell requires a phd in rocket science to be proficient, and most people have other things they want to do with their life. You also can't hire a team of 1000 rocket scientists so most companies can't go this route.
Edit: One other thing I'll add about typescript/javascipt because it's a bit of an oddball. There really isn't a typescript/javascript style because most devs end up writing javascript. The java people try to write java in it, the python people python, etc. This alone makes it hard to jump into a random JS/TS codebase and figure out what's going on.
Regarding Go, it takes away a lot of flexibility, which makes the code longer generally, but it makes it much more consistent across code bases. It's lack of inheritance prevents the devil from showing up, and it's largely a simple function call with parameter passing style all the way through the code base. Structural typing is also a godsend.
Edit 2: Also, package management in python is a complete train wreck.
Re: Go Replaces Interface{} with 'Any'
#423Earlier quoted context omitted.
> I’d kill for union types as well. > … and pattern matching. Maybe just some extensions for `switch`. Go has type switches which are… ok. If it were possible to “close up” interfaces and type switches took that in account (match completeness) you’d be done about done, you would not have the structural / patterned unpacking but that’s probably less of a concern.
the fact that the set of types that can satisfy an interface is open is the source of their power. "closed interfaces" are broadly an antipattern in Go.
Re: Go Replaces Interface{} with 'Any'
#424Earlier quoted context omitted.
Only subtractive changes and eg performance changes would not break things in the grandfather comment's scheme.
I did not in any way shape or form "propose a scheme." I pointed out what I perceive to be a limitation in semver to describe some kinds of changes in some kinds of things in practical terms. These replies are incredibly and bizarrely dogmatic. I never knew it'd be so hard to have a discussion about semver without people just going "semver is semver" as if that means something.
You seem to have misunderstood. We're not pointing out that "semver is semver", we're pointing out that semver as defined with respect to compilers, which is to say, the ability of existing code to run with a new version of the compiler, and what you "perceive to be a limitation in semver" are fundamentally in tension.
The only non-perf changes that would be allowed as non-breaking changes if we addressed what you perceive to be limitations in semver are precisely those changes which would be breaking in semver-as-it-exists, and those permitted in semver-as-it-exists are precisely those which you perceive as limitations.
Happy to discuss semver, but fundamentally the thing here is that what would address your perceived limitations is... the literal opposite of semver. Which is fine! But something not being its literal exact opposite isn't exactly a flaw in the thing itself; you simply want something else entirely.
Re: Go Replaces Interface{} with 'Any'
#425In related news, does anyone have any idea when a new edition of Kernighan and Donavan's gopl will be released to include all the changes since 2015? https://www.gopl.io/
Re: Go Replaces Interface{} with 'Any'
#426Earlier quoted context omitted.
> Python does And it's awful. I use EAFP locally (to avoid TOCTOU and the like) at low level interfaces but I don't let it bubble up out of a function scope, because it is a goto in all but name. I've also been increasingly using the `result` library/data structure. It's incredibly liberating to return an error as an object you can compose into other functions, vs try/catch, which does not compose. Yes I write python…
Maybe I'm just too inexperienced, but I don't see the point of this library. The linked example shows a really basic sqlalchemy model lookup. What does spewing these new types all over my code get me that returning None or an empty dict/list doesn't without the overhead? def find_user(user_id: int) -> Optional[User]: user = User.objects.filter(id=user_id) if user.exists(): return user[0] else: return None Not only is…
No, it doesn’t. For a single computation like this, that pattern is roughly equivalent to Maybe (which contains no information about the case where there is no success result besides that it is absent) rather than Result (which has error information, kind of like an exception, but in the normal return path.)
For a series of computations, the composability of both Maybe and Result means that they are semantically richer.
Re: Go Replaces Interface{} with 'Any'
#427Earlier quoted context omitted.
Typescript is stricter and safer while also being less obtrusive than Go
Typescript is also far slower both in terms of runtime and compilation time, uses much more memory, and is far more complicated which in turn has led to a ton more compiler bugs. It also inherits a ton of questionable features and API decisions from Javascript and has a tiny standard library which means most Typescript developers repeatedly end up turning to the NPM ecosystem which is an unmitigated disaster. Deploym…
Re: Go Replaces Interface{} with 'Any'
#428Earlier quoted context omitted.
Maybe I'm just too inexperienced, but I don't see the point of this library. The linked example shows a really basic sqlalchemy model lookup. What does spewing these new types all over my code get me that returning None or an empty dict/list doesn't without the overhead? def find_user(user_id: int) -> Optional[User]: user = User.objects.filter(id=user_id) if user.exists(): return user[0] else: return None Not only is…
> Not only is this idiomatic, it conveys the same semantic meaning No, it doesn’t. For a single computation like this, that pattern is roughly equivalent to Maybe (which contains no information about the case where there is no success result besides that it is absent) rather than Result (which has error information, kind of like an exception, but in the normal return path.) For a series of computations, the composabi…
Also, both Django and SQLAlchemy throw proper exceptions on bad queries or DB errors, which is probably the right thing to do in the average app using these libraries (the exception bubbles up, getting logged, returning the appropriate http error, etc).
I'm not crapping on this library, mind, I just can't find the use case that justifies it.
Re: Go Replaces Interface{} with 'Any'
#429Earlier quoted context omitted.
> Not only is this idiomatic, it conveys the same semantic meaning No, it doesn’t. For a single computation like this, that pattern is roughly equivalent to Maybe (which contains no information about the case where there is no success result besides that it is absent) rather than Result (which has error information, kind of like an exception, but in the normal return path.) For a series of computations, the composabi…
Couldn't I just return a tuple instead if I wanted to give the caller information on the nature of the success or failure? Also, both Django and SQLAlchemy throw proper exceptions on bad queries or DB errors, which is probably the right thing to do in the average app using these libraries (the exception bubbles up, getting logged, returning the appropriate http error, etc). I'm not crapping on this library, mind, I j…
How do you compose a function that returns an int or an error with a function that takes an int as parameter?
Yes you can split this in multiple steps, or you can use monads to handle the composition for you, making you type less code, giving more information to the typesystem (mypy for python for example) about what is valid and what's not.
This is a completely different programming style, it's functional programming, aka: "how to make functions by composing other functions".
Re: Go Replaces Interface{} with 'Any'
#430Earlier quoted context omitted.
I’ve used all those languages. It’s far easier to make sense of a non trivial go code base I’ve never seen before than any of those.
It's far easier for you . It definitely isn't for me or in general . Thank you for answering the list of languages though. Makes me wonder what the concrete points are for, since I really have a different opinion. Maybe our minds just work very different; :)
For me an easy to understand program is one where the way memory is structured and the way execution modifies said memory is easy to follow. That's why Go, despite being very verbose in some cases, it's easier to reason about, than codebases doing similar things in higher level programming languages.