Sunday, December 26, 2010

Need to learn more swing now

So, I finally got my little clojure launcher cleaned up and able to look for insertUpdates or removeUpdates.  Unfortunately, I now need to implement  property change listener, because when you select the browse button and choose your directory or file, although the associated JTextField gets populated with the correct string, this new string is not reflected in the command row's JTextField.  Calling setText on a JTextField apparently does not trigger an event that insertUpdate listens for.

But anyhow, here is the latest screenshot:










As you type into any of the top three fields, the command row gets updated.  I still need to put in the actual beginning of the command....eg "java -cp ... -jar somejar.jar"

Once that's done, I need to execute a new process, and tie in its stdin and stdout to  JTextArea component.  I also need to make it so that you can save these fields and store them away for future use.  I am thinking of saving them as records in a database, this way you can retrieve commonly used values.  I will also have the means to write them to a file.

The code was also significantly cleaned up.  I didn't like how I was using a top-level def for the JPanel and JFrame, and I also started going down the path of a global ref called rows which was a map containing the rows in the panel.  This just got uglier and uglier, so I decided to make all these things local symbols in the -main function instead.

I solved the mutability problem with a map I wanted to update by creating the following function:


(defn into-map
  "This takes a list or vector of keys and a list or vector of values and
   makes a map out of it"
  [ init key-coll val-coll ]
  (into init (map #(assoc init %1 %2) key-coll val-coll)))

So for example, you could call it like this:

(def rows (into-map {} [:row1 :row2 :row3] [(JLabel. "First") (JLabel. "Second") (JLabel. "Third")]))
=> {:row 1 #<JLabel ...> , :row2 #<JLabel ...> , :row3 #<JLabel ... > }

It's sort of similar to hash-map, but instead of k v, k1 v1, ... pairs as arguments, all the keys are in one collection, and all corresponding values are in another vector.


So I'm slowly getting the hang of this.  I find functional programming much more intellectually stimulating than imperative style programming.  One of the reasons my code is often buggy is from one of three following reasons:

1.  Off by one error in some for loop
2.  Failed to consider some code path in a function with multiple returns or exception possibilities
3.  Bogus while loop conditional checking (usually with some sentinel value)

But so far in my clojure code, I rarely have to deal with this if at all. It's far more interesting to think recursively or how the output of one function can be used as the input of another.

No comments:

Post a Comment