Friday, August 10, 2007

You get spoiled by languages with first-class functions

Earlier today, I needed to take a list of strings and grab all of them that end with ".html". Very simple task. My first thought is of course something like:

[fn for fn in fns if fn.endswith(".html")]

Or even:
filter( lambda x: x.endsWith(".html"), fns)

Or the equivalent Lisp. Y'know, with "loop" and "collect". (Common Lisp has, as they say, the Cadillac of loop syntax)

Or something to that extent. But then I remembered that I was writing in Java, and I ended up writing a for-loop. There's no clean, idiomatic way to say that in Java, is there? Do you have to build up the list procedurally? ...


Mark Luffel said...

Or a Haskell rendition:

htmlFiles = List.filter (List.isSuffixOf ".html")

Have you read the Kingdom of the Nouns rant?

And yes, the idiomatic way is the procedural for-loop.
One way around this frustration is to use something like IntelliJ's Live Templates, which expand into blocks of code that express typical patterns and allow you to "fill in the blanks" with your .endswith or similar.

Alex R. said...

A lovely rant indeed! SteveY is a smart dude.

It's certainly easier to do this in dynamically typed languages; you just pass a reference to the function, obtained from its name, and it's up to the caller to invoke the function with the proper arguments and use its return value correctly.

But many statically-typed languages have first-class functions as well. This includes verbosely-typed languages like C and C++, and also type-inferring languages like Haskell and ML. The languages just need to provide a syntax for creating, passing and invoking function literals with an appropriate type signature.

That's the whole point!