Re: 7.0 wishlist?
- From: hzergel901@xxxxxxxxx
- Date: Sun, 16 Nov 2008 19:07:02 -0800 (PST)
On Nov 14, 11:56 am, Andreas Leitgeb <a...@xxxxxxxxxxxxxxxxxxxxxxxx>
wrote:
That point not taken. The only reason why a Square would not be a
Rectangle (in Java) would be a goofy contract attached to the Rectangle.
Imho, this is an entirely different pair of shoes than whether
commutativity is broken by side-effects of the operands.
Interestingly, those different pairs of shoes still fit the same feet,
to continue the metaphor.
Both problems arise from having mutable value-objects in the system.
Immutable Rectangles don't have the problem with Square, as was
pointed out elsewhere in this thread (which, since my name came up in
it, I have since had the time to read more-or-less thoroughly).
And immutable mathematical value-types have operations that don't
(semantically*) have side effects.
* They might internally cache information; for example, a Matrix its
determinant, computing it lazily when it's first requested. Then if
m.getDeterminant() appears multiple times in an expression,
technically this has a side effect, but semantically it doesn't; the
point is that the semantics of the determinant are that it is an
immutable property of the immutable Matrix and so it does not matter
which of the calls to m.getDeterminant() in a particular expression
(if any; it might already have been computed earlier) actually
computes it; all of the calls return the same scalar and the Matrix's
identity is not mutated, unlike an int being affected by expressions
containing "i++".
(The above assumes correct code).
Immutability solves an awful lot of problems with value types. Or
rather, mutability CAUSES an awful lot of problems with value types.
Even given mutability, though, I don't see the problem with the
operator overloading proposal at issue, which resembles one of my own
suggestions of a year or so ago. As long as the translation of
operators into method calls is well-specified, with the future JLS
version clearly explicating what pre-overloading code has the same
semantics, then programmers can figure out when, in what order, and
how many times any side effects will occur. Just as they presently can
when an expression has multiple occurrences of "i++" in it.
And, then as now, code that depends on such JLS-lawyering for its
correct interpretation will be bad (i.e. essentially unmaintainable)
code, and, then as now, making value types immutable will be vastly
preferable to making them mutable.
Anyway, (to return one level back in the discussion), demanding
that (intValue + SomeClassInstance) could always be rewritten to
(SomeClassInstance + intValue) is goofy
I don't agree; that is, I agree with Harold that + should be
commutative. Non-commutative arithmetic-like operations should
generally be regarded as being multiplication-like rather than
addition-like. This is the usage among mathematicians; generally they
use * or x or . or similar symbols for potentially non-commutative
operations and only + for commutative ones. (I took abstract algebra
too -- and I took it all the way to graduate level, with straight As.)
If anything, a problem with Harry's proposal is that .plus could be
implemented to be noncommutative. And any of these could be made non-
associative, too. But the possibility that someone will write bad code
is not reasonably avoidable (and sometimes there's a use for non-
associative operations, though heaven forfend that anyone call THOSE +
instead of *).
Interfaces might also be used; for example, + might require at least
one operand implement Addable<OtherOperandsType>, which specifies
plus, and not just that it have the plus method. That would have
problems with the present inability to implement both Addable<X> and
Addable<Y> in the same class. Reified generics might fix that.
Given such a fix, Addable and similar interfaces enable extending
java.util (or java.math?) with useful new things, for example an
accumulate method that can take a Collection<Addable<Foo>> and return
a Foo that is their sum, or an Accumulator<Foo> that can perform
accumulations. Indeed, an Accumulator class can be polymorphic with a
suitable factory method to get one, and can special-case some things,
for example by making a request for Accumulator<String> supply a
StringBuilder(!) (with .plus and .getValue added that punt to .append
and .toString) or with multiple methods (say, accepting an
Iterable<Foo>, an Iterator<Foo>, or Foo... -- with both of the above,
you can do accumulator = Accumulator.getInstance(String.class),
accumulator.accumulate("foo", xString, "bar", "baz", yString),
accumulator.getValue(). Or rather, the compiler can turn "foo" +
xString + "bar" + "baz" + yString into an accumulation, and can even
turn other + chains (if it assumes + is commutative, associative, and
non-mutating, which assumption would be documented) into accumulations
that might be more efficient, effectively generalizing the present
special-casing of chains of String +s to all Addables. Addable's
contract would specify that .plus be commutative, associative, and non-
mutating -- no worse than the existing equals and hashCode contract,
comparable and equals contract, and similar contracts the compiler
can't enforce, really. Accumulator would need three type parameters to
fully generalize this -- left-summand type, right-summand type, and
result type; StringBuilder would implement
Accumulator<String,Object,String> since it can add any Object to a
String and return a String, for instance.
Does the above sound somewhat complex, and somewhat like work? Yes,
but consider the possible benefits to math/engineering code, and even
to String-handling code, as well as the complexity of some existing
features of Java, like the triangle of Object.equals, Object.hashCode,
and HashMap/Set, or the triangle of Object.equals, Comparable/
Comparator, and TreeSet, that require user-provided objects to adhere
to contracts not entirely compiler-enforceable and sometimes with
subtle gotchas (hashCode being forgotten, compareTo using naive
arithmetic that may wrap, etc.).
Are the results worth it? Those working a lot with scientific/
mathematical computations would probably say yes. Those not doing so
really needn't care, I expect.
.
- Follow-Ups:
- Operator overloading [was Re: 7.0 wishlist?]
- From: Joshua Cranmer
- Operator overloading [was Re: 7.0 wishlist?]
- References:
- Re: 7.0 wishlist?
- From: Harold Yarmouth
- Re: 7.0 wishlist?
- From: Joshua Cranmer
- Re: 7.0 wishlist?
- From: Harold Yarmouth
- Re: 7.0 wishlist?
- From: Joshua Cranmer
- Re: 7.0 wishlist?
- From: Harold Yarmouth
- Re: 7.0 wishlist?
- From: Joshua Cranmer
- Re: 7.0 wishlist?
- From: Harold Yarmouth
- Re: 7.0 wishlist?
- From: Joshua Cranmer
- Re: 7.0 wishlist?
- From: Harold Yarmouth
- Re: 7.0 wishlist?
- From: Joshua Cranmer
- Re: 7.0 wishlist?
- From: Harold Yarmouth
- Re: 7.0 wishlist?
- From: Joshua Cranmer
- Re: 7.0 wishlist?
- From: Andreas Leitgeb
- Re: 7.0 wishlist?
- From: Joshua Cranmer
- Re: 7.0 wishlist?
- From: Andreas Leitgeb
- Re: 7.0 wishlist?
- From: Joshua Cranmer
- Re: 7.0 wishlist?
- From: Andreas Leitgeb
- Re: 7.0 wishlist?
- Prev by Date: Re: the Java Lang will support Properties in Futuere?
- Next by Date: WWW.HONESTAAA.COM OFFER NIKE JORDAN, PRADA, ADIDAS, PUMA GUCCI UGG SHOES
- Previous by thread: Re: 7.0 wishlist?
- Next by thread: Operator overloading [was Re: 7.0 wishlist?]
- Index(es):
Relevant Pages
|