Content from 2009-05
NOTE: I've been terrible at keeping up with other people's blogs. If you're a friend of mine and I haven't read/commented in a while, I'm sincerely sorry. I'll be trying to catch up soon. Also, if you haven't heard about the underground sensation tearing up comedy clubs everywhere, his name is Justin Morgan and I'd keep your eyes peeled for him.
I've been hearing about a few albums that might be good and that I should check out as a consequence. They follow:
Doves - Kingdom of Rust
White Rabbits - It's Frightening
Night Control - Death Control
Danger Mouse and SparkleHorse - Dark Night of the Soul
It's occurred to me recently that I really kind of need a phone and I'm ready to take the fancy smartphone leap. I did a quick survey of the competition yesterday and narrowed my choices down to 4 models, none of which are released yet and one of which isn't even official. Don't ask me about all that. I'm sure we'll discuss this later. Here they are: Palm Pre, Samsung I7500, Nokia N97, and the Nokia N900 (because Rover is a very stupid name for a phone). Hopefully some official word about the N900 will break soon.
Okay, so there's an awesome site about Literate Programs here. If you're looking for some code to read it's probably not a bad place to start.
There was recently a great discussion on proggit about most used emacs commands. That's some handy stuff to keep track of. Between that and the emacs-fu blog I referenced two posts back I'll be learning a good while.
Considering that it's old news, there's still a fair amount of hollering about MIT switching from Scheme and SICP to Python and continuing debate on the value of SICP. Indeed, it's not the holy bible and grauenwolf is getting a too many downvotes. He makes a number of very good points. I haven't taken time to read through the whole thread (should I?) but psnively seems to have the right idea to me, as usual.
O'Reilly Radar put up a pretty good article on the things HTML5 will enable and the resulting scramble to the finish by a lot of big players.
There was a good discussion on the Haskell reddit about making -Wall the default for GHC, I chimed in because there didn't seem to be enough discussion to suit my tastes and though I'm an idiot I'd at least learn something. Learn I did and I'm wondering if this bug is one of those referenced in response to my comment.
Other random Haskell stuff: Recommendations to learn monads after functors, monoids, etc from Conal Elliott, a curious DSL from Sir Kiselyov, a neat package of adaptive datatypes from Dons, an interesting article on benchmarking EC2 with GHC compile times (which would be more relevant if I was trying to put off buying a computer or looking into working remotely) and some Haskell responding to Factor that I wish I could read.
Three last things: I found this cool programming problems blog that offers small, fun puzzles like Project Euler. It's called Programming Praxis. There's a really neat paper that's over my head called Types are Calling Conventions which makes a little sense but I wish it made more. And lastly, some thinking on the productivity boost of Object Oriented Languages that harkened back to some things Wren Thorton wrote and so on. Later!
timecommand to time it. The output of
time ./funnyWords.core english-words.txtwas as follows:
That's significantly shorter than the corresponding Haskell time and I wonder why. This code is a lot more imperative but I'm curious exactly where the speedups are. By the way, LOOP is awesome. As for the differences, I'll spend time sorting it out when I have time later. NOTE: solrize posted an improvement to my Haskell code that made it run in umm...half a second? Less? The main speedup seemed to be coming from using Data.Map and using the sort of each word as the key during insertion. That way, you get isAnagram for free, among other things. If you have thoughts on this code or the earlier Haskell code, where the differences lie or how to make them lispier or haskellier please let me know! :) Here's the code:
;; how to find words like cosmicomics:
;; words which can be split into anagrams by the middle letter
;; PRESENTLY ASSUME THAT ALL WORDS ARE LOWERCASE! how can we type/test for this?
(defparameter *dict* nil)
(defparameter *results* nil)
(defparameter *file* nil)
(defun main ()
(let ((*file* (or (second *posix-argv*)
(defun funny-words (wordlist)
(let ((result nil))
(with-open-file (in wordlist)
(loop for word = (read-line in nil) while word do
(push word result)))
(setf *dict* result))
(mapcar #'partial-find *dict*))
;; (concat-map #'partial-find *dict*))
(defun is-anagram (word1 word2)
(string= (sort (copy-seq word1) #'char-lessp)
(sort (copy-seq word2) #'char-lessp)))
(defun has-joiner (word1 word2)
(let ((strlen (- (length word1) 1)))
(char= (elt word1 strlen) (elt word2 0))))
(defun is-funny-word (word1 word2)
(and (has-joiner word1 word2)
(is-anagram word1 word2)
(not (string= word1 word2))))
(defun build-word (word1 word2)
(concatenate 'string word1 (subseq word2 1)))
(defun same-length (word lst)
(loop for item in lst
when (= (length word) (length item))
(defun partial-find (word)
(loop for item in (same-length word *dict*)
when (is-funny-word item word)
do (let ((answer (build-word item word)))
(push answer *results*)
;;(defun concat-map (f lst)
;; (loop for item in lst appending (funcall f item)))
Quick (but serious) pop quiz, Compare and contrast these two quotes. They may be my two favorites. Tell me what they make you think in terms of their different approach to the benefits and drawbacks of the advance of human knowledge. I think the dichotomy between them pretty neatly encapsulates my scattered thoughts and feelings about human progress.
Civilization advances by extending the number of important operations which we can perform without thinking about them. - Alfred North Whitehead
We are living now, not in the delicious intoxication induced by the early successes of science, but in a rather grisly morning-after, when it has become apparent that what triumphant science has done hitherto is to improve the means for achieving unimproved or actually deteriorated ends. - Aldous Huxley
I'm mostly enjoying my summer courses, particularly Data Structures. It's given me an excuse to relearn pointers and learn how to actually use gcc/g++ and makefiles. I'm still a long way from being any good or knowing what the hell I'm doing though. C'est la vie. The Sixteenth Edition of the Haskell Communities and Activities report is out, in PDF and HTML. I was mostly excited to see a progress report on the Glasgow Haskell Compiler which is some top notch technology if ever there was any. Just look at the stuff they're working on! I've been poking around the Computer Language Benchmarks game recently, too. Gotta love SBCL and GHC.
There are a few pieces of software I'm anticipating a release of. Here they are with links to the blockers for each: Firefox 3.5 because I live in it, Chromium's (Google Chrome) Linux Beta and Songbird which I don't really use but track with some interest. I'm also looking forward to a new Pitivi release (which should happen today, actually) and GHC 6.12 but that's months out still. Emacs 23 should also be fun because emacs releases are so punctuated but it's a pain to find a release schedule anywhere or even a list of blockers! GEEZ! Outside of software, I'm really looking forward to Peter Seibel's book Coders at Work which appears to be reaching it's endgame.
Speaking of Emacs I've been spending a bit more time in that incredible editor trying to become more proficient and found the Emacs-Fu blog to help immensely. There was also a guide to using the extension that ships with Mercurial that I found pretty helpful in getting off the ground quickly. I'll wrap this up by posting three songs I enjoyed listening to this morning.
|Max Richter - Horizon Variations|
|Found at skreemr.com|
|Andrew Bird - Anonanimal|
|Found at skreemr.com|
|School Of Seven Bells - Iamundernodisguise|
|Found at skreemr.com|
Thursday, May 21, 6 - 8pm:
Visitation at HM Patterson's (Spring Hill facility) Atlanta GA
Friday, Mary 22, 10am:
Funeral Service at All Saint's Episcopal Church, Atlanta, GA
Friday, May 22, immediately following the service:
Graveside service at Arlington Cemetery (Sandy Springs)
Friday, May 22, immediately following Graveside service:
My aunt and uncle, Sandy and Spencer Wiedemann, have graciously offered to open their home to those who would like to gather.
Their address is 340 Cameron Ridge Dr, Atlanta, GA 30328.
I had just gotten on a train to Arts Center to get on a bus to school.
I know I'll have more to say about him later, I'm not sure I'll find much to say about his passing. It's pretty hard to analyze or make sense of. There are really only two places to approach it from, an objective and detached place that can't signify the importance of the event as it's just the course of life or an emotional, irrational place which can't grant it importance enough.
I've made a Live CD image with an installer and uploaded the ISO to my Amazon S3 account. You can grab the ISO here. The old install guide still applies.
The biggest news from last week pertains to Dad. Mom and Dad got news from the doctors that the cancer was no longer responding to treatments and was getting worse. He can't walk without assistance and has been moved into the dining room. He's now under hospice care. It's hard to say how much time we'll have with him but the odds are good that he won't make it to Autumn. I just hope he gets one more Father's Day. I'm actually off to go fix Mom some Couscous and Parmesan Crusted Chicken for dinner but in the next 24 hours I hope to get a blog post up with a tour of the apartment posted.
After that, I'm hoping to spend the week playing with Haskell, Lisp and maybe some Discrete Math or Calculus before summer classes start on the 18th. I'd also like to throw a pool party somewhere in there. As for how I'm doing with Dad, I've had a lot of time to prepare and I'm just thankful for the 15 or so years we had. That said, I expect the hammer just hasn't dropped yet. We'll see.
Last but certainly not least, Dad has moved into the dining room and is now getting around via a wheelchair. I don't get the impression that the cancer is beginning to win and he can walk a little but odds are good he'll never be back to full mobility. Pray for him if you can and if you're interested in tracking his progress Mom is keeping a journal here.
Just because I need it, here's some Sigur Ros:
|Sigur Ros - Svefn-G-Englar|
|Found at skreemr.com|
1) This has no business showing up on reddit. It's a journal entry from a dumb kid who played for a few hours. I'm acutely aware of it. Also, there would be no post (no code) at all if cgibbard (Cale) in #haskell hadn't been so damn helpful. Thanks also goes out to olsner, ski, yitz and Twey.
2) This post is completely programming related for readers of my blog who aren't interested in that.
I've been increasingly enamored with Haskell recently. Back in March I picked up Real World Haskell and read through 3 chapters stopping short of finishing the last 3 exercises in Chapter 3 one day over spring break. School and real life caught up with me unfortunately and I've just now had time to sit down with Haskell again. I've been following the language pretty heavily since February and read a number of Dons blogs on things like writing simple unix tools. That's proof enough of disclaimer #1.
Looking back over some of the RWH stuff, I stumbled upon mention of a book by Italo Calvino called Cosmicomics. Cosmicomics is just a cool word. I decided to see how many words like it I could generate. That is, how many words could I generate that are anagrams smushed together by a shared letter. Naturally, I decided it'd be fun to try to do it in Haskell.
The resulting code is 39 lines, 35 removing comments. It is quite readable as far as I'm concerned and as I mentioned, I'm an idiot. The code compiles to a nice, native linux binary that takes up 684k on my machine (ArchLinux x86_64, GHC 6.10.2, etc). It reads in a 6750 word dictionary file with a word on each line and certainly does more computation than is necessary to get the desired result: a printed list of words like cosmicomics. It executes in just over 17 seconds. Fast enough for me. Here's the code:
-- how to find words like "cosmicomics":
-- words which can be split into anagrams by the middle letter
-- PRESENTLY ASSUME THAT ALL WORDS ARE LOWERCASE! I should probably unit test or type for this.
import Data.List (sort)
import System.Environment (getArgs)
main = do
[f] <- getArgs
inFile <- readFile f
let dict = filter (not . null) (lines inFile)
printFunnies (filter notSameWord (findFunnies dict))
isAnagram :: String -> String -> Bool
isAnagram word1 word2 = sort word1 == sort word2
hasJoiner :: String -> String -> Bool
hasJoiner word1 word2 = last word1 == head word2
isFunnyWord :: String -> String -> Bool
isFunnyWord word1 word2
| isAnagram word1 word2 && hasJoiner word1 word2 = True
| otherwise = False
notSameWord :: (String, String) -> Bool
notSameWord (word1, word2) = word1 /= word2
sameLength :: String -> [String] -> [String]
sameLength word xs = filter (\x -> length x == length word) xs
printFunnies :: [(String, String)] -> IO [()]
printFunnies xs = mapM (\(x,y) -> putStrLn (x ++ tail y)) xs
partialFind :: [String] -> String -> [(String, String)]
partialFind dict word = [(word,w) | w <- sameLength word dict, isFunnyWord word w]
findFunnies :: [String] -> [(String, String)]
findFunnies xs = concatMap (partialFind xs) xs
Note from the future: Accidentally navigated away from this page, Wordpress lost the last 600 words\40 minutes of work. Future posts will be written in Emacs.
I found the tricky parts of the problem to be findFunnies, partialFind and printFunnies. findFunnies I was actually on the right track about, I was just using map instead of concatMap. I'd bumped into concatMap earlier while looking at a different problem but it slipped my mind until Cale said, "Hey, you actually want concatMap here". Remember when I said I was dumb? partialFind may have been the trickiest and there are two reasons for that. One, I'd completely forgotten about list comprehensions. Clever, right? Even if I'd remembered them I had no idea you could test predicates while you built the list. Again, thanks Cale. Then it was working but I wanted to format the results differently and introduced two non-exhaustive pattern matches trying to do it so it was back to hastle #haskell. I was soon talking with Cale again. Finally, I realized you had to get the type system to accept the IO being done in printFunnies but I was using map as I didn't know something like mapM existed. Even had I known, I doubt I would've been able to throw together the lamba function it's being passed. Cale gave me a working version with forM and I found my way from there.
I came to Haskell from SBCL (Common Lisp) which I had come to from Scheme (PLT/MIT/Chicken, take your pick). I feel like a lot of my thoughts on Haskell are deeply colored by that trajectory so take the following with a few nice big grains of salt. Now then, for three random thoughts on Haskell from one of those fools who plays way too much with languages instead of getting better by actually getting things done.
It's really nice that Haskell actually has a dominant implementation, GHC, as well as a good package manager, Cabal. Consequently, all the libraries I've encountered on Hackage are easily installable and compatible with GHC. Conversely, I can't say if any require GHC extensions or are compatible with HUGS. That said, everything seems pretty up to date and I haven't even had to think about installing something from version control. Having easily installable bindings to a major cross platform toolkit like GTK or QT and Curses is pretty essential in my opinion. Don't even get me started on the awesomeness that is Hoogle and Hayoo.
Haskell is the first language that's made me see types can actually be useful. To be fair, before this I'd only programmed in Lisp, Scheme, Python and C. A trivial amount of each, at that, so you can see why I wasn't thrilled by static typing. To be fair, I did get a good number of compiler errors over typing problems in my code but they were always helpful. I'm not decidedly on either side of the fence with regards to typing and my gut says that both lend themselves better to certain problems (see the ease of multiple arity functions in Lisp and Scheme, for example) but at least now I can see the issue from both sides.
Haskell is also the first language with non-lispy syntax that I actually like. Dons posted an article called On Syntax a while back proclaiming the superiority of Haskell's syntax but did a bit of a disservice by using a trivial example. Haskell's syntax gets a fair bit more complicated doing anything non-trivial though the code remains concise by consequence. That said, it's far from unreadable and I hope that it'll become more natural as I spend more time writing code. While I found Python's syntax pretty tolerable, Haskell's use of Pattern Matching and Guards really puts it over the top. Lisp has been said to have no-syntax which certainly makes it easier (read: feasible) to use macros, not that it's merely a matter of syntax. I don't even want to think about Template Haskell. I remember reading something along the lines of "Lisp's no-syntax as syntax is certainly flexible but it doesn't lend itself to expressing anything in a very elegant way so much as expressing nothing in a very inelegant way". At least now I can vaguely understand why people could think Perl's syntax was a good idea.
Ironically, an article got posted on the Haskell subreddit earlier regarding Haskell's syntax and difficulty reading it. I thought Nostrademons comment was pretty thoughtful and it largely sums up my issues, particularly points 2 and 3. Maybe if I'm lucky I'll encounter point 1 as I code more in the coming months. Most importantly, none of these issues (syntax, typing or anything else) are dealbreakers. If you want to learn Lisp or Haskell you absolutely can and the main reason for that is the exceedingly helpful communities that surround them. When you can jump into a chatroom, mention a problem you're having and instantly get advice from some much smarter and more experienced folks there's no reason not to dive in and play around. More and more, I'm convinced that languages make it or break it based in large part on their communities and I promise Haskell and Lisp both have damn good ones.
If you're interested in learning Haskell, these are some of the best resources I've found on the web so far (excluding #haskell, of course):
Real World Haskell - A book available in paperback and readable free online.
Learn You a Haskell - A freely readable online book.
Haskell Wikibook - Community edited online Haskell book.
The GHC Standard Library
and User Manual
Any packages docs on Hackage. Just click any of the links under "Modules".
The Haskell Wiki is phenomenal and has stacks of articles on everything from style and idioms to tutorials.
Search Engines: Search the libraries for a function by either name or type!
Finally, here's the output of
time funnyWords english-words.txtbehind a cut:
This blog covers 2015, Books, Butler, C, Dad, Discrete Math, Displays, Education, Erlang, Essay, Gaming, Gapingvoid, HTDP, Hardware, IP Law, LISP, Lecture, Lessig, Linkpost, Linux, Lists, MPAA, Milosz, Music, Neruda, Open Source, Operating Systems, Personal, Pics, Poetry, Programming, Programming Languages, Project Euler, Quotes, Reddit, SICP, Self-Learning, Uncategorized, Webcomic, XKCD, Xmas, \"Real World\", adulthood, apple, careers, coleslaw, consumption, creation, fqa, games, goals, heroes, injustice, linux, lisp, math, melee, metapost, milosz, personal, poetry, programming, ragequit, recreation, rip, strangeloop, work
View content from 2015-05, 2015-03, 2015-02, 2015-01, 2014-11, 2014-09, 2014-07, 2014-05, 2014-01, 2013-10, 2013-09, 2013-07, 2013-06, 2013-05, 2013-04, 2013-03, 2013-01, 2012-12, 2012-10, 2012-09, 2012-08, 2012-06, 2012-05, 2012-04, 2012-03, 2012-01, 2011-10, 2011-09, 2011-08, 2011-07, 2011-06, 2011-05, 2011-04, 2011-02, 2011-01, 2010-11, 2010-10, 2010-09, 2010-08, 2010-07, 2010-05, 2010-04, 2010-03, 2010-02, 2010-01, 2009-12, 2009-11, 2009-10, 2009-09, 2009-08, 2009-07, 2009-06, 2009-05, 2009-04, 2009-03, 2009-02, 2009-01, 2008-12, 2008-11, 2008-10, 2008-09, 2008-08, 2008-07, 2008-06, 2008-05, 2008-04, 2008-03, 2008-02, 2008-01, 2007-12, 2007-11, 2007-10, 2007-09, 2007-08, 2007-07, 2007-06, 2007-05