I’m currently working on a personal project by way of learning Clojure – it’s actually a program to match up my itemised phone bill against my list of contacts to help me expense my calls. I find it best to have a real-world problem I need to solve to learn a new programming language. The problem itself is rather dull, but it did give me a chance to consider an issue I’ve hit with many other languages.
One of the core parts of my telephone expense program is the process of normalising phone numbers so I can match them up. What I am trying to do is something long the lines of:
Strip spaces, then add the missing area code, then internationalize it
So in Clojure there are a number of functions I’ve written, each of which take, and return, a string (the program is nowhere near finished, so consider this to be virtually pseudo code) :
(defn #^String normalize [str] (internationalize (add-missing-areacode (strip-spaces str))))
In Java, this would look like:
public String normalize(String str) { return internationalize(addMissingAreaCode(stripSpaces(str))); }
The problem is that I, and most of the western world, read from left to right – with both Java and Clojure I’m having to read from right to left to determine what is being done. One system I use frequently has a construct which matches what I’m after – UNIX:
strip-spaces "44 1230 9183" | add-area-code | internationalize
So what other languages support this kind of construct? I suspect I could coax Scala into doing something like this, and it seems that it is right up Python’s alley (Django’s excellent templating system has filters which do exactly that). But if I want to use Clojure, am I stuck with this inside-out programming model? What other JVM-based languages would help me here – Ioke perhaps? It seems right up AINC’s alley, but that syntax makes me want to cry…
Update 11 Jan 2010: Thanks to Matt for pointing me towards Clojure’s ‘->
‘ macro. This looks pretty close to what I’m after. So I *think* I should be able to do something along the lines of:
(-> phoneNumber stripSpaces addAreaCode internationalize)
Which is very cool.
6 Responses to “Data Transformation and Language Syntax”
Ioke could definitely do it, although I don’t have an operator for it right now. I’ve considered adding it, though. I would probably not send around raw strings – so if you assume you have something else, you can simply do it like this, where the three methods are defined on PhoneNumberText
PhoneNumberText from(“44 1230 9183”) stripSpaces addAreaCode internationalize
F# have a serialization construct with the |> operator. You can also use <| for it. Take a look in Needhams blog for a number of examples.
So if I understand correctly what you want to do is compose several functions together in the order in which they’re executed against the input?
If so could you make use of the ‘comp’ function in Clojure or is that the wrong way around which is what I’m maybe thinking after reading the docs again – http://richhickey.github.com/clojure/clojure.core-api.html#clojure.core/comp – ?
Ola: I’d really want to pass around whatever the functions return, rather than limiting myself to a raw string. Which I’d imagine limits me to a language with dynamic typing, or else jumping through lots of hoops getting a sufficiently advanced static typing system to be happy with it.
Mark: I think comp still works right to left from my reading of the docs.
try “->” macro, it threads your expression through a chain of function calls, regardless of the return values. http://exploringclojure.blogspot.com/2010/01/function-chaining.html
The standard is Haskell is to do right-to-left function composition like this:
normalize = internationalize . addAreaCode . stripSpaces
You do soon get used to reading these. However there is also a left-to-right composition operator, like this:
normalize = stripSpaces >>> addAreaCode >>> internationalize
Ben
Percocet….
Percocet. Long term use of percocet. Canadian prescriptions and percocet….