Various Thoughts and WebMote, the Next Part
Sun Nov 25, 2012It has become obvious to me that I'm getting old.
My wife and mother-in-law went out for lunch while I was at work. They dined|1| at KFC, and brought the leftovers of their feast home, ostensibly to serve as dinner for me. Three pieces later, my body is loudly and clearly telling me to fuck off. So having torn myself away from the porcelain god, I'm going to write something in an effort to expunge the taste of grease and fail.
Fatherhood
Children are a lot of effort. I'm still constantly being told that it gets easier, and that the second and third ones are cakewalks, but I'm not seeing it yet. All I can definitively say so far is that if you're planning on generating larva with your significant other, expect to sleep significantly less than you're used to.
Two more things actually. First, if at all possible, have a female of your family unit breast-feed. Milk-fed babies' initial output doesn't smell like, well, shit, for about a month. Second, babies have a ridiculously poor API. They just open a stream and send "Waaaaah" at various volumes and modulations. That might mean "feed me", "change me", "burp me", "pay attention to me" or "fuck off"; and they don't close the stream until you do the right ones?
and/or get very lucky. So ... be prepared to iterate through that pattern.
A lot.
Finally, a word advice for the programmer daddies specifically, hands down the best investment you can make is a sling carrier of some kind. It'll let you cradle your baby while keeping both hands free. I'd have basically no hope of finishing this article without one.
Haskell
I've finally gotten past Absolute N00b stage with Haskell. Like I said last time, it only took three years. There's a few patterns I'm detecting in the libraries and community that I thought I'd point out.
The strong typing stereotype turns out to be right on the money. There are precious few libraries on hackage that have any kind of usage example in addition to type signatures, and fewer still that have actual documentation. I guess I'll have to get good at reading type signatures, but guys, these are for the fucking compiler. Some human readable media beyond basic explanations would be nice. The upshot is that, if you're hopping around ghci
, you can use :browse Library.Name.Here
, and the hoogle
docs are available for local use, so I guess it might kind-of-almost-sort-of even out once you get to the point where you're comfortable with language basics. The other upshot is that the community is very responsive. I wasn't expecting to have as easy a time getting stupid questions answered as I've actually had, whether that's been in-person, via IRC or on the appropriate SO tag.
Clojure
swank-clojure
seems to have been deprecated! I went to install my usual Clojure environment to do a bit of hacking for this article, and noticed that giant note in its git
repo. The good news is that there's apparently a thing called [nrepl](https://github.com/kingtim/nrepl.el)
that provides more or less the same functionality, except through the Clojure Networked REPL rather than through SWANK. nrepl.el
is available here, for those of us who still install Emacs packages manually. The model is a bit different; where SWANK
is a thing that gets started as part of SLIME
, and then loads projects, nREPL
is theoretically a thing that your project needs as a dependency, then gets started once you start editing that project.
I say "theoretically" because, just like swank-clojure
, nrepl
fails pretty spectacularly on my machine. I guess I'm sticking to inferior-lisp
for Clojure code.
On the language in general by the way, it feels surprisingly comfortable after a couple months playing around in Haskell-land. To a first approximation, it's Common Lisp with more emphasis on the stuff I like and less emphasis on the stuff I don't. Because of the ecosystem its embedded in, you frequently find yourself having to call Java code for one task or another, but doing so is easier than you'd think. The only part I really don't like about it is its weight. Every time I lein run
a project, or start up the repl
/run-lisp
, there's a visible few-second delay during which all my cores start spinning into the 98% range. That doesn't happen with any other language I use regularly, even while running what seem to be more compute-intensive operations.
Web Mote
On that note, a very small chunklet of my time has been going towards the tweaking of a Python project I started for my RasPi a little while ago.
Web-Mote is in a usable state at the moment|2|; I've got the Pi hooked up to a separate wireless router and running a subset|3| of my media library through the livingroom TV's HDMI port. I still haven't figured out how to control the TV itself from the device. Hopefully, I'll fix that soon soon|4|.
I ended up not following my thought process out to its ultimate conclusion. Ok, I did experiment a bit with a completely client-centric approach, but the downsides I mentioned turned out to be more severe than anticipated. Specifically, it ended up causing all sorts of headaches relating to what to do when my remote lost the signal, or when it ran out of battery power. Those kinds of problems seem to be inherent to keeping most program state on the client rather than the server, and being that they directly got in the way of my enjoying the use of the system, I will not be going down that path.
What I do have to do is put together a handler that deals with sending out a log in the form of an SSE response. That'll be critical for the future when I actually want clients to start interacting with one another|5|; they'll each need to know what the state of play is on the server, so a coordination handler is in order. A cursory googling tells me that web.py
is built more or less like hunchentoot
in terms of the threading model, so I may actually need to move to a different server if I intend to make this puppy support more than a handful of clients at a time. Which I may as well, just for the fun of it. The Python situation is a bit better than the CL one here, since there's actually a production-ready non-blocking web-server waiting to be used, where Lispers warned me away from the comparable CL application for fear of its prime-time readiness. The good news is that, thanks to this front-end separation experiment I'm running, porting the backend away from web.py
will involve changing exactly one file in a not-very-extensive way.
Footnotes
1 - |back| - Typically for my mother-in-law but atypically for my wife,
2 - |back| - Though oddly listed as 21.2% Perl, even though the only non-JS/HTML/CSS code I've got in there is Python.
3 - |back| - It would be the complete set, but I'm still waiting on a drive enclosure that will finally let me store more than 32GB of data there without using up a second wall outlet.
4 - |back| - Realistically, I don't need anything like complete control. I need to be able to tell it power on
/power off
, go to the channel [this] is connected through
and volume up
/volume down
.
5 - |back| - For instance, one use I've already dreamed up but haven't come close to implementing yet, is something I'm calling democracy mode. The idea is that the server tallies votes for the next thing to play, and plays the highest voted rather than next-in-queue when a media change occurs. When I think about how to implement something like that... Well, it seems like it would be both simple and in keeping with the general design principles of the semi-client approach. You keep a running total and a list of IPs that have already voted, and you give each client a handler by which to register a vote. Done. Now, thinking about how I would do it without central state being kept on the server. It seems like the best I could do is let the user register their current vote. Keep the clients synchronized with the server somehow, and send a message every once in a while that says VOTE NOW, BITCHES
, at which point each client would report its current vote and clear it. There'd need to be a momentary stateful operation, but it would literally be getting the len
of the collected [vote-ip]
. That seems like it would be a bit more complicated, if theoretically elegant, to actually implement.