-
Would like to see this offered by dropbox itself, but could make an awesome service even more awesome
-
On by default in firefox, opt-in via CSS for Safari nightlies & Chrome.
-
A great example of how not to log errors
-
Steps for unlocking 3's mifi device for use with other sims
-
I agree with @jazzatola – Best. Trailer. Ever.
-
Handy looking tool for digging out creative commons images from Flickr, and importantly generating attribution.
-
The ideas behind Jon Hick's excellent fluid-width website
-
Rolf and Andy talking about the importance of fast, bullet-proof releases at one of our quarterly technical briefings
-
Incredibly impressive stuff from Jon Hicks – a fluid width website which scales from one to four columns depending on the available width of the browser. Want one!
-
I wonder if this works for Mosquito's too?
-
Nice syntax for defining tests. Still, I'd settle for support for plain-old clojure.test in Intellij!
-
Perl script to count lines of code
-
Freeware opensource Source lines of code counter. Not easily redistributable like the Perl cloc though
-
Awesome. Absolutely awesome
Updated to reflect some feedback and one example of using commons-exec as an alternative to the plain old Runtime.exec
Second Update to reflect use of shell-out
– thanks Scott!
Basic
Making use of clojure.contrib.duck-streams
:
(ns utils (:use clojure.contrib.duck-streams)) (defn execute [command] (let [process (.exec (Runtime/getRuntime) command)] (if (= 0 (.waitFor process)) (read-lines (.getInputStream process)) (read-lines (.getErrorStream process))))) ... user=> (execute "ls") ("MyProject.iml" "lib" "out" "src" "test")
It could be improved obviously – for example catching some of the potential IOExceptions
that can result to rethrow additional information, such as the command being executed, or the ability to take a seq
of program arguments.
Error & Argument Handling
This version adds some basic (and ugly) exception handling, and also handles spacing out arguments passed in (so passing "ls" "-la"
gets processed into "ls -la"
):
(defn execute "Executes a command-line program, returning stdout if a zero return code, else the error out. Takes a list of strings which represent the command & arguments" [& args] (try (let [process (.exec (Runtime/getRuntime) (reduce str (interleave args (iterate str " "))))] (if (= 0 (.waitFor process)) (read-lines (.getInputStream process)) (read-lines (.getErrorStream process)))) (catch IOException ioe (throw (new RuntimeException (str "Cannot run" args) ioe)))))
Using commons-exec
I had some problems with hanging processes, so knocked up a version using Apache’s commons-exec
. This version has the added advantage of killing long-running processes, and I folded in Steve’s suggestion for a better way of splicing in the spaces in the command line args (see his comment). commons-exec
is part of the special sauce inside Ant, so is a rock solid way of launching command-line processes (well, as rock solid as Java gets).
The use of the ByteArrayOutputStream
is probably inefficient, and again, decent error handling is left as an exercise to the reader.
(defn alternative-execute "Executes a command-line program, returning stdout if a zero return code, else the error out. Takes a list of strings which represent the command & arguments" [& args] (let [output-stream (new ByteArrayOutputStream) error-stream (new ByteArrayOutputStream) stream-handler (new PumpStreamHandler output-stream error-stream) executor (doto (new DefaultExecutor) (.setExitValue 0) (.setStreamHandler stream-handler) (.setWatchdog (new ExecuteWatchdog 20000)))] (if (= 0 (.execute executor (CommandLine/parse (apply str (interpose " " args))))) (.toString output-stream) (.toString error-stream))))
Using clojure.contrib.shell-out
Many thanks to Scott for this. clojure.contrib
supplies the very neat shell-out
:
user=> (use 'clojure.contrib.shell-out) nil user=> (sh "ls" "-la")
I haven’t probed further to see if this deals with my hanging process problem, but it certainly doesn’t seem to have any support for killing timeout processes. If you’re worried about runaway tasks, the commons-exec
version above might be the right choice for you.
I’ve been playing around with partially applied functions in Clojure, and have hit an interesting snag when dealing with Java interop. First, lets examine what partial
does in Clojure, by cribbing off an example from Stuart Halloway’s Programming Clojure:
user=> (defn add [one two] (+ one two)) #'user/add user=> (add 1 2) 3 user=> (def increment-by-two (partial add 2)) #'user/increment-by-two user=> (increment-by-two 5) 7
What partial
is doing is partially applying the function – in our case we have applied one of the two arguments our add
implementation requires, and got back another function we can call later to pass in the second argument. This example is obviously rather trivial, but partially applied functions can be very handy in a number of situations.
Anyway, this wasn’t supposed to be a discussion of partial
in general, but one problem I’ve hit with it when trying to partially apply a call to a Java static method. So, let’s implement our trivial add
method in plain old Java:
public class Functions { public static int add(int first, int second) { return first + second; } }
Then try using partial
as before:
user=> (import com.xxx.yyy.Functions) com.xxx.yyy.Functions user=> (Functions/add 1 2) 3 user=> (def increment-by-two (partial Functions/add 1)) java.lang.Exception: Unable to find static field: add in class com.xxx.yyy.Functions (NO_SOURCE_FILE:3) user=>
So it seems like the partial call can’t handle static calls in this situation. But what if I wrap the call in another function?
user=> (defn java-add [arg1 arg2] (Functions/add arg1 arg2)) #'user/java-add user=> (def increment-by-two (partial java-add 2)) #'user/increment-by-two user=> (increment-by-two 10) 12
Which works. There is probably a reason why, but I can’t quite work it out right now.
Posted in the “I hope no-one else has to go through this” category in the hope that Google surfaces this for some other poor soul.
Picture a rather trivial split function:
(defn split [str delimiter] ((seq (.split str delimiter))))
Which helpfully spits out:
java.lang.ClassCastException: clojure.lang.ArraySeq cannot be cast to clojure.lang.IFn
The issue here is the additional set of parentheses – a hang-over from a previous edit. Removing this fixed the trouble. These parentheses were causing Clojure to expect a function call…