[personal profile] flexibeast
i've finally got around to scanning through the Revised5 Report on the Algorithmic Language Scheme, or R5RS as it's more commonly known. Scheme is a minimalist dialect of Lisp. The Report and the language both feel particularly light and elegant to me.

Over the last several months, i've immersed myself in the world of Haskell. Haskell has an elegance of its own, but for me it's a very dense language (translation: It makes me feel stupid / exposes my stupidity). i often find that, when reading Haskell code, i really have to concentrate to get a sense of what's going on. And even then, i don't always "get it". Although i've noticed a TMTOWTDI-like attitude on the Haskell-cafe list: code posted as an implementation of a particular algorithm can elicit responses from me ranging from "Zuh?" to "Oh my, that is truly a thing of beauty!"

Of course, this can happen with many programming languages: i'm not a C programmer, but i've found the source for OpenBSD that i've looked at to be very understandable - a testament to the 'cleanness' of that code base. Still, on the basis of the (admittedly small amount of) Scheme code i've read thus far, Scheme comes across to me as quite a readable language. But maybe i just need to search the Web for Obfuscated Scheme contests, to see how bad it can get. :-)

Edited to add: Just came across this, which refers to someone "who compared programming in Lisp to studying Kabbalah, in that it does strange things to your head". Bwahaha!
 

Date: 2007-05-25 11:16 (UTC)
From: [identity profile] annie-lyne.livejournal.com
OpenBSD is hot.

But anyway, I really enjoy Mathematica.

Date: 2007-05-25 13:32 (UTC)
From: [identity profile] flexibeast.livejournal.com
i've never had the opportunity to use Mathematica, unfortunately - although there have been a number of stories submitted to reddit.com of late which talk about how it's teh hawtness. :-)

Date: 2007-05-26 06:10 (UTC)
From: [identity profile] winterkoninkje.livejournal.com
Hmm. I've always found Scheme a bit... too minimalistic. The cleanliness is very nice for pure clear mathematical algorithms, but it's a bit... how to say, mindwarping for more complex tasks. But then, I wouldn't consider assembly or lambda calculus a great language either.

Haskell I really like. The density per line can be very high, but it also allows for some remarkably eloquent code in the right hands. It's a bit uneven at times (then again, it was designed by a committee), but there're a lot of things it does really well.

Date: 2007-05-27 02:22 (UTC)
From: [identity profile] flexibeast.livejournal.com
Heh, funny that you should say that Scheme is mindwarping for more complex tasks, because that's often how i feel about Haskell . . . . for example, i still haven't grasped the idea of "threading state" through Haskell programs, where with Scheme i can simply (define *global* 1). But that's what i like about Haskell - it forces me to think in new ways.

Out of interest, what are the areas in which you feel it's "uneven"?

Date: 2007-05-28 00:08 (UTC)
From: [identity profile] winterkoninkje.livejournal.com
Well, yes, I suppose Haskell is also mind-warping for complex tasks. But it's... more of a theoretical mind-warping, rather than a reductionist mind-warping; and I tend to prefer the former. Also, I do really like Haskell's type system much better than Scheme's utterly untyped system. (Indeed, I prolly like Haskell's type system better than any other I've encountered. Though Ruby and Perl are pretty nice too, if less strict.)

As far as "threading state", at a first blush: you can't, because Haskell's pure functional :) The truer answer though (assuming you mean a global notion of state, instead of, say, accumulators) is: monads. Personally I think a lot of the tutorials online for monads are not the greatest since they're a bit too focused on "getting I/O done" to really give a good idea of what monads are and how they work. Also I think it's much easier to understand if you look at the underlying (>>=), (>>), and return operators first, and only later look at the do syntax as a shorthand for those operators; whereas most tutorials teach the do-syntax first, or only teach the do-syntax. If you look up some of the papers by Phil Wadler or Mark P. Jones, though, they're much better. (Or if you can take a class from them, even better ;) I can throw out some links a bit later if you're interested, I'd have to hunt them down first.

As for unevenness, Haskell's really well done for things at the expression level —which is to be expected since it's a functional language— but once you get above that it all starts to fall apart. The way modules are done is only just barely enough; Namespacing is one of the areas that's particularly bad. And, I mean, you can get that sort of effect with things like:

(foo, bar) = (foo, bar)
           where
           foo = ... (helper ...) ...
           bar = ... (helper ...) ...
           helper = ...


...to hide helper from the outside namespace, but if you do that you can't access it for things like unit testing. Which means you're left with either namespace pollution or a proliferation of meaningless modules (each needing their own file, so far as I can tell) like in Java.

At the moment, I think that's my leading complaint. There're a few other things it took me a while to get used to and I'm still not entirely fond of (aspects of whitespace sensitivity, the assumption that you always want to pass a function as an argument[1]) but I'm willing to chalk those up to the way the language works.

[1] Which leads to way too many parentheses ala Lisp/Scheme, or too many function combinators like ($) and flip in order to remove parentheses which in turn only exacerbate the namespace pollution issues (or if you use qualified modules, exacerbates the whitespace issue by making function names too long).

I prefer the way Perl uses slurpy lists for function composition (which assumes functions are to be called unless you use special syntax to get a function reference). Which, given the way function definitions work in Haskell, I can understand why they don't do that (it would lead to functions not quite being first-class in appearance). The nice thing about Perl is that it knows how many arguments a function takes (if you use prototypes) and so the moral equivalent of Haskell's (.) works a lot better, whereas Haskell's only works well if the function (or partially applied function) takes a single argument. A converse approach would be if Haskell used a special syntax to indicate function application and only took the proper number of arguments, instead of taking all of them like it does now — which would be kind of like Scheme/Lisp's parentheses but without requiring the closing parens.

Date: 2007-05-28 02:17 (UTC)
From: [identity profile] flexibeast.livejournal.com
I do really like Haskell's type system much better than Scheme's utterly untyped system. (Indeed, I prolly like Haskell's type system better than any other I've encountered. Though Ruby and Perl are pretty nice too, if less strict.)

Yeah, Perl is the language i'm most familiar with, and so Haskell, with its beautiful type system - the notion of typeclasses especially, which it's fun to watch OO people trip over ;-) - has for me been a good intro to strongly typed languages.

As far as "threading state", at a first blush: you can't, because Haskell's pure functional :) The truer answer though (assuming you mean a global notion of state, instead of, say, accumulators) is: monads. Personally I think a lot of the tutorials online for monads are not the greatest since they're a bit too focused on "getting I/O done" to really give a good idea of what monads are and how they work.

Er, sorry, i think you've misunderstood me. i know that Haskell is purely functional, and how monads cordon off non-functional code from functional code, and what things like bind operator do; i've even written a little intro to Haskell monads (http://hierodule.livejournal.com/69052.html?mode=reply) in my LJ. :-) What i was saying was that, when Haskellers talk about using, say, the ST monad to "thread state" through a program, i don't really 'get' how this 'threading' is taking place.

Re. modules and namespaces - yeah, that's an area of continuing debate on the Haskell-cafe list. And i'm not sure there's an end in sight.

Currying and partial application i'm slowly getting used to; again, my experience with Perl has helped, but it's only recently that i've really started to 'get' currying.

Finally, yes, the fact that one seems to need to have multiple versions of the same function in order to cope with varying numbers of possible arguments (e.g. zip and zip3) is a wart on the language that i simply can't get used to, relatively trivial though it is.

Date: 2007-05-28 02:28 (UTC)
From: [identity profile] winterkoninkje.livejournal.com
hen Haskellers talk about using, say, the ST monad to "thread state" through a program, i don't really 'get' how this 'threading' is taking place.

Ah. Well, basically, all a monad is is an encapsulation of state (much like objects in OO languages). You can open up that state to look at the innards and mess around with them, but you only touch the innards through methods not directly as you do in OO languages. And for wonky monads like IO, you can never discard the monadic container (though you can for "easier" monads like List, Maybe, Either,...). I'm not familiar with ST specifically to know how they implement the threading on the back-end, but I'd guess the thread data is just another state (albeit more on the IO side of things than on the easy side).

Profile

flexibeast: Baphomet (Default)
flexibeast

Journal Tags

Style Credit

Powered by Dreamwidth Studios