B
bbound
I would say 99.99% probability.
Wrong!
I would say 99.99% probability.
Joshua Cranmer said:[example snipped, as it boiled down to exactly my prognose]Andreas said:what type of rectangle-related contract do you have in mind?Joshua Cranmer said:Note, for example, that making a Square class extend a Rectangle
[...] would fail to match the Rectangle's contract.
I hope it is not something like "width!=height must be allowed"
And that is, what I consider an #1 example of a goofy contract.The idea that changing the height does not change the width is what is
violated.
Arne Vajhøj said:http://java.sun.com/docs/books/jls/third_edition/html/arrays.html
section 10.2 say:
"A variable of array type holds a reference to an object."
I think I can say that arrays are passed by value.
Andreas said:And that is, what I consider an #1 example of a goofy contract.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
(e-mail address removed) schreef:
Does anybody understand this?
If I say "the one true editor" you'll have a 50% chance of guessing right.
That point taken.Joshua Cranmer said:Well, first off, the entire example is contrived.
But in any case, most people would agree, on only seeing the Rectangle
class, that assertContract should always succeed
The point still remains, though, that structures from mathematics are
not directly transferable to code.
Andreas said:That point taken.
I'm seemingly not "most people". I'd think about fix-proportioned
rectangles, where changing the width would auto-adjust the height
and vice versa. I have seen applications that behaved that way:
you grew/shrunk it in height, and it grew/shrunk in width
proportionally. And it made sense for these.
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.
Andreas said:here neither the 0+,o+,O+ nor -> digraphs are
assigned the same way as they seem to be on your machine.
He uses it when someone other than him replies to a post that he
thinks only he should reply to, often/usually one that he thinks
requires a reply from him. How this is a "feedback loop" --
as I understand it, the idea is that these not-from-him replies
result in there being yet more posts to which he must reply.
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.
Anyway, (to return one level back in the discussion), demanding
that (intValue + SomeClassInstance) could always be rewritten to
(SomeClassInstance + intValue) is goofy
[email protected] said:[implied insult deleted], H.No. None of the nasty things that you have said or implied about me
are at all true.
Hold on. Wasn't "Harold" denying being yet another alias for Twisted?
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).
* 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).
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.
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.
> 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.
A reason why immutability is a good thing. In any case, the intent I
attempted to convey was the fallacy of naïve translation of mathematical
concepts to programming.
A side effect is a side effect. True, some may be only visible to the
internal code in the API, but, as far as the JLS is concerned, it's a
side effect if some Java code could detect the difference.
While users ideally need only deal with correct code, the specification
must deal with any valid code.
To paraphrase a CSS spec developer: "You
may not worry about what a web page looks like on a 3x3-pixel screen,
but a browser has to worry about that."
I doubt a change that would break either of these conditions would fly:
* User-overloaded operators would evaluate in the same order as the
operators they are based on, i.e. operands are evaluated as they appear
and associate as the operators (left-to-right except for the few
right-to-left ones).
* An expression involving user-overloaded operators can be rewritten as
an expression (not a series of statements) using the base methods.
2. The spirit of operator overloading should be agnostic to the name of
the operator being overloaded, modulo something like interface names or
the arity of the operator.
Why?
A proposal I saw on the possibility of "contracts" (or static
implementation of interfaces) gave me an idea to work around the
LHS-issue with a bit more workaround:
public interface Addable<Left, Right, Value> {
Value add(Left left, Right right);
}
public class Matrix<T extends ...> implements
static Addable<Matrix<T>, Matrix<T>, Matrix<T>>,
static Multipliable<T, Matrix<T>, Matrix<T>> {
static Matrix<T> multiply(T scalar, Matrix<T> matrix) {
Matrix<T> result = new Matrix<T>(matrix);
for (T[] row : result.rows) {
for (int i = 0; i < row.length; i++) {
row = T * row;
}
}
}
}
with suitable `? super' and `? extends' thrown in the type definitions.
Writing generics libraries is still a pain, though.
Thus the compiler could then translate the expression |scalar * matrix|
to |multiply(scalar, matrix)|...
Implementation via interfaces opens up wide possibilities that could not
be offered by other proposals for operator overloading. Indeed, it is
probably safe to say that these interfaces alone--along with
retrofitting the appropriate primitive wrappers, BigInteger, and
BigDecimal--would be powerful enough, even if operator overloading
didn't follow.
One step at a time, I'd say. Pin down the implementation of regular
operator overloading before trying to extend it.
Hmm...
public interface CumulativeAddable<Param, Return> extends
Addable<Param, Param, Return> {
public Return add(Param... params);
}
But it can also add any String to an Object and get a String. Unfortunately.
Joshua said:Harold said:Joshua said:Harold Yarmouth wrote:
Joshua Cranmer wrote:
((array[i++] << 8) & 0xff) | (array[i++] & 0xff)
That is side effects.
That is bit-twiddling, not matrix multiplication.
It is very much the same vein.
Hardly.
Boolean or is
any operation in computer science is not commutative.
Note, for example, that making a Square class extend
a Rectangle (since a Square is-a Rectangle) does not
actually work since it would fail to match the
Rectangle's contract.
Jerry said:Somehow, I doubt Harry was proposing that the translation be naïve.
As I understood the proposal, it would have to break encapsulation to
do so, and the semantics of well-behaved code wouldn't be dependent on
the exact order of evaluation, although the performance might be.
Poorly-behaved code would behave in a manner that would require
language-lawyering, just like it already does with multiple "i++" in
one line of code. An example I think Harry'd mentioned explicitly.
Worrying about how the presentation might degrade at 3x3 is like
worrying about how you'll get to work the next day if your car goes
over that cliff at 40mph, when you happen to be in that car.
I don't see why the second one is necessary.
I thought this was now about implementing these interfaces and some
compiler tweaks, then adding operator overloading later as a layer on
top?
Harry?
Erk. I think I prefer Accumulator.
As I understood Harry's latest proposal, this would basically be
StringBuilder, not String.
Eh, then the third type parameter's not needed. Or the first isn't.
It'd just be Accumulator<Object,String>, left hand argument is what
you can add, right hand argument is the type of the running sum and of
the result. Addable<Object,String> on String, also, since it can be
added to any Object to get a String.
Eh. You also need a way to get the "zero" for the accumulation.
Addable needs a getIdentity() method, and ugly-enough this needs to be
non-static for an interface to specify it. For strings it would return
"", for numbers zero.
Then again, this could be generalized further. Accumulation of
products, with identity 1; of logical-ors, with identity false; of
logical-ands, with identity true; and so forth. Maybe some notion of
generalized commutative, associative operations? Mathematicians call
that an abelian group. We'd need something less exotic and easier to
type. And yes, we'd need to be able to implement the same interface
with multiple sets of generic parameters in a single class. That would
need reified generics, since otherwise method foo taking an
Addable<Foo,Bar> that's also an Addable<Baz,Quux> and doing its add
won't know whether to call Bar add(foo) or Quux add(bar) at runtime
due to erasure.
Arne said:It was you that started in the quoted material.
Sure you did.
Joshua said that you should stop posting because you are
off-topic, you agreed with "yeah" but still continued
to post.
Arne said:Do you need help
Mike said:"Ad hominem"? What language is that?
Arne said:The language Harold does not like - wait - hmm ...
Want to reply to this thread or ask your own question?
You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.