3 ms·
This is an implementation detail, and abstractions shall never be conflated with their possible implementations We're talking about performance here, right? So
by sievebrain 10y ago
This is an implementation detail, and abstractions shall never be conflated with their possible implementations
We're talking about performance here, right? So unfortunately this statement is totally untrue in that context.
Java world wants value types largely to avoid pointer chasing that hurts cpu cache effectiveness. Haskell suffers the same issue, then. You can make what are effectively value types in Java as long as you don't use == to compare but rather .equals, make all the fields final, override toString/equals/hashcode etc, and more sensible JVM targeting languages of course convert == into calls to .equals by default.
- catnaroek 10y ago> We're talking about performance here, right? So unfortunately this statement is totally untrue in that context. You don't need implementation details to discuss performance. Abstractions can come with a cost model. (C++'s standard library concepts are a great example of this.) And Haskell's cost model says that values can be passed around in O(1) time. > Java world wants value types largely to avoid pointer chasing that hurts cpu cache effectiveness. Haskell suffers the same issue, then. That's not the whole story. When the physical identity of an object no longer matters (note that immutability alone isn't enough), the language implementation can, without programmer intervention: (0) Merge several small objects into a single large object. (Laziness kind of gets in the way, though. ML fares better in this regard.) (1) Use hash consing or the flyweight pattern more aggressively. > You can make what are effectively value types in Java as long as you don't use == to compare but rather .equals, make all the fields final, override toString/equals/hashcode etc, and more sensible JVM targeting languages of course convert == into calls to .equals by default. But the JVM itself is completely unaware that you intend to use a class as a value type, and thus can't automatically apply optimizations that are no-brainers in runtime systems for languages where all types are value types. Also, `.equals()`'s type is broken: it allows you to compare any pair of `Object`s, but it should only allow you to compare objects of the same class.
- jstimpfle 10y agoWhat you say is not incorrect. But you totally miss the context of the discussion. And you switch sides just to disagree with your last quote.
- eru 10y ago> And Haskell's cost model says that values can be passed around in O(1) time. I am not sure of that. The compiler is free to inline expressions, or otherwise evaluate them multiple times.
- sievebrain 10y agoI know what optimisations identity-less aggregates allow. Objects can be passed around in O(1) time in any language that uses references. It's not the issue. Indeed passing value types is O(n) in the size of the value type, so that's a loss. The goal is to avoid data dependent loads (i.e. pointer dereferences) by flattening/inlining data structures. As you point out, Haskell could in theory merge things together and lay out memory more effectively, but in theory so could Java with e.g. interprocedural escape analysis. But in practice there's a limit to what automatic compiler optimisations can do - learning this the hard way is a big part of the history of functional languages (like, how many functional language runtimes automatically parallelise apps with real speedups?). Java sometimes does convert object allocations into value types via the scalarisation optimisations, but not always, hence the desire to add it to the language.
- catnaroek 10y agoPassing around copies is O(n) in the size of the copy. This has nothing to do with call-by-value, and all with the retardedness of having to defensively clone objects to cope with arbitrary mutation.