From: Tomas Mikula on
On Mon, 19 Oct 2009 17:23:33 -0700, Marcin Rzeźnicki wrote:

> On 20 Paź, 01:45, Tomas Mikula <tomas.mik...(a)gmail.com> wrote:
>> On Tue, 20 Oct 2009 00:05:41 +0100, Tom Anderson wrote:
>
>
>> > What are you planning to do with this zero if you don't have any
>> > Vector instances? I don't really buy your scenario.
>>
>> Consider you want to implement a method that takes a collection of
>> vectors and returns their sum. Simple, eh? If I can call static methods
>> on type parameters, it will look like this:
>>
>> public V sum(Collection<V> coll){
>>     V s = V.zero();
>>     for(V v: coll)
>>         s = s.add(v);
>>     return s;
>>
>> }
>>
>> However, we cannot call V.zero(). What will you return if coll is an
>> empty collection?
>
> But what is so wrong with passing neutral element to the method and
> implement it like foldl? For me it is quite natural

Isn't so bad, but not quite natural for me (ok, this is subjective). I
want a method that takes a collection and returns its sum. Instead, I
will have a method that takes a collection and an element and returns
that element plus the sum of the collection. If I was reading this code
after someone else, I would wonder why they have written it like this,
because I would not see the problem at the first sight.

What if the method that calls sum() doesn't have an instance at hand
either? Then I have to propagate this instance-passing up the call
hierarchy.
From: Tomas Mikula on
On Mon, 19 Oct 2009 16:22:56 -0700, Daniel Pitts wrote:

> Tomas Mikula wrote:
>> On Sun, 18 Oct 2009 19:19:55 -0700, Peter Duniho wrote:
>>
>>> Tomas Mikula wrote:
>>>> I have searched this group for "abstract static methods" and found a
>>>> couple of threads, but I think none of them was discussing the kind
>>>> of semantics I am going to describe. As you might have guessed, I
>>>> believe it would be useful :). [...]
>>> You aren't the first. However, in C++, C#, Java, and languages like
>>> them, you simply are never going to have methods that are both virtual
>>> and static. And since abstract implies virtual, that rules out
>>> abstract static methods too.
>>
>> I'm not talking about virtual static methods. In this case, abstract
>> would not imply virtual. My second use case could most probably be
>> accomplished in C++ by Concepts (though Concepts didn't make it to C+
>> +0x). In fact, it is achievable with current C++ templates, only
>> without compile time checking --- it is possible to call
>> T::staticMethod() where T is a template parameter.
> C++ Template programming provides compile-time polymorphism. In Java,
> you don't have Templates, so there is no similar approach.
>
> If you think you need a "static" method to be overidden, then you really
> need to have a non-static method, on a polymorphic object.

I rather think that sometimes I need to enforce that the static method
_will_ be overridden in every subclass. Non-static methods do not enforce
overriding, because they inherit the implementation from superclass. Note
that I don't want that the following example outputs "B", as was proposed
in some other discussions about abstract static methods.

class A {
static void f(){ System.out.println("A"); }
}

class B extends A {
static void f(){ System.out.println("B"); }
}

A a = new B();
a.f();
From: Marcin Rzeźnicki on
On 20 Paź, 02:50, Tomas Mikula <tomas.mik...(a)gmail.com> wrote:
> On Mon, 19 Oct 2009 16:06:27 -0700, Marcin Rzeźnicki wrote:
>
> > But I am free to pass an instance of any conforming type.
>
> I don't think so. At least not without the compiler warning about
> unchecked casting. If you have
> Vector2D v;
> you can only pass Vector2D instances to v.add(...). If you have
> V v;
> where V is actually Vector2D, you can only pass V instances to
> v.add(...). But V is actually Vector2D, so it is OK.
>
>

OK, let's discuss this below when we are talking about reification

>
> > Except that super calls are dispatched by VM with no help needed from a
> > programmer.
>
> The thing is that prohibiting inheritance is a feature here, not a
> drawback. This is because inherited behavior is most likely to be wrong.
> (as with Vector.zero() or Serializable.readObject() (if readObject was a
> static method returning the read object)). If this is not the case, then
> it would probably not be the best choice to use this feature.
>
>

But still we have to dispatch correctly, that's the biggest problem in
my eyes with this feature ,regardless of whether we restrict
inheritance or not.

>
> > Right, but the difference is that super calls are not subject to 'human'
> > errors (what happens if inheritance chain has been updated? you have to
> > manually review all subclasses and repair static calls)
>
> This is not a new problem. You have the same problem with current static
> methods, if you call a static method of a superclass. It might be useful
> to have some static analog of the 'super.instanceMethod()' construct,
> regardless of my proposal.
>
>

OK, agreed (but somehow I don't feel it still, only I do not have
counter arguments :-) )

>
> > Still, you have to redefine static method so that it is _usable_ for
> > every type, but _used_ only when exact type is of special interest which
> > encourages too strict typing.
>
> Again not sure what exactly you meant. In the example of AudioVideoCodec
> I provided, the isReadable() method was only required to work with
> AudioFiles.
>

Right, but is there a way to know it at runtime? Method takes
Stream<File> parameter and a file and wants to check whether isReadable
(file) holds. I wonder, maybe it is all about how to dispatch.

> > Ok, probably now I understand fully your
> > concept. I'd uphold my opinion that this is not so good. Here is a quick
> > rundown why I think so: 1. Problem it solves can be solved in other
> > ways, without any need for special syntax/semantics/language or VM
> > changes (like Vector)
>
> Each problem can be solved in other ways. You could argue that we don't
> need generics, because every problem can be solved without them. The
> question is how concise and readable the solution is. Unnatural hacks are
> IMO very bad for code readability.
>

As with the sum example, I do not feel it is unnatural. But that is
obviously matter of taste.

> > 2. It is not clear how it would/should behave even
> > for problems it is supposed to solve
> > (code: public <T extends Foo> void doSth(T t) { T.staticFromFoo(); }
> > public class Bar extends Foo { public static void staticFromFoo()
> > {...};}
> > what should it bind to? If Foo, what if it is passed a Bar instance in
> > runtime?)
>
> It should bind to whatever type T represents. That is why reified
> generics are necessary. The bytecode of doSth() would contain the
> information that the staticFromFoo() method of T is called, where T will
> be specified at runtime (though I suspect that this could be optimized at
> link-time).
>

You need more than reification. As far as we are concerned about
bytecode, there is currently no way to express what you said. Probably
you need modified version of invokestatic which takes class as an
operand (currently it is constant from CP)

> > 3. It encourages bad code smell, that is: coding with the most specific
> > type instead of coding with interfaces
>
> How? Did we have an example of this? If yes, I probably missed it.
>

Well, I can tell you when you answer my question about how
AudioVideoStream statics can be used (or called by some dispatch
mechanism) in context where more generic Stream is used.

> > 4. It solves relatively infrequent problems
>
> The problem with serialization frameworks is infrequent. I suspect that
> the other problem with generics may be quite frequent.
>

But solvable, it is just matter of how unnatural we think it is.

> > 5. It is error prone - developers will have to study
> > all subclasses to spot what should be changed after any superclass has
> > changed
>
> I don't see any special relation of this problem to the proposed feature.
> It is always bad if you depend on the implementation of the superclass
> rather than on the interface only. This feature does not encourage you in
> any way to depend on the superclass. If you are referring to the problem
> of calling superclass methods on superclass's class literal
> (MySuperClass.staticMethod()), I already argued that this is not a new
> problem.
>

Yes, that's what I was referring to. So we can skip this point.

> > 6. It makes developers implement this static heritage over and
> > over, even when it is not needed
>
> It is designed for cases when it _is_ needed. I admit that someone could
> be tempted to use it inappropriately. But almost anything can be misused.

Right, ok, agreed.
So, everything boils down to dispatching, right? Do you have any
ideas?
What do you think about interface methods in .NET?
From: Tomas Mikula on
>> > Still, you have to redefine static method so that it is _usable_ for
>> > every type, but _used_ only when exact type is of special interest
>> > which encourages too strict typing.
>>
>> Again not sure what exactly you meant. In the example of
>> AudioVideoCodec I provided, the isReadable() method was only required
>> to work with AudioFiles.
>>
>>
> Right, but is there a way to know it at runtime?

I think there isn't. But it is not a problem if you don't pass a raw
type. If you pass a raw type, you get a compiler warning and probably get
a ClassCastException(?) at runtime.

> Method takes
> Stream<File> parameter and a file and wants to check whether isReadable
> (file) holds. I wonder, maybe it is all about how to dispatch.

If a method takes Stream<File>, then it will not accept
Stream<AudioFile>. Stream<AudioFile> is not a subclass of Stream<File>.
If it took Stream<? extends File>, then it would accept Stream<AudioFile>
s. But then the compiler won't allow you to call s.isReadable(f) in this
method (whatever type f has; provided that isReadable is declared to work
on the type parameter F). We can only pass a File to AudioFile.isReadable
() if isReadable was declared to accept File (no generics involved). Then
the implementation would have to check that the file is actually an
AudioFile. But we are already far away from the concept of abstract
static methods.

>> > Ok, probably now I understand fully your concept. I'd uphold my
>> > opinion that this is not so good. Here is a quick rundown why I think
>> > so: 1. Problem it solves can be solved in other ways, without any
>> > need for special syntax/semantics/language or VM changes (like
>> > Vector)
>>
>> Each problem can be solved in other ways. You could argue that we don't
>> need generics, because every problem can be solved without them. The
>> question is how concise and readable the solution is. Unnatural hacks
>> are IMO very bad for code readability.
>>
>>
> As with the sum example, I do not feel it is unnatural. But that is
> obviously matter of taste.

If I find a bigger example where it won't be just the matter of taste, I
will post it here.

>
>> > 2. It is not clear how it would/should behave even for problems it is
>> > supposed to solve
>> > (code: public <T extends Foo> void doSth(T t) { T.staticFromFoo(); }
>> > public class Bar extends Foo { public static void staticFromFoo()
>> > {...};}
>> > what should it bind to? If Foo, what if it is passed a Bar instance
>> > in runtime?)
>>
>> It should bind to whatever type T represents. That is why reified
>> generics are necessary. The bytecode of doSth() would contain the
>> information that the staticFromFoo() method of T is called, where T
>> will be specified at runtime (though I suspect that this could be
>> optimized at link-time).
>>
>>
> You need more than reification. As far as we are concerned about
> bytecode, there is currently no way to express what you said.

I know nothing about bytecode. I just supposed that when there are
reified generics, there will be enough information to dispatch it
correctly.

> Probably
> you need modified version of invokestatic which takes class as an
> operand (currently it is constant from CP)

Yes. And I suspected that if the generic class is used with just a few
different parameters at runtime, one specialized copy of the generic
class, in which static methods would be invoked as usual, could be made
for each type parameter. A similar process is called template
instantiation in C++, but it is done as code generation at compile time.

>> > 3. It encourages bad code smell, that is: coding with the most
>> > specific type instead of coding with interfaces
>>
>> How? Did we have an example of this? If yes, I probably missed it.
>>
>>
> Well, I can tell you when you answer my question about how
> AudioVideoStream statics can be used (or called by some dispatch
> mechanism) in context where more generic Stream is used.
>
>> > 4. It solves relatively infrequent problems
>>
>> The problem with serialization frameworks is infrequent. I suspect that
>> the other problem with generics may be quite frequent.
>>
>>
> But solvable, it is just matter of how unnatural we think it is.

Yes. I will have to come up with a more elaborate example :)

>
>> > 5. It is error prone - developers will have to study all subclasses
>> > to spot what should be changed after any superclass has changed
>>
>> I don't see any special relation of this problem to the proposed
>> feature. It is always bad if you depend on the implementation of the
>> superclass rather than on the interface only. This feature does not
>> encourage you in any way to depend on the superclass. If you are
>> referring to the problem of calling superclass methods on superclass's
>> class literal (MySuperClass.staticMethod()), I already argued that this
>> is not a new problem.
>>
>>
> Yes, that's what I was referring to. So we can skip this point.
>
>> > 6. It makes developers implement this static heritage over and over,
>> > even when it is not needed
>>
>> It is designed for cases when it _is_ needed. I admit that someone
>> could be tempted to use it inappropriately. But almost anything can be
>> misused.
>
> Right, ok, agreed.
> So, everything boils down to dispatching, right? Do you have any ideas?
> What do you think about interface methods in .NET?

I haven't done any coding in .NET, so I can't tell :(
From: Andreas Leitgeb on
Eric Sosman <Eric.Sosman(a)sun.com> wrote:
>> On second thought: If the Entertainers were designed to be dynamically
>> loaded by name, then Comedians just wouldn't have any chance of a individual
>> default joke.
> I'm not sure why the second sentence follows from the first

The Framework designed for dynamically engaging Entertainers just hasn't
the slightest idea, that some of the Entertainers require special cons-
tructors, and even if it enumerated the constructors, it wouldn't have
any idea what a Joke is in the first place.

> And if you know enough to be able to supply a Joke to a post-construction
> setter, why couldn't you just as well hand it to a Constructor's
> newInstance() method?

The post-construction setter (or rather the property being set) has a name,
for which a Joke(actually String) can be configured in some engaging contract
(xml). Otoh., the arguments to a constructor are nameless in bytecode.