Issues and Interesting things I have found while working on software development
Don't wanna be here? Send us removal request.
Text
Element Substitution with closures in Clojure
I got a list of numbers, let say: (1 0 0 2 4 7 0 0 0)
And I need to replaces all 0's with the elements from a second list, for example: ( 1 2 3 4 5 6)
It must work even if there are not enough elements in the second list to replace all the 0's on the first.
So in clojure I am doing:
(map (fnGenLstCleaner lstSecond) lstFirst)
where fnGenLstCleaner is:
(defn fnGenLstCleaner [ lstSecond] (let [ iSz (count lstSecond) atIndex (atom 0) ] (fn [iFldPos] (if (= iFldPos 0) (if (< @atIndex iSz) (let [ ans (nth lstSecond @atIndex) ] (swap! atIndex inc) ans ) 0 ) iFldPos ) ) ) )
Does anyone can imagine a better approach?
0 notes
Text
Proxy fun on Clojure
The original Issue:
So, I was working in a system able to display tabular data. I got one abstract class doing all the UI work by itself and letting its "children" (lets call them "Display classes" ) define the particularities for each case.
Some days ago, I have to decide between creating many more Display classes for small variation cases, or doing something more creative. Of course I opted for the later :)
The trick was that I only needed to change a single variable in the data generation process for the tabular table, so in fact, I could reuse the Display classes as they were except for the id() function because I needed the rest of the system to treat them like a different Display class.
The problem was that the id() function of the instances was an abstract function, so I would need to change the way it was working based on some arbitrary condition. I didn't like this idea because it means change around 20 individual classes and do something to remember to take this into account for every future Display class.
I know there are many ways to solve this problem in java but the idea I liked most was to use Clojure proxies. Just change the id() function dynamically and work done!
Enter Clojure:
My first try was to use the proxy macro. I tried something like:
(defn fnGenProxyFn [StrClassName]
(fn [StrId]
(proxy [StrClassName] []
(id [] StrId)
) ) )
Which of course, is perfectly wrong. There is no way the proxy macro would accept other thing that the exact name of the class. So StrClassName must be java.util.Vector for example. You can not use a variable, you can not do something like: (Class/forName StrClassName) or (symbol StrClassName) . If you do not know the name of the class you want to proxy at compiler time (as in my case), then proxy macro is not for you.
Enter get-proxy-class:
Looking at clojure documentation, I found the functions get-proxy-class, construct-proxy and update-proxy. These are Functions so I thought they would do the trick.
Testing on LightTable the line (get-proxy-class StrClassName) certainly worked but running the very same line on my system didn't. And it threw a very strange "ClassCastException" to DynamicClassLoader.
Now at this point, I have spent several extra hours on this problem, and the documentation on get-proxy-class wasn't exactly abundant, but the promise of dynamic class modification was so powerful that I keep looking for an answer.
I eventually found the source code for the get-proxy-class on github (The source belong to core_proxy.clj file. )
Looking at this code I understood that the bug has nothing to do with my class, but with the way get-proxy-class works.
I forgot about get-proxy-class in particular and looked for bugs related to clojure.lang.Compiler/LOADER instead. Thank God that proved to be the right way.
If you want get-proxy-class to work then be sure to have no issues with ClassLoaders!! Do something like:
(let [ dcl (clojure.lang.DynamicClassLoader. (.getClassLoader ClassSM)) ClProxy (with-bindings {clojure.lang.Compiler/LOADER dcl} (get-proxy-class ClassSM ) ) ]
...your code....
)
All Problems Solved???
Of course not. Morphy law always apply. You see, although construct-proxy did work without any further problem, update-proxy was sending a NullPointerException. And if get-proxy-class has little documentation, update-proxy has even less.
I return to clojure_proxy.clj and looked for update-proxy for more clues. And found none. But reading that code, by causality, I looked to the previous function: init-proxy, which just happens to have the very same parameters.
I replaced update-proxy with init-proxy in my code, and everything started to work as expected.
my code:
(let [ Proxy (construct-proxy ClProxy) MpFns { "id" (fn [this] StrId) } ] (init-proxy Proxy MpFns) )
Hopefully this may be useful for you :)
0 notes