Wednesday 2 April 2014

Survey results: lists in CFML, and the naming of list member functions

I didn't quite get 50 results for this survey, but so be it. It wasn't a terribly interesting one, granted. So, what do people think about lists, list functions, and what the approach to the naming of list member functions should be?

The subject line of the survey was:
ColdFusion 11 and Railo 4 have added "member functions" to CFML, so one can call a method on an object, rather than pass an object to a function. ColdFusion has implemented list functions as member functions of a string, and in the process have blurred the distinction between what's a list function and what's a string function. There is conversation about this on the Railo Google Group, and this has lead me to wonder what the community participants think about Adobe's approach here.
There were five questions.

1. Do you chiefly use/concern yourself with ColdFusion or Railo?

This was just to gauge where people were coming from.

I think 30% is pretty good for Railo. However the readership here would be a niche segment of the CFML community (not because this blog is high brow - far bloody from it!), but because most CFML developers don't really participate in our community.

I checked to see if people saying "ColdFusion" as opposed to "Railo" significantly trended their answers a certain way, but nothing really stood out.

2. Which best reflects your opinion on the concept of "lists" as a CFML "data type"?

It's interesting that people erred more towards lists being a good thing. Although the sample size is so small that's a bit meaningless.

There were quite a number of additional comments with this question:

Never gave it much thought until you brought it up. They are there, I use them occasionally for short sets of data

I know lists exist, but i typically use array

They have long been a part of CFML, and are present in a number of places (e.g., HTML form attributes for checkboxes come through as lists, query.columnList) within the language. We use them. They are a simple and useful data structure. Can they be abused or used in situations that other data structures would make more sense? Sure.

These are just 'strings', but then again, so is a JSON structure. To me, there is very little difference between: "one,two,three" and '["one","two","three"]'. I've always thought that when I wanted to perform any list function, CF converted my string to an array, performed it's action, and then popped it back to a string.
I suspect it doesn't do that.

A list in many languages is a proper data type on its own with specific benefits. CFML lists, being just strings, I cannot condone.

They aren't a data type, but I think it is ok to have them as a concept. Many of the list functions are useful when manipulating strings.

I think lists are great, but because they are also strings, it makes it difficult to explain the differences between lists and strings. In CFML, a list is a string (given a delimiter), and any string can be a list, and each can be treated as the other. This has the benefit of allowing quick loops over strings, outputting lists (in most languages, a more difficult task), and easily specifying custom delimiters to break up a string, but if CFML had a true list construct (akin to an ArrayList, on the level of Structs and Arrays, but would toString() just by outputting), I think things could be improved dramatically. Right now, it's a sloppy mess.

Works well for simple handling of data. Lists are far quicker to define than structures and there is a place for lists in my heart. Lots of times I've been supplied with lists and it's nice to work with them in this form just by pasting them into my code. Lists are a great feature of CFML and like most things you should choose the right tool for each job. Sometimes you just have to use arrays or structs if things get slightly complicated. Viva lists!

I can see the benefit of a "list" data type, remembering back when I was a junior level, I had used them quite a bit. Having "lists" helps with adoption for new developers just starting out that may struggle with arrays and is somewhat unique to the language. However since CF is very loose with data types, overall I'm not sure they make sense. Issue now is they are part of the language and not going anywhere.
You see I think that newbies' reliance on lists is the cause of often CFML developers never becoming comfortable with arrays / structs. It's another example of where dumbing-down the language is - long-term - counterproductive.

I use list functions as a quick way to split up strings. I also use it to sent list of things to arrays as in listToArray.

I'm neutral. I think of them in the manner ColdFusion does because, well, ColdFusion looks at them as such. However, if lists were to be no more and I had to look at it as a string, it's no bother. 9 times out of 10 I end of converting them to arrays for manipulation etc. anyway.

It's an artifact of the "Let's make CFML simple so non-programmers can use it." days - and it was made worse by the ridiculous handling of empty elements in the "list"!
The "empty elements don't count" thing made lists unusable for many situations, in my experience. It was a frickin' stupid idea from the outset. They should always have respected empty elements, and simply provided a listCompact() (or something) function to get rid of empty elements if that's what someone wanted to do.

Personally, I love list data types and that their are specific functions for working with them. Sure, it's really just a wrapper for working with strings and/or simple arrays, but we use List functions a lot and like them.

I find lists to be very useful. I know it can be easily done as an array, but I do find the list functions useful.

I use them all the time to extract directories from paths, names/extensions from files, etc... Very handy in my book. Now, that could be done via listToArray, but not having to do that is a convenience that I don't think hurts anything/anyone.

I don't really consider lists to be a cfml datatype. in the past, we've just had list aware functions that have worked on strings. I've found it to be a convenience factor to use string as list, though I mostly turn them into arrays because I've found arrays to be more reliable. the ability to treat a string as a list has some useful side benefits in that string parsing/manipulation is easier

3. Some ColdFusion "list" member functions[...]

[...] where there is no string-centric function of the same name - drop the "list" prefix from the function name. EG: the listAppend(list) member function is simply string.append(). Whereas where there is already a string-3. centric function, the list prefix is maintained, eg: listFind(list) => string.listFind(). What is your opinion of this?

A couple of the options are truncated on the chart here. They read:

1) this is a poor approach: list functions should always have the "list" prefix in their name
5) this approach is fine: there is insufficient ambiguity here for it to be a problem

My own answer was (1), so I'm pleased three quarters of people tend to agree. This might suggest Adobe need to rethink their approach in ColdFusion 11.

And some comments:

They should all be prefixed with list, not only for the reasons given, consistency, new name is often misleading etc, but also because the new 'list' less names are taking names that could be useful string functions that do what the name suggests.

I really like the idea of having member functions available to simplify the language syntax. Where lists in CFML really are just strings, I think the only thing that makes sense is to use the list...() prefix.

With all of the other random inconsistencies within CF, I'm not too surprised. But I'd rather that everything be named the same way and start with list

I would expect "a".append("b") to return "ab", not "a,b", having it as listAppend() avoids this confusion.

Language consistency is powerful. Take a look at PHP to see how inconsistencies have turned out.

Function names should be as consistent as possible. Coldfusion right now is a huge hodgepodge of naming conventions.

I think there needs to be something to indicate that these functions will be acting on the string as if it was a list. Also if they wanted to add an append method that just appended to a string that name would already be taken. You probably wouldn't do that but there could be other cases where that would come up.

string.append() means you are adding one string to another. string.listAppend() means you are adding an item to a list, where the string is a list.

Clarity and consistency are paramount. I hate inconsistencies, it makes things more difficult to remember and bashing out code is more prone to error. It's illogical. Coding is all about logic and if the language is lacking in naming logic then that's a pretty crappy start, especially for people looking at CFML for the first time.

Since the base class of both string and list is really "string", I almost think prefixing with "list" is a requirement to prevent any confusion for future functionality. What I personally would like to see is having to explicitly define a variable as a "list"; otherwise a similar member function would act like a string. Not sure how feasible this is, as I'm sure the underlying class of a list is really a string, but I'm sure it's not beyond possibilities. Things would look like this. param name="mYList" default="x,y,z" type="list"; myList.append(); myList.find(); myList.last(); ... and beyond cfscript, maybe having a cflist tag. .... To me this is essentially the same as cfimage, cfquery and other tags that return explicit types.

It's indicative of Adobe's slap-dash approach to language "design" (i.e., they don't think stuff through properly).

I do agree that they should be clearly delineated versus this blending described - one of my biggest frustration with some other languages, like PHP, is this sort of confusing mix. One thing I've always liked about CF is consistency in function names, and this messes that up.

It's a poor approach to be inconsistent. I personally like not having the "list" prefix as its obvious by the intent. If I was to do "string".first(), I would know I'm working with the string as a list (or an array). "string".find()* should probably be renamed to "string".indexOf().

The - almost ubiquitous - gist of the comments is that the list-specific methods should be prefixed with list. I agree.

To the people answering "it's fine" (from the multi-choice options; no-one who commented suggested it was fine), can you please tell me what you'd expect from this code:

options = "1) first; 2) second";
options.replace("1,2", "i,ii");

4. Railo are giving thought to adding list-oriented member functions. What are your thoughts on this?

Again, SurveyMonkey has truncated the options here:
1) don't bother. Don't encourage list usage;
5) it's essential to add list-oriented member functions.

I suppose general ambivalence here is fair enough. I suppose one can just opt to not use list member functions if they are there, and just ignoring something causes no harm. That said, I see an awful lot of code torturously relying on lists where arrays would be a better fit, and if I was around when CFML was being planned, I'd veto the idea of lists as "a thing".

5. Anything else to add?

If Railo are to maintain some level of syntax parity with Adobe, I think they must add these (regardless of how stupid the ACF implementation is). List functions are not the type of functionality that I would expect to be the force driving a wedge between the two platforms - compatibility wise.
This is a good point. "Implemented them but don't encourage them", perhaps?

Personally, I do think Railo should support all functions/tags from CFML, regardless of whether they "like" them or not. Yes, I get that some people are of the opinion that some tags/functions are stupid, useless, etc and that there is no official "standard" for CFML, but IMHO Railo cannot be seen as a valid alternative to Adobe's CF if it will not actually support the full breath of current CFML tags/functions.
On the other hand, what if they are positioning themselves as the leader of the direct that CFML takes, these days? Which I think is accurate.

I've seen a lot of code in the wild that does horrible crap like this: cfloop index="i" from="1" to="#listlen(s)#" cfset x = listGetAt(s,i) ... do stuff with x ... /cfloop Inefficient and ugly! No wonder CFML devs have such a bad reputation and everyone thinks CFML is really slow!
Yeah, list usage should definitely - in general - be actively discourage, I think.

So many other ways to do "lists" without JSONizing the language.

Personally, I would like to see the name qualifiers removed from all member functions. Simplify the syntax. In general: move the language toward something like Ruby's "everything's an object" while we're at it. When coding in pure Ruby I find that I love so much of the "object-ness" but dislike the look of some of the syntax. When coding in CFML, I feel the opposite... in general I would like a mixture of the two.
My thoughts are much the same.

I think if Railo wants to tout itself as a CF replacement, it should follow the Adobe road map and feature set as closely as possible. Especially when it comes to basic core functionality, which I think member functions fall into. That being said, I don't have a problem with Railo taking the lead and implementing them right. Meaning either require explicit definition of a variable as a "list" and implementing names without a "list" prefix, or option 2, implementing member functions all prefixed with "list". Maybe an even better option for Railo would be to require the explicit variable definition, and then implement member functions with and without a prefix. This would make migration from CF to Railo a matter of the parameter initialization with either of these: or param name="myList" default="x,y,z" type='list';
Hmmm... one cannot win a race by playing follow the leader though. That'll always just land you in second.

So long as it doesn't break any compatibility if code is moved off a CF server and put onto a Railo server. I guess the other way around isn't a huge concern. :-)

Thanks, Adam -@nathanstrutz
No worries mate.

Lists can easily be replaced with Arrays. That being said, I often find myself using lists when working with strings simply because they're available in the language.
So do I, sometimes. If I am given a string - like a file path - I'm completely fine with using listLast() to get the filename.

I see no real benefit to them. I've heard examples of their usage for handy things such as splitting extensions from file names and such. But here we can take cues from languages like Python: fileName, fileExtension = os.path.splitext("/path/to/file.jpg")
Aha! "Great minds [etc]".

We've moved off of lists in the vast majority of cases for arrays, so in the rare cases that we do need listAppend, we can use the BIF if there is no equivalent member function.
This is a good point. It's not like the procedural-oriented functions are going away.

If every other 'tag based' function is going to have a member function, then skipping a set for some reason just seems wrong.
The premise is that "lists" don't really exist. They're just strings.

For the sake of the language consistency, lists should have member functions... but as you note, they need to be clearly named to avoid collisions with string member functions.
I think this is actually the most pragmatic approach, yes.

As usual, Railo is damned if they do and damned if they don't. They have to copy the ill thought out crap that comes out of Adobe to stay compatible. We all know it's wrong (well.. except Adobe) but what else can they do, perhaps they could implement them and immediately deprecate them and recommend they are not used.
Hopefully Adobe can be encouraged to rethink how they've tackled these. On the basis of the comments here, I will be raising a ticket to get this addressed in ColdFusion 11: 3735413.

I think the general gist is that Railo should implement the list member functions, but they should be prefixed with "list", yes?

I'd go with that.

Cheers for the input, everyone!.