7.0 wishlist?

A

Andreas Leitgeb

Joshua Cranmer said:
Andreas said:
Joshua Cranmer said:
Note, for example, that making a Square class extend a Rectangle
[...] would fail to match the Rectangle's contract.
what type of rectangle-related contract do you have in mind?
I hope it is not something like "width!=height must be allowed"
[example snipped, as it boiled down to exactly my prognose]

Whether Square breaks Rectangle's contracts of course depends on the
contracts put up by Rectangle. If it contains goofy contracts then,
indeed, Square may not match those.
The idea that changing the height does not change the width is what is
violated.
And that is, what I consider an #1 example of a goofy contract.

PS: but then again, the Square could override setWidth and setHeight
to throw a certain exception and instead offer a setSize...
The Rectangle class would have to "allow" the throwing of exceptions
in its contract for that.
 
A

Andreas Leitgeb

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.

You can of course say whatever you feel like saying, unless
you were communicatively challenged, which you don't appear
to be (based on an abstract meaning of "say").

Now, having dealt with the "I think I can say"-part, let's
see the rest: "that arrays are passed by value."
This looks like you consider the array to *be* whatever the
array typed variable holds (i.e. the reference to some object),
which indeed is copied by value.
Identifying references with objects is not a good idea, IMHO.
 
J

Joshua Cranmer

Andreas said:
And that is, what I consider an #1 example of a goofy contract.

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 while Square would break that
contract. That the height may be able to affect the width is non-intuitive.

The point still remains, though, that structures from mathematics are
not directly transferable to code.
 
B

blmblm

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

(e-mail address removed) schreef:
Mike Schilling wrote:
[snip]

NO FEEDBACK LOOPS!

Does anybody understand this?

I can't say I do entirely, but I'm all too familiar with this
bit of boilerplate as used by the person who posts using the
e-mail address (e-mail address removed) and several other gmail addresses,
and since it appears he's not going to explain (unless I missed
that post), I'll try:

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.

My two cents' worth.

[ snip ]
 
B

blmblm

If I say "the one true editor" you'll have a 50% chance of guessing right.

:) :)

But maybe it's not a good idea to mention in this group either of
what I figure are your two possibilities, right? as those who were
following this newsgroup a year or so ago may recall ....
 
A

Andreas Leitgeb

Joshua Cranmer said:
Well, first off, the entire example is contrived.
That point taken.
But in any case, most people would agree, on only seeing the Rectangle
class, that assertContract should always succeed

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.
The point still remains, though, that structures from mathematics are
not directly transferable to code.

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, too, not withstanding the
goofiness of actually writing such unreadable code that would
exhibit such side effects for the operands.
 
M

Mike Schilling

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.

Plus the fact that it is always a bad idea to derive one concrete
class from another. A more sensible hierarchy would derive both
Square and Rectangle from an abstract class that defines only methods
appropriate to both.
 
R

RedGrittyBrick

Andreas said:
here neither the 0+,o+,O+ nor -> digraphs are
assigned the same way as they seem to be on your machine.

My original text got a little truncated along the way, the full sentence
was "my favourite text editor lets me define digraphs so that, for
example, I can type ⊕ by typing Ctrl+K 0+"

In other words I had to first issue the command
:digraph 0+ 2295

If Roedy's idea became obligatory (or commonplace) I'd add that to the
configuration/startup file.

The extra digraphs (pa, -> and so on) get loaded when you set the
encoding to utf-8, they don't appear if the current encoding is latin1.
:set encoding=utf-8
:digraphs
 
H

hzergel901

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.

A somewhat distorted or simplified explanation, to be sure.

Essentially, it's this: When things get personal, two things occur --
one, the discussion is no longer legitimately within the newsgroup
charter, and it's really not proper then for anyone to reply except in
their own defense if maligned; two, the "discussion" has generally
turned into an argument, and usually this has divided up into several
separate arguments that are essentially just two people arguing.

Therefore, a) if A insults B and B rebuts A's insult, possibly also
counter-insulting A, B has a valid reason (self-defense) for breaking
the newsgroup charter and making what is surely an off-topic post and
probably against the nominal rules in other ways as well. Much as if A
rushed B with a knife, B might be justified in using lethal force to
stop A, even though B killing A would normally violate rules of
conduct.

However, some third party C has no such justification for butting in
and making an off-topic, or especially an inflammatory, remark. So if
C replies to B (other than to defend A; defense of another is also a
justification) or if C replies to A's reply to B, C has no excuse for
his or her behavior.

In actual practise, the cases that arise tend to be that C replies to
B to second B's insult on A (i.e. ganging up on A, generally without
any direct and immediately-recent provocation of C by A) or C replies
to A to attack A and interfere with A's self-defense (which is again C
jumping in to gang up on A).

This is clearly illegitimate.

As for "feedback loop", the effects of C's actions are that the
arguments in which A is embroiled begin to multiply. Consider if A and
B are arguing with each other, A and C are arguing with each other,
and B and C are arguing with each other, separately. As a rule, each
day or week or however-long A will find some posts by B and C that
require a response, B will find some posts by A and C that do, and C
some by B and A. They will each post similar numbers of posts. The
total number of posts each interval will tend to stay about the same,
or gradually decrease as the arguments are resolved one by one, or end
in draws one by one, or whatever.

This is good, if the ideal is for acrimony, flamewars, and suchlike to
die down rather than persist, and for off-topic discussions to peter
out rather than grow to dominate the traffic in a newsgroup, as I
think reasonable people will concede.

When C starts butting into what has become a personal argument between
A and B, you get A posts a post, B posts a reply, and C butts in; A
now has to defend from both B and C, and makes two posts; if B replied
to A's reply to B and C to A's reply to C we wouldn't have much of a
problem but suppose C again butts in and replies to A's new reply to
B, so now A has two replies by C and one by B to deal with, and A now
makes three posts; B replies to A's reply to B and C replies to
everything by A, attacking A, and A now makes four posts; A's
workload, as well as C's, and the newsgroup's flaming/off-topic
traffic, are now growing rather than shrinking. Linearly, mind you.

It gets worse if more than one person starts butting in when not
themselves threatened. Suppose both B and C tend to attack everything
that A writes to either of them, whether or not what A said impacts
the other. Now A makes one post, gets two attack replies. A makes two
rebuttals, gets four attack replies. A makes four rebuttals, gets
eight attack replies ... clearly now the growth is exponential. A, B,
*and* C have exponentially growing workloads, and the newsgroup has
exponentially growing undesirable traffic. This is the worst-case
scenario, quickly drowning the newsgroup with what is, to other
participants, basically spam, and quickly growing to consume
inordinate amounts of time from A, B, *and* C. All of whom probably
really have better things to do with their time.

That is why it is best if nobody butts into the middle of other people
disputing or arguing about an off-topic thing. It makes things worse.
It fans the flames. It spams the newsgroup.

Think of the exponentially-growing off-topic traffic as a feedback
squeal, caused because of C's butting-in that acts as an amplifier. C
causes feedback between C and the dispute between A and B that
generates a rapidly worsening shriek of unwanted noise.

Hence, "no feedback loops".

I admit to an ulterior motive: my own workload is expanded by such
feedback loops. But I avoid butting in in the manner described and
urge others to do likewise for the sake of everyone's time and for the
sake of the newsgroup's SNR.

My earlier suggestion of a way to de-escalate this in such a way that
nobody "loses" relative to anyone else was, sadly, completely ignored
-- it didn't even draw any flames! -- but I reiterate the suggestion
that a staged de-escalation will ultimately benefit everyone involved
in this mess, compared to the alternative.

Especially, though, two things should be done:
a) My opponents should desist from feedback loop buttings-in;
b) They should likewise desist from dishonorable tactics such
as various forms of computer hacking, denial-of-service
attacks, and intentional misquotations -- such tactics
actually are self-defeating anyway, since anyone caught
using them is unmasked as a charlatan, a fraud, and a sore
loser besides; and
c) They should desist from attempting to reignite old flame-
wars gratuitously and randomly, and, especially, from
dragging random people in and flaming them too. A quick
google of this group shows many people I've previously
locked horns with engaged in multiple flamewars with
multiple apparently-innocent victims, most of whom they
have accused wrongly of being me (not that being me is
actually a crime, other than in their view). This is
especially bad -- it harms innocent people, brings cljp
into disrepute (by making newbies afraid to speak up,
lest they get jumped on and dragged into some stupid
two-year-old feud that needn't involve them), and has
the same pernicious effects as feedback loops, growing
and multiplying the amount of flame-traffic and OT
traffic by inoculating various threads with irrelevant
flamage that had formerly lacked it.

Flamage here is like Dutch elm disease in a tree farm. Deliberately
spreading the disease to formerly-uninfected trees is vandalism. All
those who keep attacking random people out of a paranoid belief that
they're me are therefore vandalizing cljp. If they truly value cljp,
they should desist from such behavior. Those that do not, I shall call
out as enemies of cljp, persons who place their private vendettas and
personal axes to grind above the well-being of the community and the
newsgroup, and who view themselves as above the law, beyond
netiquette, and accountable to no-one.

But they are not accountable to no-one; they are accountable to the
community, if the community sends a clear message that their wish is
for cljp to be a place for the civil discussion of Java programming
and not really comp.flame in disguise, dominated by personal and
acrimonious debates that have little or nothing to do with Java.

And to reiterate, for those that have forgotten or that simply do not
know: bugs in Google Groups intended to limit the rate at which
spammers can generate postings via automated script have the
unfortunate side effect of forcing users that participate heavily,
posting more than about 14 news posts a day, to get multiple Google
Groups accounts, and I am basically stuck using Google Groups. I have
not posted here using any other news server, or using any other than
@gmail.com emails. I have not impersonated anyone else and I have made
no intentional effort to disguise my identity. Generally, I'm
instantly recognizable from my "none of the nasty things that you have
said or implied about me are at all true" line. There is no attempt at
deception or disguise. The side effect of being harder to killfile is
unfortunate and unintended, but not apparently avoidable given the
other constraints present (such as those imposed by the sheer volume
of incorrect crap being written about me and posted publicly, which
cannot of course be allowed to go uncorrected). However, stuck with
Google Groups as I am, I have an even harder time killfiling anyone
else. :)

Oh, and since people simply will not quit promulgating incorrect
guesses about my real name, and then compounding the error by mis-
attributing their guesses to multiple *other* people in turn: my
actual name is Jerry Gerrone.

Silly-sounding, yes, I know. That and my valuing my privacy and
physical safety from potential stalkers made me reluctant to disclose
it, especially in a not-entirely-friendly environment. However, it is
now clear that maintaining my anonymity will simply end up costing the
poor, much-maligned Paul, bringing on him whatever ills I manage to
dodge by remaining anonymous. Whatever his past sins (and for all I
know he could be the Antichrist himself), and regardless of his
apparently deceased status (based on a quick google), he has no
causative role in this dispute and it would therefore be
irresponsible, negligent, and just plain evil of me to essentially end
up using him as a human shield. If someone is going to be attacked
because of things that I have done, whether those things deserve such
responses or not, let that someone be me and not some uninvolved third
party. I choose not to be complicit in causing such collateral damage,
even though it may cost me.

I wonder if a single one of my opponents is man enough to seek de-
escalation, seek to avoid collateral damage to third parties and to
cljp, and seek as amicable as possible a resolution to all this as I
am.

We will soon find out who else is such a man, and who is just out to
"win" at any cost, unwilling to accept a loss or even a draw,
determined to go down swinging and the hell with the consequences.
 
H

hzergel901

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.
 
T

The ScuzzBuster

[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?

He was, and he is correct to do so. He isn't Twisted. I am.

The "H." in that post up there is Hendrik's sign-off, not a reference
to Harold; that post of Hendrik's was attacking me, not Harold.

Here's a link to the original post by Hendrik, which clearly has
nothing to do with Harold:

http://groups.google.com/group/comp.lang.java.programmer/msg/8ba0b0d0402524b4

Mike, at least do your homework before mouthing off at me, Harold,
both of us, or anyone else!
 
J

Joshua Cranmer

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).

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.
* 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++".

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.
(The above assumes correct code).

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."
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.

The JLS could say whatever it wants, since it is the specification. In
reality it's bounded by common sense. The changes have to be approved by
a group of people; 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.
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 *).

For the sake of simplicity, I think we can agree on the following:
1. Some user-defined overloaded operators may be noncommutative.
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. So if we assume that one binary operator
could be noncommutative, we should assume that all binary operators
could be noncommutative, even if it would be bad practice to do so.
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.

My preferred method for overloading would involve interfaces like that:

public interface Addable<T, R> {
R add(T);
}
// etc.

public class Matrix<T extends Number> implements
Addable<Matrix<T>, Matrix<T>>,
Multipliable<Matrix<T>, Matrix<T>>,
Multipliable<Vector<T>, Vector<T>>, // NOT java.util.Vector
Multipliable<T, Matrix<T>> {
}

Actually, probably even better is this:
public class Matrix<T extends
Addable<? super T, ? extends T> &
Multipliable<? super T, ? extends T>>
implements // etc.

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)| and then select the correct method to call
for multiply based on normal method resolution rules. The only catch
(which my example shows) is that the correct way to write the libraries
is still difficult.

Well, there's also the fact that it depends on not one but two proposals
before it.
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.

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.
> 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.

One step at a time, I'd say. Pin down the implementation of regular
operator overloading before trying to extend it.
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.

Hmm...

public interface CumulativeAddable<Param, Return> extends
Addable<Param, Param, Return> {
public Return add(Param... params);
}

Sometimes I wish there were a way to say in an interface that "this
method is actually equivalent to this one."
> 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.

But it can also add any String to an Object and get a String. Unfortunately.
 
J

Jerry Gerrone

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.

Somehow, I doubt Harry was proposing that the translation be naïve. :)
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.

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.
While users ideally need only deal with correct code, the specification
must deal with any valid code.

I'm sure it would.
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."

A browser might as well give up on that and assume some sort of
minimum that's a darn sight bigger than 3x3; no matter what it does,
the results will be unusable below some threshold resolution, so it
might as well be designed to give the best possible results above that
threshold regardless of the effects doing so has below that threshold.

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 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.

I don't see why the second one is necessary. The first one is strongly
desirable, but for the case of OlderClass op NewerClass with
NewerClass defining op it will generally be necessary to give up the
second one to get the first.
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)|...


Seems pointless to introduce a whole new kind of "interface" for this
purpose. In that case, you might as well just allow static methods
Foo.operator+ (or whatever, I used the C++-like name) and operator
overloading enabled using import static.
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.

They would also make operator overloading that much "closer", in some
sense, such that it'd have a decent shot at getting in in the *next*
Java version after the one that added Harry's proposed interfaces.
One step at a time, I'd say. Pin down the implementation of regular
operator overloading before trying to extend it.

I thought this was now about implementing these interfaces and some
compiler tweaks, then adding operator overloading later as a layer on
top?

Harry?
Hmm...

public interface CumulativeAddable<Param, Return> extends
     Addable<Param, Param, Return> {
   public Return add(Param... params);

}

Erk. I think I prefer Accumulator.
But it can also add any String to an Object and get a String. Unfortunately.

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.
 
H

Harold Yarmouth

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

bit-twiddling, which is not at issue here.
any operation in computer science is not commutative.

Nonsense. Some aren't, some are, like elsewhere.
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.

How so? I don't see this causing a problem, at least for immutable
Squares and Rectangles.
 
H

Harold Yarmouth

Jerry said:
Somehow, I doubt Harry was proposing that the translation be naïve. :)

It's Harold. Only my wife calls me Harry.
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.

I had. And see above.
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.

Cute. And true.
I don't see why the second one is necessary.

Nor do I. Indeed, if Java had thus far lacked the trinary operator ?:,
and someone was proposing to add it, Joshua's second criterion would
torpedo it, since the equivalent pre-trinary code is if (foo) tempVar =
bar; else tempVar = baz.
I thought this was now about implementing these interfaces and some
compiler tweaks, then adding operator overloading later as a layer on
top?

Harry?

Yeah, I thought so too.

And see above.
Erk. I think I prefer Accumulator.

Yeah, me too.
As I understood Harry's latest proposal, this would basically be
StringBuilder, not String.

Yes. (And see above.)
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.

I think you have a point here.
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.

Sounds difficult.
 
H

Harold Yarmouth

Arne said:
It was you that started in the quoted material.

No. The first insultage came from somebody other than me.
Sure you did.

No, you did.
Joshua said that you should stop posting because you are
off-topic, you agreed with "yeah" but still continued
to post.

Because he did. And you did.

I'll stop when you stop.
 
H

Harold Yarmouth

Mike said:
"Ad hominem"? What language is that?

Same as "et cetera". I claimed not to know the language; I didn't claim
not to know the odd random loan-word from it.
 
H

Harold Yarmouth

Arne said:
The language Harold does not like - wait - hmm ...

I never said I didn't like it. I said I didn't know it. And I never said
I didn't know the odd loan-word that came from it, either.
 

Ask a Question

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.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,161
Latest member
GertrudeMa
Top