Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.java.programmer > #34745 > unrolled thread

Two surprises in for (:)

Started byMike Amling <mamling@chaff.us>
First post2016-07-01 12:55 -0500
Last post2016-07-01 15:08 -0700
Articles 3 — 3 participants

Back to article view | Back to comp.lang.java.programmer


Contents

  Two surprises in for (:) Mike Amling <mamling@chaff.us> - 2016-07-01 12:55 -0500
    Re: Two surprises in for (:) Eric Sosman <esosman@comcast-dot-net.invalid> - 2016-07-01 15:07 -0400
      Re: Two surprises in for (:) Daniel Pitts <usenet@coloraura.com> - 2016-07-01 15:08 -0700

#34745 — Two surprises in for (:)

FromMike Amling <mamling@chaff.us>
Date2016-07-01 12:55 -0500
SubjectTwo surprises in for (:)
Message-ID<nl6apt$gg5$1@dont-email.me>
I was surprised that the javac compiler accepted the following:

String[] foo={"a", "b"};
for (final String who : foo) {
}

because it seems strange to have a for loop's variable work when final. 
After all,

for (final int i=0; i<7; ++i) {
}

gets an error.

But for (final String who : foo) is more like an abbreviation of

for (final Iterator<String> iter=foo.iterator(); iter.hasNext(); ) {
   final String who=iter.next();
}

wherein it's not strange that who can be final.

My second surprise was that the compiler rejects

String[] foo={"a", "b"};
for (final Iterator<String> iter=foo.iterator(); iter.hasNext(); ) {
   final String who=iter.next();
}

apparently because arrays, unlike everything else accepted after the : 
in a for(:), do not actually implement the Iterable interface.

--Mike Amling
SSBzdXBwb3NlIGEgbG90IG9mIHlvdSBhcmUgbm90IHN1cnBpc2VkLg==

[toc] | [next] | [standalone]


#34746

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2016-07-01 15:07 -0400
Message-ID<nl6f14$ukj$1@dont-email.me>
In reply to#34745
On 7/1/2016 1:55 PM, Mike Amling wrote:
> I was surprised that the javac compiler accepted the following:
>
> String[] foo={"a", "b"};
> for (final String who : foo) {
> }
>
> because it seems strange to have a for loop's variable work when final.

     Well, the "for loop's variable" is not a particularly rigorous
description.  Examples:

	for (int i=0,j=10; i < j; ++i,--j) ...

	for (; !theList.isEmpty(); theList.remove(0)) ...

Neither of these has a unique obvious "loop variable."

> After all,
>
> for (final int i=0; i<7; ++i) {
> }
>
> gets an error.

     Yes, and I think that's unfortunate.  Sometimes I want to use
`i' in a lambda expression (or in a nested class), and I must write

	for (int i = 0; i < 7; ++i) {
	    final int iFinal = i;
	    // use iFinal in the lambda
	}

> But for (final String who : foo) is more like an abbreviation of
>
> for (final Iterator<String> iter=foo.iterator(); iter.hasNext(); ) {
>   final String who=iter.next();
> }
>
> wherein it's not strange that who can be final.

     Not really "like" at all, because (as you go on to observe)
the latter won't compile ...

> My second surprise was that the compiler rejects
>
> String[] foo={"a", "b"};
> for (final Iterator<String> iter=foo.iterator(); iter.hasNext(); ) {
>   final String who=iter.next();
> }
>
> apparently because arrays, unlike everything else accepted after the :
> in a for(:), do not actually implement the Iterable interface.

     No, they don't.  Observe that an array of primitives would be
unable to implement Iterable anyhow, because an Iterator's next()
must deliver an object reference.  (The sharp distinction between
primitives and references is, I think, a shortcoming of Java -- but
it's there nonetheless, and we have to live with it.)  For an array,
the code looks pretty much like

	for (Type thing : array) ...

	// Roughly equivalent to
	Type[] $array = array;
	for (int $idx = 0; $idx < $array.length; ++$idx) {
	    thing = $array[$idx];
	    ...

(Note that the loop uses the `$array' temporary variable instead of
`array' itself; if `array' gets changed the loop continues its march
across the original array, not its replacement.)

     The relevant bit of the JLS is at

http://docs.oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-14.14.2

-- 
esosman@comcast-dot-net.invalid
"Don't be afraid of work. Make work afraid of you." -- TLM

[toc] | [prev] | [next] | [standalone]


#34747

FromDaniel Pitts <usenet@coloraura.com>
Date2016-07-01 15:08 -0700
Message-ID<nl6pks$68q$1@dont-email.me>
In reply to#34746
On 7/1/16 12:07 PM, Eric Sosman wrote:
> On 7/1/2016 1:55 PM, Mike Amling wrote:
>> I was surprised that the javac compiler accepted the following:
>>
>> String[] foo={"a", "b"};
>> for (final String who : foo) {
>> }
>>
>> because it seems strange to have a for loop's variable work when final.
>
>     Well, the "for loop's variable" is not a particularly rigorous
> description.  Examples:
>
>     for (int i=0,j=10; i < j; ++i,--j) ...
>
>     for (; !theList.isEmpty(); theList.remove(0)) ...
>
> Neither of these has a unique obvious "loop variable."
>
>> After all,
>>
>> for (final int i=0; i<7; ++i) {
>> }
>>
>> gets an error.
>
>     Yes, and I think that's unfortunate.  Sometimes I want to use
> `i' in a lambda expression (or in a nested class), and I must write
>
>     for (int i = 0; i < 7; ++i) {
>         final int iFinal = i;
>         // use iFinal in the lambda
>     }

Or something along the lines: IntStream.range(0, 7).forEach(i -> 
doSomethingWithLambda(() -> doSomethingWith(i));

 > [snip]

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.java.programmer


csiph-web