How  ‘resolve have solved my problem



When I found Clojure, it was with the intention to implement a high concurrent application to manage provisioning commands for Huawei Equipments. Meanwhile I was learning about  the concurrent toolset that comes with the language, then I found a small but not less important feature in Clojure: the use of symbols. After diving into this feature I discovered that the majority of Lisps dialects has it.

Having symbols means an additional  level of abstraction for development, the good news is that is 100% integrated with the evaluation process of Clojure, so you can create logic in your programs that explode this feature, as I did in my project. The problem was that I had to implement different functions to be dispatched depending of the command  received, I wanted to avoid write a switch/like structure for dispatching. The commands had this syntax:

ADO $ 19203212 CWI CWT $
ADO $ 19200242 CPC PRIOR $ Y $
DEO $ 16200213 CNDC $ Y $
ADO $ 16200212 CCW $ Y $

The first word give a top level behaviour (ADO,DEO, etc), then, depending of the arguments (like CWI, CCW, etc) it should goes to specific function. Clearly, I had to write five different functions for the previous commands, but to avoid a direct dispatching (hard coded)  I need something dynamics, before show the solutions, let me show you this idea of symbols in Clojure.

A symbol es just a string with certain constraints (like not start with a number), so a list in symbols is:
‘(john peter mary)

Note  that I have used an apostrophe so Clojure do not interpret the list as a  function invocation, which is the default behaviour for a list. I can count the members of the list with:
(count '(john peter mary))
=> 3

There is a function that let me verify if something is a symbol:

(symbol? 'any-func)
==> true


And, finally, there is another function that allows me to create a symbol from a string:
(symbol "other-func")
==> other-func
To complete the puzzle, there is another function that let me to resolve a symbol into the real value that is assigned, like a function:
(resolve 'clojure.string/split)
==> #'clojure.string/split
This means that the symbol ‘clojure.string/split is resolved (evaluated) to a function #’clojure.string/split . Putting together symbol and resolve functions I can build a string with the original command that finally resolves to the function and invoke that function, for example:
(resolve (symbol
(str "apic.request.deo/" fname)))

Where fname is built removing the variable (see below code) parts of every command. With the symbol, the execution is just an invocation following the rules of Lisp: (symbol-fn args) 

The code(published as Gist) to create a string from the command, avoiding numbers and other stuff is :


Success!!. I avoided to maintain a list of dispatching functions, for every new command, the previous code told me if the symbol could not been resolved, is like Test Driven Development, for every pending code, an exception occurs and warned us that its was a pending function to implement. Thanks Clojure!

Comments

Popular posts from this blog