Earlier quoted context omitted.
That's not a deeper lesson. A deeper lesson is to understand where the pointer points to and then decide accordingly.
That is pretty much what I said, except phrased different.
Making a Go program faster with a one-character change
171–180 of 249 posts
Re: Making a Go program faster with a one-character change
#172> You can see these decisions being made by passing -gcflags=-m to go build: That's a very nice feature! I wonder if compilers for other languages have something similar.
Re: Making a Go program faster with a one-character change
#173Earlier quoted context omitted.
> As far as I know, Java's (default) runtime gives cheap allocations at the cost of long GC pause times. "long GC pause times" is kind of vague, so I guess you could be correct, but in practice there's a LOT of different ways the memory management can be handled, many of which are deemed "pauseless GC" (though the term is somewhat misleading). My statement was considering that reality though. While not true for some…
> in practice there's a LOT of different ways the memory management can be handled, many of which are deemed "pauseless GC" (though the term is somewhat misleading). Yes, but I'm pretty sure those "pauseless GC" schemes impose other tradeoffs. > My statement was considering that reality though. While not true for some use cases, in the vast majority of cases, the runtime optimizes the allocations more than sufficient…
Re: Making a Go program faster with a one-character change
#174Earlier quoted context omitted.
Yup, it's definitely a bit of a code smell if you do. The issue is more the reverse, though - I can't make a mutable map, then hand it by pointer/reference to something that says it wants an immutable map later.
Not necessarily a bad thing either, things can get odd if you're not the only owner and it's mutated under you unexpectedly.
std::unordered_map m;
m["foo"] = "bar";
std::unordered_map m2 = m;
doesn't compile.Re: Making a Go program faster with a one-character change
#175Earlier quoted context omitted.
Agreed. Could you Imagine a Java where you have a `Map` and a `MutableMap` and that's what you put at your API? I'd make it SO much clearer how safe any individual API is to call.
In general this doesn't work, the history rule says mutable types are not proper subtypes of immutable ones (and the converse is obvious). If you want to capture mutability in your type system, it needs to be orthogonal to subtyping (like C/C++ const).
Conceptually, you can have constness in your subtype-system (as long as you are sticking with interfaces (methods), as Liskov's subtyping model does, and aren't inherting potentially-mutable fields).
MutableMap and ImmutableMap are both subtypes of a hypothetical ReadableMap. ImmutableMap is the same as ReadableMap, but has an informal contract that subclasses shouldn't add mutability.
Re: Making a Go program faster with a one-character change
#176Earlier quoted context omitted.
In general this doesn't work, the history rule says mutable types are not proper subtypes of immutable ones (and the converse is obvious). If you want to capture mutability in your type system, it needs to be orthogonal to subtyping (like C/C++ const).
> the history rule I'm unfamiliar with this rule (and not finding anything good to google). Can you elaborate? I can't really think of a scenario where an immutable datastructure isn't a subset of actions against a mutable datastructure.
> History constraint (the "history rule"). Objects are regarded as being modifiable only through their methods (encapsulation). Because subtypes may introduce methods that are not present in the supertype, the introduction of these methods may allow state changes in the subtype that are not permissible in the supertype. The history constraint prohibits this. It was the novel element introduced by Liskov and Wing. A violation of this constraint can be exemplified by defining a mutable point as a subtype of an immutable point. This is a violation of the history constraint, because in the history of the immutable point, the state is always the same after creation, so it cannot include the history of a mutable point in general. Fields added to the subtype may however be safely modified because they are not observable through the supertype methods. Thus, one can define a circle with immutable center and mutable radius as a subtype of an immutable point without violating the history constraint.
[1]: https://en.wikipedia.org/wiki/Liskov_substitution_principle#...
Re: Making a Go program faster with a one-character change
#177Earlier quoted context omitted.
> The performance issue here is not value semantics There's no performance cost to value semantics, so of course not. > The copy is cheap. The lifetime tracking is not because it forces a heap allocation and creates additional GC pressure. In fact, assuming Rule is small, if Match returned by value, the code would be similarly as fast. I'm referring more to how this stuff seeps in without the programmer realizing it.…
Sorry, because of value semantics. (Also, you wrote "performance costs of inopportune value semantics". So the correction is annoying; you know what I meant.) This stuff seeps in without the programmer realizing it because Go made a deliberate design decision to have automatic lifetime management. In other words, this is a feature of the language and not a bug. The only way for this to not seep in is if Go forced pro…
I would disagree about this stuff seeping in because of automatic lifetime management. The equivalent code in Java, Smalltalk, etc., would either not have the performance problem or it would be much more obvious that the code wasn't as efficient as it could be.
Re: Making a Go program faster with a one-character change
#178Earlier quoted context omitted.
Sometimes it doesn't matter if a public API is incorrect, because it's set in stone for whatever reason, and you just need to fix the problem internally.
This is why I like https://github.com/openrewrite so much. One gets to tell users how to rewrite code automatically. It makes refactoring almost as easy as in a mono repo.
In my head, the ideal flow would be an annotation on your library function/class which triggers an IntelliJ suggestion for downstream users affected by your breaking change to run the automated refactor for them. Kinda like a more helpful @Deprecated.
Re: Making a Go program faster with a one-character change
#179Earlier quoted context omitted.
> I've only ever found myself missing value semantics when I use languages with implicit reference semantics. Oh, I miss it every time. ;-) I will say though that some newer languages seem to have a confused idea about how to offer mixed semantics. A bunch of them tie semantics to types. The ideal interface can vary by usage context. It's hard enough getting the semantics right as the callee (as opposed to caller), l…
> I will say though that some newer languages seem to have a confused idea about how to offer mixed semantics. A bunch of them tie semantics to types. Curious about what you mean here. This sounds like C#'s class/struct distinction to me.
Re: Making a Go program faster with a one-character change
#180So, this is very basic Go design and you could write something about how it works in C and Go and why a older lang like C don't have this prob but then at the end of the day the Go fanclub will down vote the hell out you no matter what.
Go compiler is garbage by the design. A 20 year old C compiler does not have this prob. This is also why Go have declined so much during the last couple of years. The benefits of Go have not increased and most of the quirks are still there. Like the error handling, the naive compiler and the syntax sugar that somewhat hides the diff between pointers and direct heap allocs. -1