Note: Since this was first posted, foreach has been deprecated in favor of for, but the syntax and behavior are the same. I have modified this example and the post to reflect this.
I knew I couldn't fool you twice! Just as if/else
can be a statement or an expression, for
can be either as well. Compile and run the following example to experience this for yourself:
import java.lang.System;
class CompiledSequenceExample {
attribute ordinals:String[] = ["zero", "one", "two", "three",
"four", "five", "six"];
function printSomeOrdinals():Void {
for (lmnt in ordinals where lmnt.length() > 3) {
System.out.print("{lmnt} ");
}
System.out.println();
}
function getSomeOrdinals():String[] {
var elements =
for (lmnt in ordinals
where lmnt.length() > 3) lmnt;
return elements;
}
}
var example =
CompiledSequenceExample {
};
example.printSomeOrdinals();
System.out.println(example.getSomeOrdinals());
The foreach
and for
Keywords Have Been Simplified into Just for
The first occurrence of
for
in this example is a statement, very similar to the way for
is used in interpreted JavaFX Script.
The second occurrence of for
in this example is an expression, known as a sequence comprehension, which has a value that is assigned to the elements
variable. This form of for
has three parts:
- One or more input sequences (the
ordinals
sequence in this example). - An optional filter (
where lmnt.length() > 3
in this example). - An expression
(lmnt
in this example)
This value of a for
sequence comprehension is a sequence consisting of zero or more elements. The type of sequence is determined by the type of the expression (String
in this example, as lmnt
is implicitly typed as a String
). Consider the following modification to the getSomeOrdinals()
function in this example:
function getSomeOrdinals():Integer[] {
var elements =
for (lmnt in ordinals
where lmnt.length() > 3) lmnt.length();
return elements;
}
In this case the value of the for
expression is a sequence of type Integer
, whose elements consist of the length of each of the strings in the ordinals
sequence that are longer than 3 characters.
The final two lines of the program call the functions that contain the for
keywords, each printing the element values that meet the criteria of having a length greater than 3. Here is the console output of the original program:
zero three four five
[ zero, three, four, five ]
And here is the console output of the program with the modification shown above:
zero three four five
[ 4, 5, 4, 4 ]
Note: Since this last posted, Patrick Wright posed the following question: "Are the return in getSomeOrdinals() and the local variable necessary? I'm wondering if in this case the last statement in the block would be returned automatically, and one could just have the function block include the for."
That is a very insightful question, and the answer is that they are not necessary. The getSomeOrdinals() function could be written as follows:
function getSomeOrdinals():Integer[] {
for (lmnt in ordinals
where lmnt.length() > 3) lmnt.length();
}
This works because the value of a block expression is the value of its last expression. See the Express Yourself in Compiled JavaFX Script post for more details on block expressions.
If you have any additional questions on this example, please post a comment, as they prove very helpful in prompting me to provide additional info.
Regards,
Jim Weaver
JavaFX Script: Dynamic Java Scripting for Rich Internet/Client-side Applications
Immediate eBook (PDF) download available at the book's Apress site
Patrick,
Thanks for your comment/question. You are correct. The last statement in the block would be returned automatically, and one could just have the function block include the foreach. I added a code snippet in this post to illustrate your point.
Thanks, Jim Weaver
Posted by: Jim Weaver | December 06, 2007 at 11:23 AM
Thanks for the answer, Jim. It's clearer now on a re-read.
One followup--are the return in getSomeOrdinals() and the local variable necessary? I'm wondering if in this case the last statement in the block would be returned automatically, and one could just have the function block include the foreach.
Thanks
Patrick
Posted by: Patrick Wright | December 05, 2007 at 03:43 PM
Thanks for your feedback, Patrick. I have expounded on the foreach expression, so please let me know if further clarification would be helpful. -Jim
Posted by: Jim Weaver | December 04, 2007 at 09:37 AM
Hi Jim
Some clarification of the expression syntax in this case would be helpful. The loop is clear, but it's not clear what the effect is of having "element" as the sole expression within the loop, and how this ends up appending to the sequence elements. Will foreach always generate a sequence based on the last value in the foreach block? Or can I also create a single value--for example, could I use this foreach expression syntax to create a single string containing all the elements, comma-separated?
Interesting comparison, thanks.
Patrick
Posted by: Patrick Wright | December 04, 2007 at 01:55 AM