I've been meaning to "release" a clojure program into the wild. Partly,
I want to take advantage of how nice it is to be able to deploy via jar
file, and partly because I've been wanting this application.
So, without further ado, here's my hexclock (as an executable jar file).
Source is included and is covered by the GPL
http://www.gnu.org/copyleft/gpl.html
Just FYI
sha1sum: ac0b67fa8252bf06f00d627dfc3f2975b1c45a30 hexclock.jar
Here's some explanation if you're confused. The basic idea is to divide
a day into half, so now we can say if it is AM or PM; easy but, I would
say, a little too coarse of a measurement. With the AM/PM clock, you'd
only need one bit ("is it morning?"). Continuing, next we can divide our day
into 4 equal parts, now we could (using two bits) say whether it was the
first part of the morning "early morning" or the second part of the
morning "late morning." Likewise we could talk about whether it were
late or early PM. These chunks would be 6 hours long. You can see that
we can keep dividing our day like this as much as we want, with each
division we need one more bit to talk about the time and we get twice as
many (and twice as short) chunks. In fact, if you wanted to keep going
until you got something like a second, it just so happens that you'd be
using 16 bits (though, it is a pretty close call (about 32% error versus
34%)). Which just happens to work really nicely for binary arithmetic as
we'll see.
Make sense doesn't it? While I have you agreeing with me (if you are),
stop and think about this for a bit, the steps to divide up time into
hours, minutes, and seconds are not at all constant. You must divide a
day into 24 hours, then an hour into 60 minutes and then again a minute
into 60 seconds. Quick, how many seconds in a day? The answer isn't
anything in particular, 86,400 (24*60*60). A fun number for us physics
nerds to memorize as an undergrad, but just that, an arbitrary constant.
The way that the clock works is just to represent the day as a 16 bit
number (0 through 65535), if you are accustomed to hexadecimal, this is
0x0000 through 0xFFFF. Hex has the nice property that each digit is four
bits (sometimes called a nybble, half a byte, get it? Well, I like it).
Numbers go 0-9 like usual but then we use A, B, C, D, E, and F for 10
through 15. I somewhat arbitrarily (and somewhat not) divide this number
into two parts the "high" byte (two hex digits) and the "low" byte (the
last two hex digits). I separate the time with a vertical bar like this:
"AB|CD", if you are a programmer this is meant to evoke logical OR. You
can imagine that the time is 0xAB00 | 0x00CD and they get smushed
together with the or operator.
When I implemented this in Python:
http://twopoint718.blogspot.com/2008/08/hex-clock.html I talked a bit
about the scale of the digits on the clock. The last digit changes every
1.318 seconds, the next most stable digit changes just about every 21
seconds. The next (the "B" in my example above) switches once every 337
seconds or about 5 and a half minutes. The most stable digit changes
only 16 times a day, since both 24 and 16 are divisible by 4 this makes
that digit equal to 90 minutes (1.5 hour). My proposal is to talk about
the first, most stable digit as hex hours, the second as hex minutes,
and the last two digits are hex seconds. My coined terms for these are
"hexours" (HEX-zours), "hexinutes" (HEX-inuts), and "hexeconds"
(HEX-econds). There are 256 hexeconds in a hexinute and 16 hexinutes an
an hexour. Alternatively, you could just say there it is AB "in the big
byte" and CD "in the little byte". I imagine people would just call out
the time "it is ABCD." To avoid confusion, I think all digits should
always be pronounced "zero, zero, zero, one," though maybe we could all
use the English "z" sound of "zed-zed-zed-one" because it cuts down on
the syllables. But when in doubt, if fewer than four digits are
announced, we should assume that they are talking about the most
siginificant digits first (much in the way that we say "it is 3
o'clock").
You can read the post that inspired this idea here:
http://halcanary.org/vv/2007/10/31/706/
You can read more about hex time here:
http://www.intuitor.com/hex/hexclock.html (this clock is really similar
to mine, we just group the digits differently, either one is fine).
Wikipedia has an entry about it here:
http://en.wikipedia.org/wiki/Hexadecimal_time (maybe I should change my
digit grouping?)
Don't confuse this method of marking time with other binary clocks.
Often they are using binary coded decimal:
http://en.wikipedia.org/wiki/Binary-coded_decimal
Until recently this clock was an example (they added a "true binary"
switch):
http://www.thinkgeek.com/homeoffice/lights/59e0/
Comments [0]
Wow! Paredit, where have you been all my life? http://mumble.net/~campbell/emacs/paredit.el
Comments [0]
Tips on commenting lisp code. I fall into Camp 2, well I try to anyway, my code usually isn't that clear and so I shade into Camp 3.
Comments [0]
This is a simple translation of some Java code into Clojure
(http://clojure.org/). I've tried to make the code idiomatic Clojure
(as far as I know it). I'm looking at the NIO libraries and the
SocketChannel in particular for doing some more intelligent two-way
network code.
; translation of the java code at: ; http://java.sun.com/j2se/1.4.2/docs/guide/nio/example/TimeServer.java ; (original copyright can be found there) (ns com.sencjw.time-server (:import (java.net Socket ServerSocket InetSocketAddress InetAddress) (java.nio ByteBuffer CharBuffer) (java.nio.channels ServerSocketChannel) (java.nio.charset Charset CharsetEncoder) (java.util Date))) (set! *warn-on-reflection* true) (defn serv "Starts a time server on a high (8013 default) port" ([] (serv 8013)) ([port] (let [charset (.. Charset (forName "US-ASCII")) encoder (.newEncoder charset) buff (.. ByteBuffer (allocateDirect 1024)) ssc (ServerSocketChannel/open) ; create ServSockChan addr (InetSocketAddress. port) _ (.bind (.socket ssc) addr) sc (.accept ssc) ; accept the connection now (str (Date.))] (try (.write sc (.encode encoder (CharBuffer/wrap (str now "\r\n")))) (println (str (.. sc (socket) (getInetAddress)) ": " now)) (.close sc) (finally (.close sc)))))) (serv)
Comments [1]
I'm really just starting to grasp what you can do with laziness (I would say I'm "on my way" but there was a hiccup the other day where I wanted to produce a lazy sequence of files for processing (so that I could map over them, or maybe use 'seque') as the files appeared in the directory; if you know how to do this, please share!). But so far the experience has been really good. I've started to notice situations where it would be genuinely useful, but there's also just the cool factor (and that goes pretty far for me):
(def integers (iterate inc 1)) (take 5 integers); gives: (1 2 3 4 5)
Fun.
*edit: I forgot to mention, this example is from the excellent Programming Clojure
Comments [0]
Comments [0]