Re: stuck on "Incorrect type in assignment" error
Daniel Bonniot <[email protected]> Sun, 06 Mar 2005 23:18:55 +0100
| Newsgroups | gmane.comp.lang.nice.general |
|---|---|
| Message-ID | <[email protected]> |
Hi Steve,
> I'm trying to get a rather large Nice program written in a hurry,
How come ? ;-)
> and I keep hitting strange stumbling blocks. My approach so far
> has been to gnash my teeth, wail, pull my hair, and try dozens of
> different approaches until one gets past the compiler. But it's
> going too slowly, so I'm going to start posting my questions here,
> in the hopes that some Nice people will help.
Sure, it's a good idea.
> First question, then: why doesn't this code work --
>
> void main(String[] args) {
>
> let int w = 10;
> let int h = 5;
> let Integer[][] grid = new Integer[w][h];
>
> for (int j = 0; j < h; j++) {
> for (int i = 0; i < w; i++) {
> grid[i][j] = new Integer(i+j);
> }
> }
> }
>
> The compiler says:
>
> c:\nice\hello\main.nice: line 5, column 19:
> Incorrect type in assignment to grid
> Found : ?java.lang.Integer[][]
> Expected: java.lang.Integer[][]
> compilation failed with 1 error
The compiler detects that the array you created is filled with null. You need
to provide the values at the same time as the creation. Luckilly, this can be
done easily with the help of a library method (as a bonus, you don't even need
to write the loop!) :
let Integer[][] grid = new Integer[w][h].fill
((int i, int j) => new Integer(i+j));
Actually, this fill method is currently only provided in nice.lang for
single-dimension arrays. So here is the version for two dimensions. Just
include it somewhere in your program, until the next version of Nice which
will ship with it:
<T, U | U <: T> U[][] fill(T[][] array, (int,int)->U value)
{
for (int i = 0; i < array.length; i++)
for (int j = 0; j < array[i].length; j++)
array[i][j] = value(i,j);
return cast(array); // all values have been initialized, the cast is safe
}
(Quizz: is there a way to define this bi-dimensional fill by reusing the
mono-dimensional one?)
If you read attentively, you will see that 'cast' is a method that can be used
when you seem to get stuck with such type errors and you *know* there is no
problem. However, if you have the time, it's always better to stop and think
about what is happening and try to find a safe way to do what you want. Or
complain to the developers if you think the compiler should be smarter ;-)
When the only problem is null, you can use 'notNull(...)' instead, which is
"less unsafe" than cast.
> (Frankly, if Nice can't prevent run-time exceptions, then I don't believe it
> should make you work so hard to prevent null-pointer exceptions. It's
> really and truly not worth the hassle, as far as I can tell. The language has
> a lot to offer, and right now this little issue just gets in your way. Optional
> types should be, well... optional.)
Nice can't prevent _all_ run-time exceptions, but is it a reason not to try to
prevent any? In my experience, array bounds errors are very often an issue
that can be localized to a small portion of code. On the other hand, when
types do not specify if they contain null or not, whole APIs become
ill-specified, and the potential for errors diffuses to large portions of the
program. In practice, a big proportion of the failures I see on distributed
Java programs are NullPointerExceptions.
You're prefectly right that preventing those exceptions requires some work,
and I know it can be annoying. Nice is still being improved (at this very
moment, hey Artem! ;-) to make this process as little intrusive as possible by
making nullness analysis more precise. Providing this new version of the fill
method helps in you particular case.
By the way, why do you need to use type Integer[][] and not int[][] ?
> Incidentally, is it complaining because it thinks the grid reference
> could be null, or that one of its child elements could be null, or
> one of the child-child-elements?
Because the leaf elements could be null. The arrays are guaranteed to be
non-null since you provided the sizes for both dimensions.
> There are three different types
> here: the grid reference, its children, and their children. Which
> one is the question-mark referring to?
?Integer[][] is the same as (?Integer)[][]
Note that when you write types, you can use such parantheses to remove the
ambiguity.
> The User Manual could stand
> some expansion of the Arrays section, to include information about
> multi-dimensional arrays and arrays of non-primitive types.
Indeed. Does somebody has a bit of spare time to do it? Bryn? Arjan? Isaac?
(I'm in the middle of the visibility implementation, so I'd rather stay focused)
Cheers,
Daniel
PS: Steve, are you subscribed to the list?
-------------------------------------------------------
SF email is sponsored by - The IT Product Guide
Read honest & candid reviews on hundreds of IT Products from real users.
Discover which products truly live up to the hype. Start reading now.
http://ads.osdn.com/?ad_id=6595&alloc_id=14396&op=click