Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> But it's not a hint to the compiler. It's stating a fact to the compiler. It'll stop compilation.

So, if I type out that something's a Banana, and the compiler stops and tells me it's actually an Apple, why did I need to type anything?

> Did the other languages (C++, C#, Java) get it wrong?

I can only speak for Java, but here goes. Here's something that compiles without warning and crashes at runtime:

  Fruit[] basket = new Apple[] { new Apple(), new Apple() };
  basket[0] = new Apple();
  basket[1] = new Banana();  // Crash here
You and I know Dung doesn't belong in a basket, but Java sure doesn't. It will not warn about me comparing Fruit to Dung, nor is there a way to ask the compiler to warn me that I forgot to handle Banana:

  void handleFruit(Fruit fruit) {
    if (fruit instanceof Apple) {
        System.out.println("Apple");
    } else if (fruit instanceof Dung) {
        System.out.println("Dung");
    }
  }
Here's another one:

  void foo() {
    Fruit[] basket = new Apple[] { new Apple(), new Apple() };
    handleFruit(basket[0]);
    handleFruit(new Apple();
  }

  void handleFruit(Fruit fruit) {
    System.out.println("Do I get called?";
  }

  void handleFruit(Apple apple) {
    System.out.println("Or do I?";
  }
In the first code sample we established that the basket could only contain Apples, but now when you handle something from the basket, it's apparently any Fruit. And when you handleFruit an Apple, there's no warning that the compiler is making a choice between the two acceptable handleFruit functions.

Anyway, just like me, this Bucket<Dung> is full of shit. Time to dump it all out. I could put it in the compost, or in the veggie garden. Anywhere that contains Dung. Likewise, the Fruit could go in a Bowl, or a Cupboard.

Here's a first pass at it:

  interface Transfer<F, T> {
    void dump(F from, T to);
  }

  class FertiliseGarden implements Transfer<Bucket, Garden> {
    public void dump(Bucket from, Garden to) {
    }
  }

  class PutAwayFruit implements Transfer<Basket, Cupboard> {
    public void dump(Basket from, Cupboard to) {
    }
  }
It compiles, but it's missing the only safety check I really cared about - the contents must match (even if the containers vary!) Let's introduce another type variable X to assert this:

  interface Transfer<F, T, X> {
    void dump(F<X> from, T<X> to);
  }
Now it asserts what I want it to assert, but it doesn't compile.

I can't call how Java handles the above stuff as 'wrong', since that's stating it too objectively. I can only say I disagree with the above design decisions (if they were deliberate) or I find fault with them (if they just turned out that way).



Yes that Java example is bad and terrible. I'm honestly amazed you can do Fruit[] basket = new Apple[]. That's terrible.

You can't do that in C++. You can slice objects but you'll get a warning in any good compiler.

I would like to know the type of the object I am working with else it'd be "auto everything" in C++ and it makes the code unreadable.

That's basically what I am finding objectionable about PHP because you've got types added as return types from functions, and also types for parameters and you can enable strict checks for the types but none of it makes any sense when you can just get an array of unknown/any type.

It's like a C++ vector of void pointers that you can cast to whatever you'd like it to be and that's really bad. It's also not very maintainable, particularly in large codebases.

It's a strange oversight in PHP given the type "safety" enforced elsewhere. I suspect they just aren't doing it because so much code would break.

I would like to see this typed array introduced so you can look at horrible codebases like the Magento example (there's loads of it) and see at a glance what you're dealing within instead of "an array of unknown type".

I will use your FertiliseGarden function shortly, thanks.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: