» Saturday, 3 February A.D. 2007
random acts of functional programming
For all the beauty and enjoyment that comes from functional programming, I find myself writing out the same old loops time after time. Some times this because I'm programming in a language (C) where functional programming is not really an option. Other times it's because I'm prematurely optimizing in my head and I don't trust the compiler to work its magic on my code. But most of the time, it's because I just don't think about the functional solution to my code.
I had two opportunities to think about functional solutions at work yesterday. The first is pretty standard, I think; I had to comb through a list of objects and produce two lists, each containing objects satisfying some property. I wrote the equivalent of:
(loop for x in list when (pred1-p x) collect x into result1 when (pred2-p x) collect x into result2 finally (return (values result1 result 2)))
It wasn't quite as elegant in the source language because I had to initialize result1 and result2, but you get the idea. Some of the quick readers in the group may have grasped from the specification that the “better” solution is:
(values (remove-if-not #'pred1 list) (remove-if-not #'pred2 list))
This also has the nice property of working interchangeably with vectors, whereas the explicit loop would require source changes.
The second one was a little less obvious to me. I had a list of objects and I needed a list of the first objects whose 'filename' property differed from the previous object. I should also note here that the objects were sorted by the 'filename' property, so that all the objects with filename 'A' came first, then all the ones with 'B', and so forth. I've written out a similar loop for this sort of problem before. But yesterday, the bolt of inspiration struck:
(remove-duplicates list :key #'filename :from-end t)
(The :FROM-END there is really necessary; otherwise, you'll get the last duplicate in the list, which is not what we want in this case.)
I blame this one on having to write in an unfriendly language (C). But I'm not sure that the functional solution would have come to me as easily in a functional-friendly language.
Of course, as I write out the specifications for this blog post, it's obvious to me that I should have been using remove-if-not and remove-duplicates. I guess I just need to learn to specify my problems a little more fully to myself and to think more functionally about my specification.
posted by Nate @ 3:12PM