same loop for all data type.. (List, Struct, Array)

10 views
Skip to first unread message

Henry Ho

unread,
Feb 18, 2010, 8:51:15 PM2/18/10
to CFML Conventional Wisdom
It'd be nice if say, for..in loop works with all of the types (i.e.
List, Struct, Array).

Marko Simic

unread,
Feb 19, 2010, 7:25:36 PM2/19/10
to CFML Conventional Wisdom
Which is what I dream (while I am awake :)) for a long, long time:

foreach(ITEM in COLLECTION){}

That is:
a) Array: foreach(ELEMENT in ARRAY){}
b) List: foreach(ELEMENT in LIST){}
c) Structure: foreach(KEY in STRUCT){}
d) Query: foreach(ROW in QUERY){}
e) File: foreach(LINE in FILE){}
f) COM/DCOM: foreach(ITEM in (D)COM){}

Note:

b) This requires additional parameter for separator.
d) Cell value = ROW[COL_NAME], Current position:
ROW.CurrentPosition, ...

Best Regards,
Marko Simic

Matthew Woodward

unread,
Feb 21, 2010, 10:13:52 AM2/21/10
to cfml-convent...@googlegroups.com
On Fri, Feb 19, 2010 at 4:25 PM, Marko Simic <marko...@gmail.com> wrote:
b) This requires additional parameter for separator.

Or perhaps lists could "know" what their delimiter is? Might require doing something like myList.setDelimiter("|") but then the loop syntax wouldn't have to incorporate that.
 
d) Cell value = ROW[COL_NAME], Current position:
ROW.CurrentPosition, ...

Isn't CurrentPosition the same as myQuery.CurrentRow, or are you getting at something else here?

--
Matthew Woodward
ma...@mattwoodward.com
http://blog.mattwoodward.com
identi.ca/Twitter: @mpwoodward

Please do not send me proprietary file formats such as Word, PowerPoint, etc. as attachments.
http://www.gnu.org/philosophy/no-word-attachments.html

Alan Williamson

unread,
Feb 21, 2010, 10:16:41 AM2/21/10
to cfml-convent...@googlegroups.com
i was thinking about this in the plane yesterday ... how about a new tag
for this:

<cfforeach element="" object="">

</cfforeach>

i am not sold on the "object" parameter name.

Matthew Woodward

unread,
Feb 21, 2010, 10:53:31 AM2/21/10
to cfml-convent...@googlegroups.com
On Sun, Feb 21, 2010 at 7:16 AM, Alan Williamson <al...@aw20.co.uk> wrote:
i was thinking about this in the plane yesterday ... how about a new tag for this:

<cfforeach element="" object="">

</cfforeach>

i am not sold on the "object" parameter name.


I like it! Maybe "var" instead of "object" for consistency with a couple of other tags?

Mark Jones

unread,
Feb 21, 2010, 11:50:01 AM2/21/10
to cfml-convent...@googlegroups.com
>> b) This requires additional parameter for separator.
>
> Or perhaps lists could "know" what their delimiter is? Might require doing
> something like myList.setDelimiter("|") but then the loop syntax wouldn't
> have to incorporate that.

Interesting, but wouldn't that, in turn, require that lists be
promoted to a formal datatype? As opposed to an informal one and a
very convenient way to manipulate strings. I guess maybe it could be
added to the String datatype, but then you have to address the
questions of concatenation, datatype conversions, etc.

foreach( ELEMENT in LIST, delimiter="|") works fine for me, if this
sort of syntax exists on other places.

Matthew Woodward

unread,
Feb 21, 2010, 3:19:54 PM2/21/10
to cfml-convent...@googlegroups.com
On Sun, Feb 21, 2010 at 8:50 AM, Mark Jones <mark...@visi.com> wrote:
Interesting, but wouldn't that, in turn, require that lists be
promoted to a formal datatype?

Well maybe, and I don't know the inner workings well enough to say, but it might not necessarily mean you'd have to do anything special in terms of the general use of lists in your code.

In other words I don't see why you couldn't do:
<cfset mylist = "1|2|3" />

And if you want to later use that in a loop, since it isn't the default of , for the delimiter:
<cfset mylist.setDelimiter("|") />

And then:
foreach(element in mylist)

Sticking the delimiter in the loop statement itself seems rather awkward to me, but now that I type this all out, having to say setDelimiter on a list that's already been created doesn't seem much less awkward. I guess given that all the existing list functions operate on lists based on the delimiter you pass to the functions when you're doing the list manipulation, maybe indicating the delimiter when the loop is run is more consistent conceptually.

More to ponder. ;-)

Peter J. Farrell

unread,
Feb 21, 2010, 3:45:16 PM2/21/10
to cfml-convent...@googlegroups.com
I've always wondered why we don't have "list" datatype in CFML anyways?  It would be nice to do something like:

<cfset var myList = ListNew("|") />

This would create a list with a delimiter of "|".  We already have StructNew() / ArrayNew(1) and all the related functions to append/prepend etc.

If you could set the list delimiter on the list itself, then you could just do:

foreach(element in mylist) {

}

Matthew Woodward said the following on 21/02/10 14:19:

Matthew Woodward

unread,
Feb 21, 2010, 3:48:40 PM2/21/10
to cfml-convent...@googlegroups.com
On Sun, Feb 21, 2010 at 12:45 PM, Peter J. Farrell <pe...@mach-ii.com> wrote:
I've always wondered why we don't have "list" datatype in CFML anyways?  It would be nice to do something like:

<cfset var myList = ListNew("|") />

Right, which would take it up to the level of a "real" datatype as Mark was saying. Personally I think that's fine but it does remove some of the convenience factor to which Mark was referring. And that also begs the question if we're going to go that route, why not tell people to use the underlying split() method on the underlying String class in Java and loop over an array instead.

As you can probably tell I'm still undecided on the best way to go here. ;-)

Marko Simic

unread,
Feb 21, 2010, 5:02:19 PM2/21/10
to CFML Conventional Wisdom
@Matthew You are right about CurrentRow. Just wanted to emphasize
necessity for such attribute to exist.

About separator. I doubt that auto-recognition of separator could
work. How parser could recognize what is separator, if anything can be
a separator and is that "rcognized char" separator at all, for
instance: how could you tell is "-" a separator or part of word "2-
dim" - this could be a list of 1 element "2-dim", as well as list of 2
elements separated by "-".

But, I like the idea of promoting a list to a data type. At the same
time you are right about split() method.

Best Regards,
Marko Simic

On Feb 21, 9:48 pm, Matthew Woodward <m...@mattwoodward.com> wrote:
> On Sun, Feb 21, 2010 at 12:45 PM, Peter J. Farrell <pe...@mach-ii.com>wrote:
>
> >  I've always wondered why we don't have "list" datatype in CFML anyways?
> > It would be nice to do something like:
>
> > <cfset var myList = ListNew("|") />
>
> Right, which would take it up to the level of a "real" datatype as Mark was
> saying. Personally I think that's fine but it does remove some of the
> convenience factor to which Mark was referring. And that also begs the
> question if we're going to go that route, why not tell people to use the
> underlying split() method on the underlying String class in Java and loop
> over an array instead.
>
> As you can probably tell I'm still undecided on the best way to go here. ;-)
> --
> Matthew Woodward

> m...@mattwoodward.comhttp://blog.mattwoodward.com

Mark Jones

unread,
Feb 21, 2010, 5:41:39 PM2/21/10
to cfml-convent...@googlegroups.com
> I've always wondered why we don't have "list" datatype in CFML anyways?

Because it's just a string. The only thing lists have above arrays is
that you can "pretend" that any string is a list. You loop over files
by pretending that it's a list delimited by CRLF. You can grab the
username from an email address by doing ListFirst( address, "@"), etc.

It would take a lot of work to convince me that List should be a
native datatype like Struct or Array. It *looks* like it could be one
because of all the List* functions, but really they're just
specialized string functions that utilize array logic under the hood.

I can maybe see adding a magical hidden attribute on strings in
general that sets a delimiter and defaults to "," but even that raises
some questions. If you set a list delimiter on one string, and then
append it to a new string, does the new string have that delimiter?
What if the other string had a *different* delimiter defined?

I love the List* functions in CFML because so much of building web
apps is string manipulation. But I've always seen the List functions
as a convenience for dealing with strings. The only thing about them
I've seen give people problems is that things like ListAppend() return
*a new string* whereas ArrayAppend() modifies the original one.
Fixing *that* would require changing how strings are handled overall.

Sean Corfield

unread,
Feb 26, 2010, 1:09:15 AM2/26/10
to cfml-convent...@googlegroups.com
On Fri, Feb 19, 2010 at 4:25 PM, Marko Simic <marko...@gmail.com> wrote:
> Which is what I dream (while I am awake :)) for a long, long time:
>
> foreach(ITEM in COLLECTION){}

You can say:

for ( item in collection ) { ... }

> a) Array: foreach(ELEMENT in ARRAY){}

That already works in Railo:

for ( i in [ 4, 3, 2, 1 ] ) {
writeOutput( i & '=' & x[ i ] & '<br />' );
}

(i is the index, like in <cfloop>)

> b) List: foreach(ELEMENT in LIST){}

You'd need a way to specify the delimiter if it wasn't ',' - the CFML
Advisory Committee discussed this possibility:

for ( x in "l|i|s|t"; delimiters = '|' ) { ... } // delimiters optional

> c) Structure: foreach(KEY in STRUCT){}

Already works in CF8+ / Railo:

for ( k in { a = 1, b = 2 } ) { ... }

> d) Query: foreach(ROW in QUERY){}

That would be nice. Again, the CFML Advisory Committee discussed this
and was in favor of adding it (6 for, 1 opposed):

for ( r in qry; startrow = 100; endrow = 199 ) { ... } //
startrow/endrow optional

> e) File: foreach(LINE in FILE){}

Also discussed the Committee and everyone was in favor of this:

for ( x in filepath; characters = n ) { ... } // characters optional

Our only concern was how you could tell lists from filepaths in the
default case.
--
Sean A Corfield -- (904) 302-SEAN
Railo Technologies US -- http://getrailo.com/
An Architect's View -- http://corfield.org/

"If you're not annoying somebody, you're not really alive."
-- Margaret Atwood

Simon Horwith

unread,
Feb 26, 2010, 9:46:58 AM2/26/10
to cfml-convent...@googlegroups.com
that's interesting - I didn't realize Railo already had that.
What I've always liked in languages is support for both 'for' and 'for-each' - the difference between the two being that 'for' always holds the key value (struct key name, array index value, etc.) and a for-each loop doesn't expose the key but, rather, uses the value of the key as the loop counter value (so it would be each actual item in an array, not the index, for example).  Of course, from an implementation point of view, this for-each loop type probably won't perform as well, because you've got to cast the counter to various data types as you loop.

I think the language should encourage named parameters to (built-in) functions.  A for-each loop over a list might allow a 'listdelim' argument, whereas a loop over an array or struct might allow a 'sort-function' argument for pre-sorting the complex data first.  One thing I'd really like to see, while on the topic of lists, is a real list implementation - one that doesn't just treat strings as lists but actually supports a list data-type under the hood.  For one thing, this would perform much better when repetitively using large lists... for another, it would allow for list nesting - something we should be able to do.  The current CFML implementation of lists is, in my opinion, the worst implementation in the language.

~Simon
Simon Horwith
CTO, Nylon Technology
http://www.nylontechnology.com
blog - http://www.horwith.com

Mark Jones

unread,
Feb 26, 2010, 10:13:40 AM2/26/10
to cfml-convent...@googlegroups.com
> One thing I'd really like
> to see, while on the topic of lists, is a real list implementation - one
> that doesn't just treat strings as lists but actually supports a list
> data-type under the hood.

To be the devil's advocate... isn't that an Array? There are a few
things that are currently easier to do with lists than Arrays (mostly
because of having to define the dimensions upon ArrayNew() and the
like), but a list *is* an array in string form... Maybe it would be
more constructive to identify *those* differences and make list <->
Array conversions simpler?

> for another, it would allow for list nesting - something we should be able to do.

I do this all the time. CSVs, for example, are comma-delimited-lists
nested inside CRLF-delimited lists. You have to have unique
delimiters that you manage separately, which is probably your point.

> The current CFML implementation of lists is, in my opinion, the worst implementation in the
> language.

I completely disagree, but that's because I'm not viewing "list" as a
data-type, more as a specialized way of dealing with string
manipulation.

If there's a way to formalize it without complicating it, I'd be all for it.

One use-case to keep in mind: form variables of checkboxes or the
like. It comes through as a string/list of the values checked. It
would be great if this were also available as an array, but a)
changing it from a list would be a big break and b) please, PLEASE do
not require a PHP-style change to the source HTML (<input
type="checkbox" name="colors[]">)

Simon Horwith

unread,
Feb 26, 2010, 11:16:28 AM2/26/10
to cfml-convent...@googlegroups.com
a list is VERY similar to an array, you are right... but they are more than complex... they are also treated as flat (printable) data, which arrays are not. Arrays can have empty arguments - CF doesn't treat empty list elements correctly. I definitely do view lists as a real data type... or as something that SHOULD be a real data type, anyway.  I do think that if CF handled conversion between lists and arrays better, AND supported list to struct conversions, the list data type wouldn't be something we need and the list functionality (which should should be renamed to string-as-list functionality) would be fine for some string manipulation tasks.  The strength of a datatype is generally in the functionality it supports - aside from some performance differences, the real reason to choose storing data in an array vs struct vs XML vs list vs etc., etc. is in the functionality available to you with that data type.  Being able to quickly get a string into whatever data type you want (and back out) is something we should have.  The code you have to write to treat list elements as lists is, compared to what it should be, ugly, inefficient, and inconsistent.  Were lists true data types, we could simply have list elements that are lists (or pointers to other lists).

I should qualify everything I say by pointing out that I'm a huge fan of (and amateur developer with) LISP - the king of all LIST handling languages.  In that world, lists are not just a data type and not just the most fundamental data type... they're your code, too.  This experience has probably tainted and warped my personal views of lists to an extreme from which there's no coming back ;)

~Simon


Simon Horwith
CTO, Nylon Technology
http://www.nylontechnology.com
blog - http://www.horwith.com



Marko Simic

unread,
Feb 28, 2010, 5:21:29 AM2/28/10
to CFML Conventional Wisdom
You are right Sean, but beside functionality implementation
consistency matters too.

> Our only concern was how you could tell lists from filepaths in the
> default case.

I didn't get this one. Would you be so kind to say few more words
about this?

Best Regards,
Marko Simic

On Feb 26, 7:09 am, Sean Corfield <seancorfi...@gmail.com> wrote:

> Railo Technologies US --http://getrailo.com/
> An Architect's View --http://corfield.org/

Sean Corfield

unread,
Mar 9, 2010, 1:36:50 PM3/9/10
to cfml-convent...@googlegroups.com
On Sun, Feb 28, 2010 at 2:21 AM, Marko Simic <marko...@gmail.com> wrote:
>> Our only concern was how you could tell lists from filepaths in the
>> default case.
> I didn't get this one. Would you be so kind to say few more words
> about this?

Sure, lists and filepaths are both just strings:

for ( x in "path,1/to/file.ext,2" ) // is this a list or a file?

The default for lists is most naturally delimiters="," and the default
for files in by line (not by character) since that's how <cfloop>
works.

for ( x in "path,1/to/file.ext,2"; characters = 1 ) // read
char-by-char from file

for ( x in "path,1/to/file.ext,2"; delimiters = "," ) // path then
1/to/file.ext then 2

And of course filepaths can - and often are - viewed as lists with a
"/" delimiter:

for ( x in "path,1/to/file.ext,2"; delimiters = "/" ) // path,1 then
to then file.ext,2


--
Sean A Corfield -- (904) 302-SEAN

Railo Technologies US -- http://getrailo.com/
An Architect's View -- http://corfield.org/

Marko Simic

unread,
Mar 10, 2010, 9:40:43 PM3/10/10
to CFML Conventional Wisdom
Thank you for clarification.

Some ideas:
a) By default take collection as list, otherwise set "isFile" flag
for ( x in "path,1/to/file.ext,2", isFile=true )
But this would break the idea of "no-brain" collection browser.

b) New data type. Not List but File, but, honestly I would like to see
both :)
"fileNew()" or "new File()" can be just a wrapper around java.io.File
class.

Best Regards,
Marko Simic

On Mar 9, 7:36 pm, Sean Corfield <seancorfi...@gmail.com> wrote:


> On Sun, Feb 28, 2010 at 2:21 AM, Marko Simic <marko.si...@gmail.com> wrote:
> >> Our only concern was how you could tell lists from filepaths in the
> >> default case.
> > I didn't get this one. Would you be so kind to say few more words
> > about this?
>
> Sure, lists and filepaths are both just strings:
>
> for ( x in "path,1/to/file.ext,2" ) // is this a list or a file?
>
> The default for lists is most naturally delimiters="," and the default
> for files in by line (not by character) since that's how <cfloop>
> works.
>
> for ( x in "path,1/to/file.ext,2"; characters = 1 ) // read
> char-by-char from file
>
> for ( x in "path,1/to/file.ext,2"; delimiters = "," ) // path then
> 1/to/file.ext then 2
>
> And of course filepaths can - and often are - viewed as lists with a
> "/" delimiter:
>
> for ( x in "path,1/to/file.ext,2"; delimiters = "/" ) // path,1 then
> to then file.ext,2
> --
> Sean A Corfield -- (904) 302-SEAN

> Railo Technologies US --http://getrailo.com/
> An Architect's View --http://corfield.org/

Reply all
Reply to author
Forward
0 new messages