Posted by Daniel Lyons
Mon, 12 May 2008 15:17:00 GMT
Over the weekend I wrote the same program in three (almost four) languages: Haskell, Common Lisp, Erlang and almost Prolog.
I have an informal result I want to share. The first one I wrote was in Haskell. Of the four, it was definitely the most fun to write. I did, however, avoid monadic computation when it probably would have been amenable, instead I opted to use interact and a small combinator of my own design. In a “real” program in a strict language I’m sure it would have been inefficient. I felt the freedom of Haskell, letting you design the solution in the most abstract, high-level way you can imagine it, and still make it quite small.
Next up was Common Lisp. I was surprised by several things. For one, it was shorter by a handful of lines than the Haskell version. I used essentially the same design as the Haskell and that seemed to work well enough, though Lisp lacks the combinators that Haskell comes with, so I wound up using a do loop for something I was just doing with map in Haskell. And of course I was annoyed by the effort it takes to produce an executable: (sb-ext:save-lisp-and-die "a.out" :toplevel 'main :purify t :executable t).
Then I started on Prolog. Of course, the logical part of the problem was short and sweet. Then I thought about what it would take to do line input/output, got the shivers, and decided to move over to Erlang. The syntax is fairly similar, though the execution strategy is shockingly different, but this application didn’t require any backtracking anyway.
Erlang wound up being shorter than Lisp or Haskell.
This fact stunned me, though I can explain it: Lisp requires a fair amount of schmuzz to do things that are free in Haskell and Erlang (namely, defun steals a line for itself) and Haskell requires a fair amount of schmuzz for human-assisted type checking. Erlang didn’t need either of those and has some of the strongest pattern matching around (though the limited guard support is obnoxious). Erlang did need Rubyesque and despicable list_to_integer and atom_to_list type conversions, but none of those cost me a line. You could omit the type declarations in Haskell, and I did add a line to make the type signatures more readable, but that’s really bad form.
I also found myself wondering how much I was buying myself by using Haskell’s data types for part of the computation. What’s the difference between reading a character or two to create a special instance of some data type and then using that everywhere, versus just using the character? In Haskell I’ll get a read error, whereas in Lisp and Erlang an ecase or a pattern match is going to fail later in the game, but not that much later. Does the anal retentiveness pay off in the end? I’m starting to wonder if, as Jonathan Edwards is proposing, formality is a cure that’s worse than the disease.
- Erlang was the shortest (least syntactic BS as far as writing functions are concerned).
- Erlang was the hardest to debug (the error messages are more machine-readable than human-readable).
- Haskell was the most fun to write (I guess I like function combinators and higher-order programming).
- Haskell took the longest to write (it was the first one I did).
- Lisp was the easiest to write and debug.
- Lisp was the hardest to get to a binary of those that could (I don’t think Erlang can ever give you back a binary directly).
- Lisp’s schmuzz was the most obnoxious to write (especially the hapless
destructuring-bind, which is substantially underpowered compared to Erlang’s or Haskell’s pattern matching facility).
I think I will try using Common Lisp’s bind library later this week to rewrite this and see if I like that better than destructuring-bind.
Tags erlang, haskell, lisp | 2 comments
Posted by Daniel Lyons
Wed, 06 Feb 2008 08:50:00 GMT
I have never used such a frustrating development environment as scsh.
As much as I desperately want to like it, and should like it, for all the right reasons,
- The interactive version is basically unusable. The REPL blows.
- The built-ins seem fragile, especially the very-cool
awk which I can’t seem to get to work.
- DrScheme has library functions which should be present in scsh, but aren’t (
fold-files comes to mind, probably because I’ve spent three hours trying to replicate the functionality in scsh and being unable to.)
- Scsh is built on Scheme-48, which seems to be not particularly widely used compared to PLT and Bigloo/Chicken, so it’s missing SRFIs. Plus, loading SRFIs seems to be wonky (
load doesn’t work, but the command line switch -l does, and it seems obnoxious that I’d have to use absolute paths for either.)
Scsh would be just perfect if someone had ever finished that port of it to PLT. As it stands right now, it sucks having two different Scheme environments on my machine: the really nice DrScheme one and then two different flavors of hell with Emacs, Hen mode for Chicken and run-scheme with scsh.
What to do, what to do.
Tags lisp, scheme, scsh | 2 comments
Posted by Daniel Lyons
Tue, 05 Feb 2008 04:35:00 GMT
“Lisp was not the product of a concerted design effort. Instead, it evolved informally in an experimental manner in response to users’ needs and to pragmatic implementation considerations. Lisp’s informal evolution has continued through the years, and the community of Lisp users has traditionally resisted attempts to promulgate any “official” definition of the language.”—Structure and Interpretation of Computer Programs, Abelson and Sussman, page 3.
The rocking sensation you probably did not feel a couple weeks ago was the release of Paul Graham’s Arc. Many people made many remarks about Arc being a massive letdown. I must admit I shared the sense of disappointment. After so many years of promises, and reading and respecting Paul Graham, and then, almost nothing, a tiny language atop a tiny Scheme. It hardly seems like anything to get worked up about.
The Lisp world is an interesting place these days. By and large, people have an opinion about Lisp based on experiences with Common Lisp and Scheme, which I think account for the vast majority of Lisp users. Yet, as Abelson and Sussman observe above, there never really was a Lisp consensus in the past, and today there are far more interesting variants of Lisp in the wild with few users. I think we expected Arc to represent a turning point in Lisp’s evolution towards a more Pythonic development model, the benevolent dictator, with a programming language aesthete in the driver’s seat. There are two important lessons here.
The first lesson is that we do not need Paul Graham to tell us what makes a compelling Lisp. We can mix-and-match our own stuff. Consider SRFI 26, Notation of Specializing Parameters without Currying:
(map (cut * 2 <>) '(1 2 3 4))
That’s almost as compact as this (hypothetical and untested) Arc code:
(map [* 2 _] '(1 2 3 4))
And of course it would be possible to create a reader macro for many Schemes which would achieve the same trick. But the SRFI-26 syntax also permits arbitrarily nested expressions with arbitrarily many variables—does Arc?
This SRFI has been around for six years and is supported by PLT (DrScheme), Kawa, Guile, Chicken, SISC and Gauche implementations, which is most of the ones you’d ever care to use.
Swindle has been around an equally astonishing amount of time, and is nothing but a bunch of Scheme sources that go atop any old Scheme (though bundled with DrScheme). And that gives you damn near 100% CLOS compatibility, based in part on Tiny-CLOS which is also very portable.
This is just what I’ve been looking at lately. There are a ton of compelling Lisps out there, far more fascinating than Arc; in addition to the ones I mentioned last time there’s also Nu, L# and Clojure.
My advice to you: do what Paul has done. Evolve your own Lisp. Pick Lisp or Scheme as your basis if you want to be able to share, or another language if you want to exploit some power it has. Try to keep your modifications portable or use a portable starting basis. Publish your changes.
The second lesson is, of course, to not be disappointed in Arc. We’re disappointed in Arc because we were expecting something “better” than Lisp, or something other than Lisp. Paul delivers a pile of macros. Well, that’s all you’re ever going to get with Lisp. It’s only a let down because we were expecting some kind of magic. But Paul doesn’t have a monopoly on this magic, we all have it. That’s part of the beauty of Lisp. Maybe it’s a disappointment that Paul really can’t do any better than we can, but remember it also means we can do as well as Paul.
Tags arc, lisp, scheme | 4 comments
Posted by Daniel Lyons
Thu, 31 Jan 2008 08:24:00 GMT
The world seems to be a little bit less optimistic today, because Arc has been out for 24 hours and has not yet changed the world.
In case you can’t tell, I like Lisp a lot. Seeing a Lisp machine work recently changed my opinion of Lisp a bit. I had been looking forward to Arc as a Lisp-2 with dirty macros and a lot of opinionatedness, basically as a tiny Scheme which celebrates all that’s gross about the other half of the Lisp family. But now that it’s here I’m not sure I see the point. It’s not that I don’t love Paul Graham, either. I just feel like something is awry.
There are, as it turns out, a number of minor Lisps out there which attempt to address some aspect of what makes Lisp annoying:
- Qi attempts to bring advances in functional programming back to Lisp.
- Lush tries to push Lisp into the multimedia/science sector.
- Scsh attempts to blend Unix and Scheme together.
- newLisp is a refresher and a shot at bringing Lisp to the web.
- Liskell is a Lisp syntax for Haskell with macros.
The problem, essentially, is that the Lisp machine was not a machine programmed in Lisp. It was a comprehensive environment which blurred the distinctions between language, operating system, hardware and editor. To use Emacs is to accept that the editor and the language/OS/hardware will be separate. To use Common Lisp on a modern OS is to accept that the language and the OS are separate. This goes against the nature of Lisp as fully realized on the Lisp machine. It feels inauthentic.
Of the five above, I have the most interest in the Scheme shell because I see it bringing back the tight integration between Lisp and the OS. Scsh not only brings a concise process spawning/piping and IO redirecting sublanguage to Scheme, it also bridges most of the POSIX APIs. It’s way more than just a shell, covering territory you’d traditionally need C for at the low level, the shell for process control, and a scripting language for logic. Instead you get all three for the price of one. I’m very intrigued.
This of course makes me wish I knew more Scheme. Which is an awkward position to be in as a Lisp partisan of so many years. This quote from Lambda the Ultimate helps:
An hygienic macro is one where the meanings of symbols that aren’t parameters to the macro are bound at the definition site rather than the expansion site.
Another user points out that you can accomplish variable capture with a hygienic macro as well as an unhygienic one, but there are problems you can run into with an unhygienic one that you can’t solve with gensym.
I wish I were less tired so I could be more coherent about all this, but it’s been a hell of a day, a hell of a week, and a hell of a month.
Tags lisp, scheme, scsh | 1 comment
Posted by Daniel Lyons
Thu, 29 Nov 2007 06:50:00 GMT
The way most people format CSS is something like this:
css.selector {
attribute-name: value;
attribute-name: value;
}
I read somewhere, probably via Reddit, that a better way to do it is like this for readability purposes:
css.selector { attribute: value; }
other-css.selector { attribute: value; }
Today Josh suggested something a bit more radical: alphabetize them by selector. You arrive at something like this:
a { foo: bar}
a:hover { foo-bar: baz; bazzle-bat: foo; }
b { font-blah: blah; }
I liked this a lot, but I took it a little further. I indented the braces to line up, like this:
a { foo: bar}
a:hover { foo-bar: baz; bazzle-bat: foo; }
b { font-blah: blah; }
(For a bigger example, check out the CSS on my tumblog.)
Now, I like this for two reasons. One is that this really does make finding what you’re looking for a lot easier. But another, in my book better reason, is the statement this makes about CSS.
You would never organize a program’s functions alphabetically. You would never indent them all so the code is a big jumble on the right somewhere. This layout turns CSS into a selector rolodex with insanity on the right. And you know something? That’s exactly what CSS is: insanity, complete unmitigated chaos. The best we can do is label the roads. That’s what this layout does. It gives you trails that lead off into the wilderness. And you know something? It’s better.
So this morning when I read Brendan Eich’s The non-world non-wide non-web, I was already in a bad mood because, what has the W3C ever done for us? We’ve got XHTML, which is basically a dead letter. We have CSS, which is absurd. We have the whole XML toolchain. It’s hilarious to hear people slam Lisp and turn around and defend XML’s virtues. (I bet if you printed out the W3C’s paperwork on XML, you’d arrive at more than 1500 pages.) To learn SVG, one I thought I had liked, is also a pile of lies is just the icing on the cake.
Actually, it reveals how the W3C works quite clearly. Look at the commentary on Brendan’s page. A bunch of “invited experts” facing off with a Mozilla developer, scorning the WHATWG as the “WhatthefuckWG.” Granted, I have no idea what they’re about either, but still. Nobody expects programmers with decorum. “Invited experts,” on the other hand…
As time has gone on I have seen that there are fewer and fewer anonymous institutions that are really trustworthy in computing. Zope was a big disappointment, after boosting themselves (anonymously) as being the premier OOP wizards of the universe. W3C has pretended for some time to know everything about the internet and to have the experience and knowledge necessary to make things happen, ultimately culminating in two large fiascos (CSS and XML Schema). In the case of XML Schema, there was a better, simpler concept around which has gained some adoption, RelaxNG. The work mainly of one person.
I bring up Lisp alot because, lately, using it is such a joy. There are some features you’d look at and say, that’s a wart. One example is multiple return values. You have to use this obnoxiously long-named multiple-value-bind form to get at the additional return values past the first one. It’s tempting to look at that and say, why not just return a list?
Well, one reason you wouldn’t think of but might stumble into is because you now want to include some extra information in what’s returned by a function but you don’t want to change all of the call sites to wrap their call with car. You wouldn’t think about this kind of thing unless you were writing in a language in which you would find yourself swapping out functions piece-by-piece. It’s the opposite of Haskell, where you want the compiler to catch every little thing and force you to say exactly what you mean.
Yesterday I implemented pagination. I had already created a paginate function and was using it to clamp the number of results. Then I realized, due to the data structure I’m using (a list masked by a series scanner) I’m not going to want to get the length of things to decide whether or not I have another page. The easiest way to decide if I have another page is to paginate on one more item than I want and see if I get one more item than I want, and then omit that from the return value and return a boolean indicating whether there’s more. So I make the changes and drop in my function which now returns something else. None of my existing code died. Then I went through and changed my existing code, function by function, to utilize the flag I’m now returning. There were something like four call sites so it wasn’t a big deal.
If this were Java, I would have told you all about using the Refactor menu item in Eclipse, and how easy it was to change all my existing code and recompile it and run it and confirm that yes, it is working.
Now you could ask questions about the quality of the design. It would not have been hard, however, to make another function do the actual work and return a list of items and a value in a list and repackage it for the existing call-sites and mark it deprecated. I don’t think that design is any better though, so in this case evolution brought us to where we probably should have been. Assuming there isn’t a dramatically better design. And maybe (probably) there is.
End rant.
Tags css, lisp, ranting | no comments
Posted by Daniel Lyons
Tue, 27 Nov 2007 15:15:00 GMT
I have implemented paging using the SERIES macros, but now I have no idea how to implement the actual next/previous links. Well, the next link is really the one I’m worried about. :)
I rewrote the HTML template portion and so 2/5ths of the pages are now generated in a reasonably nice way. I would say there are now maybe a hundred or 150 lines of code I like in the program. I may have made a (possibly false) observation about the Lisp/Haskell dichotomy:
When you program Haskell, the program starts out beautiful and gets uglier and uglier as gets closer to completion. When you program Lisp, the program starts out ugly and gets more and more beautiful as you factor it into correctness.
We’ll see if it pans out as I finish implementing the tumblog.
Tags lisp, programming | no comments
Posted by Daniel Lyons
Mon, 26 Nov 2007 18:16:00 GMT
Yesterday, I wrote a 250 line Lisp program to run my new tumblog. I have a few notes here I wanted to share about it. The next version will probably be open source; right now I can hardly stand to look at the code.
- Hunchentoot is very cool. The prefix and regex dispatcher functions are very handy. It was actually very easy to use, so easy it was almost counter-intuitive. I wonder why it took me so long to start actually building this program, since I’ve been thinking about it for so long.
However, it doesn’t help you build an abstraction atop it. That’s your problem. So my URL handling is very ad-hoc and slimy, which is one reason pagination doesn’t work right now.
- CL-WHO is a mixed bag. On the one hand, it seems to be very efficient. On the other hand, it’s a bit hard to figure out how to build a template with it. It also can’t handle XML namespaces, which means my Atom feeds won’t validate due to missing XML namespace declarations and whatnot. I also don’t know how to make it emit an XML DOCTYPE or the XML processing instruction which indicates the encoding. Once I figure out how to do a reasonable templating system with CL-WHO my line count will probably go down by 50 lines or so.
- cl-prevalence was a pretty serious win in the storage backend department. I just make a list of instances and as long as I go through the transaction mechanism they’re saved to disk and reappear when I restart the app. Very simple and elegant. I wish I hadn’t had to go by the really old documentation to figure it out though.
There is one bug with cl-prevalence though, which is that it doesn’t handle the clock—or at least it doesn’t seem to based on what I could find. This is a problem because my instances save their instantiation time as their creation time. I worked around it by making a snapshot immediately after adding an instance to the list. I have mixed feelings about that. In any case, it shouldn’t be very hard to fix this in the library by providing a special variable with the time when the transaction started and telling people to use that instead of (get-universal-time).
- I included the Parenscript library but never used it. So it’s Ajax-free for right now.
- Initially I was very worried about what format to put the date in. Then I decided, fuck it, nobody really cares what time you post something, they only care whether or not the site is abandoned or if they’ve missed something. So I put the last-updated date at the bottom and my design is even more minimal than Steve Dekorte’s. Top that! :) (There’s no way it could be related to my being a shitty designer.)
- Developing with Slime and sshfs was pretty good, but sshfs was definitely the worst part of it. I realized last night I could have just had the code checked out via Mercurial locally and be sending that to the remote Lisp, and then eventually check it in and back out on the server so that startup would work. Kind of a “duh” moment.
- There was a general lack of refactoring. I have a to do list with about 5 simple refactorings I should have done during development. Once a little bit of your code is scuzzy, it’s pretty easy to let the rest of it turn scuzzy apparently. I guess programming is no different than any other aspect of life.
- Weirdly, when I call
read-from-string in Slime, it comes back in the tumblog: namespace, but when my code for processing the form calls it, the atoms come back in the common-lisp-user: namespace. It’s moderately annoying because I’m having to use #'string-equal to compare atoms instead of #'eq.
So there you have it. A short feature review: I can post through the web (but not edit), it understands markdown for my commentary, you can filter by tag, it has Atom feeds overall and by tag, and that’s it. I will hopefully rewrite it soon to be less scuzzy, or perhaps to add pagination, after all I only have 4 more entries to post before I need it. I plan on using tags to point out items of particular interest to some of my friends and family, so if you see your name on an item, that’s why.
Tags lisp, programming | 2 comments
Posted by Daniel Lyons
Sun, 11 Nov 2007 01:35:00 GMT
One of the great pleasures of being a Haskell user is using hylomorphisms to accomplish all your work. To wit:
factorial x = foldr (*) 1 [2..x]
fibonacci = 1 : 1 : (zipWith (+) fibonacci (tail fibonacci))
Obviously this kind of obnoxious behavior would have to be ported to Lisp at some point. And it was, via the Series macro package. It’s Appendix A in CLtL.
In Lisp you’ll have to make a few concessions. You have to construct your series from other series. There are some handy ways of getting a series from a list or vector or another series. You’re limited to lazy lists using this functionality. Still, it’s fun.
To get started, install SERIES with (asdf-install:install 'series) and then import it with (require :series) and (use-package :series).
(defun fac (n)
(collect-product (scan-range :from 2 :upto n)))
This is a pretty straight across port: [x..y] becomes (scan-range :from x :upto y). You can omit the :from and it will start with 0, omit the :upto and it will go on forever. There’s also :by which defaults to 1 for replicating the [n,m..z] syntax in Haskell. You also have :length to ensure that you only get so many (very helpful during programming because of the “P” in REPL.) And misc predicates like :above and :below are useful in certain situations. You can also use :type to change the type to ‘float if you want to produce series of floats.
collect-product does what it sounds like it would, multiplying all of the numbers together. If we didn’t have it built-in, you could replicate the functionality with (collect-fn :integer (constantly 1) #'* (scan-range ...)).
Dealing with the Fibonacci numbers is a bit more complicated:
(defvar fibs
(scan-fn '(values :integer :integer)
(lambda () (values 1 1))
(lambda (x y) (values y (+ x y)))))
This works using Lisp’s multiple return values system. Basically, we’re returning two values with each function call; one of them is being passed out to be the item, and both are being fed back through the series generator. It’s not as beautiful as the Haskell but it captures the same concept, is as general (for lists) and performs some similar optimizations.
Tags haskell, lisp | 1 comment
Posted by Daniel Lyons
Fri, 28 Sep 2007 09:11:00 GMT
My faith in Haskell has wavered somewhat lately, and all because of Reddit. Essentially, three things:
- Haskell’s fixed-point combinator,
y f = f (y f).
- The ramifications of Haskell’s purity on abstraction.
- Haskell’s epidemic academia.
The first is really two problems. One is that the usual definition of the Y-combinator is not itself recursive. Obnoxious. The second problem is that, though it’s beautiful, there are a number of problems that you can’t express in Haskell using the above combinator which you could in an untyped language. This isn’t, apparently, news to anyone but me. I can’t see how to use the above Y-combinator. This is an incredibly academic problem, like most Haskell problems, but it bugs me a little.
The second was elucidated by Peter Van Roy on Lambda the Ultimate’s forum:
“True state lets information pass “underground” between two interfaces, i.e., the information passes without any apparent connection between them. This is because the connection is the shared state, which is shared by the two interfaces yet hidden from the outside. The shared state is a kind of covert information channel: it lets a module pass information to other modules (or to itself in the future) without anybody else seeing it.”
His point has to do with the fact that Haskell’s purity means that in order to get data from some point A to some point B through a number of other modules, each of the intermediate modules will have to carry the information around, even if it doesn’t do anything with it.
I would like to hate that, really, I would. But I can’t, because I programmed Voltaire in a very functional and abstract way in PHP partly because I could count on a handful of global variables passing some state around “underground” between modules that were loosely connected. In particular, Voltaire creates a region context and a template context in which each script is evaluated. The database connection is also shared clandestinely like this. If I were using Haskell, every function in the system would have to take an extra four parameters to get the current region, template, path and database connection, even if it wasn’t going to use it or pass it directly to a child.
It’s easy to denounce. At the same time I feel blameless for having done it, because while the state is “available” to anything beneath, nothing should be changing these variables outside the core. It’s available in a read-only way. Later on I wrote a plugin for rendering templates programmatically, and that involved understanding the inner state, and another plugin for producing lists which also involved understanding the inner state. But languages like Lisp provide interesting semantics for those times when you would want to change the behavior of a global variable safely.
Which brings me back around to Lisp, the language I have paid the least attention to of the four or so that I decided were “safe” so long ago when I started to force myself to use functional programming. And, truly, there are things about Lisp which are hard to love. The principle advantage of Lisp is that it permits you syntactic innovation. It’s certainly the only language that provides it meaningfully (let us not quibble about Lisp/Scheme differences or bizarre languages like Pliant). But doesn’t this seem like the fundamental abstraction of programming languages?
Aren’t we always starting with some problem and selecting a language based on its syntactic abstraction of some part of the problem domain? I mean, I pick Lisp because I want the ability to create my own structures. That comes in handy against every problem domain. But if I want to write a blog, well, Rails makes it a lot easier up front. Maybe I don’t get linguistic abstraction, but the starting abstraction is quite close. Michael chooses REALbasic for application development, I choose Cocoa. Both of us are making certain sacrifices in the name of abstraction. I lose defmacro. He loses the most recent Cocoa innovations. If I pick Lisp for my blog, then I’m sacrificing the fast start. The laziness of later syntactic abstraction had better pay off. The up-front cost is higher. For any given reasonable language, there is going to be a situation in which its abstraction is an up-front benefit that beats the up-front cost of using Lisp.
You see, these languages are compression algorithms. They compress your explanation of how to solve a problem. Like any compression algorithm, there are problems for each language that compress so badly you wind up writing a different language inside the language. This is Greenspun’s law all over again. Lisp wins frequently because it makes it easy to create a sublanguage for a subproblem that compresses it better. Ruby wins frequently because it encompasses most problem domains.
And Haskell wins frequently in academia because academia is interested in representative subproblems rather than complete problems. My experience on the ICFP this past year was that when you give Haskell a pure math problem, it will beat nearly anything else hands-down for both readability and speed. Now sprinkle some I/O on the problem. How about a non-local return? Perhaps a bit of, dare I say it, destructive state? Suddenly you find yourself looking up “monad transformer,” wondering what the hell you got yourself into.
And Justin, G-d bless him, is a Haskell wizard. I can sort of read the code he wrote. My contribution to that code was negligible. I wasn’t much help debugging it. But at the end, we had a performant Haskell version using prominent Haskell performance themes. But it was also 300 lines of code. I remain convinced against any of that pesky proof stuff that an OCaml implementation would have been half the length, more understandable, maintainable and debuggable. I believe Justin came away from the contest with the opposite conclusion: proof, solid proof, that Haskell can be made to attack the kinds of domains that other languages are generally selected for. In other words, his success with Haskell encourages him to use it more, whereas it filled me with doubt.
And today I see on Reddit a link to the paper introducing Haskell Server Pages. Not to the code itself, or the documentation talking about it, or to a page talking about it or some examples, but to an academic paper about it. I write on Reddit that “I have to admit I’m getting a bit tired of seeing things that should be cool Haskell libraries show up as academic papers. It’s as though the whole industry has turned its gaze to Haskell, exasperatedly asking to see something practical, and instead of turning out practical things, the Haskell world turns out academic papers about practical things. “Proof” that Haskell can be used practically is not the same as people using Haskell practically, nor the same as people practically deciding to use Haskell.”
Let’s face it. I really enjoy Haskell in part because of its snobbery, but that’s really a part of what it is. And the posturing about how mind-expanding it is. Haskell is addicted to academia. You’re much more likely to see a paper about some neat library than a neat library. When you go look at the code, it’s untested, only works on one platform, is broken or partially implemented. Academics are not rewarded for having good, useful code. They’re rewarded for writing papers.
Look at the Wash page and tell me who’s going to use this framework. Look at the first four links. Notice these PDFs and PS files are all LaTeX output. What kind of web people would do this? Academic web people.
So here we are. I suppose every language has its vices. I’m particularly drawn to languages that do a lot of posturing, apparently. Beyond that I’m not sure what to conclude. Every language that isn’t pure offal (Java) seems to have a place in the world. It would be better not to get too worked up about it, but it’s probably impossible.
Tags academia, haskell, languages, lisp, programming | 1 comment
Posted by Daniel Lyons
Fri, 28 Sep 2007 08:18:00 GMT
The other day I was talking to a friend about what one does to unwind. I mentioned that I program for fun, and he immediately asked me how large the kind of program I write for fun is. I said, they almost never get beyond a couple hundred lines. Rarely do they surpass 100 lines. And this is with my usual commenting ratio of about a comment per line or two, with lots of whitespace. Contrast with my for-pay programs, which start in the thousands and reach up into the tens or (in one case perhaps) hundreds of thousands.
Michael’s son Adeo and I have been learning Inform 7 in tandem for much of the year. Most of my programs have been short explorations of a single theme or programming concept. It’s more natural to talk about an Inform program in artistic terms than a conventional program; let’s call these poems or vignettes. That’s the category most of my small programs fall under. Adeo, however, has been writing one extremely large program, clocking in at about 3000 “words,” which looks like 400 or 500 lines of code.
I usually stop myself from starting on projects that look like they’re going to get to that size. As I put it to Michael metaphorically, I never build a garage at home; just wrenches. I make tools for myself, but not applications. I would never dream of coming home to work on DanApp. I get stalled pretty early on with stupid architectural things.
Another friend was telling me recently about the importance to his relationship of taking one day at a time, corny as it sounds. Somehow, the belief that you can put it down and never come back is important to undertaking large tasks. My fear of starting a huge program is really a fear of maintaining a large program after it isn’t fun anymore. It’s fear of deciding 1000 lines in that it should have been written in a different language, or with a different data storage system. It’s a fear of time, or of having to work hard. Yet Adeo doesn’t harbor any fears about his large Inform story. He can walk away from it at any time—and it has been weeks since he’s worked on it. Someday he will probably stop working on it altogether, but it will be a silent kind of stopping, a finding of other things to work on.
Soon I’m going to be starting on a side project at home. What comes to mind is a tumblog, a blog consisting primarily of a list of links with a very small amount of commentary. This has become necessary because, through Reddit, Anarchaia, and a variety of other sources, I gather a lot of interesting links which I mostly email to my friends. This is handy for me and for them, because I get a record in my inbox and they don’t have to police these sites looking for interesting stuff. But it also sucks because I usually leave out people who would or might be interested, and because I never can find the link again even though it’s in my email somewhere. I’d particularly like for it to have a link back to some kind of personal wiki or CMS that I could set up for certain topics, based on what my room mate David Baird does for himself.
Immediately I am assaulted by various hangups. Which language should I use? I’ve more or less decided on Lisp, not just because I am having doubts about Haskell, but also because I want to learn it better. Even setting that up worries me. Will it hog resources on Bill’s server? Will people be able to hijack it through Slime (probably)? Should I use a database or a list in the language? What am I going to do with this blog? What about forward and backward compatibility with the URL? Separate subdomain?
If I were smart, I would try to just take it one day at a time and address each of these things in sequence. Instead I try to design it up front, eat the whole elephant in one bite. If I were smart, I would just do what Adeo does: work on it when I feel like it, making what I want to have happen, one day at a time.
Here’s hoping I can figure out how to do that.
Tags blogging, inform, lisp, programming, projects | no comments