Home
Beware of the Train [entries|archive|friends|userinfo]
pozorvlak

[ website | My Website ]
[ userinfo | livejournal userinfo ]
[ archive | journal archive ]

Links
[Links:| My moblog Hypothetical, the place to be My (fairly feeble) website ]

Lazy lists, impatience and hubris [May. 16th, 2008|12:12 pm]
[Tags|, , , , , ]

There was a recent mailing list post by Andrew Coppin (which received some discussion on programming.reddit) in which he bemoans the way that GHC, when presented with reasonable-looking code, can suddenly and mysteriously decide that it needs to allocate gigabytes of memory, slowing your system to a crawl for ages (I've had similar problems myself). Andrew's example was the following:

I offer up the following example:
mean xs = sum xs / length xs
Now try, say, mean [1.. 1e9], and watch GHC eat several GB of RAM. (!!)
This is not so mysterious when you remember that Haskell uses linked lists as its native list structure, and so the only way to calculate length xs is to traverse the list a second time: the runtime system "helpfully" keeps around the copy of xs that it generated while calculating sum xs, and you have a space leak. But what to do about it?

The story so far )

Doing it in Perl )

Doing it in Ruby )

Take-home messages )
link10 comments|post comment

Sage [May. 14th, 2008|01:15 pm]
[Tags|, , , , , ]

Those of you who do scientific computation may be interested in this link:

Bye Matlab, hello Python, thanks Sage.

Short version: Sage is a bundle of all of the various numeric/scientific/graphing tools for Python, made easy to download and install (even if you don't have root access, apparently). According to the blogger linked above, it's now good enough to serve as a replacement for Matlab (and it has ambitions to be a replacement for Maple and Mathematica too, though I don't know how far along it is). It integrates with R, Gap, etc. And because it's Python, you get a real, high-level, well-designed programming language with a proper environment to do your coding in.

In other news, [info]wormwood_pearl finished her Finals yesterday. As you can imagine, we're both pretty relieved. There's no tradition of meeting people outside Finals here like there is in Oxford, but I went along with a bottle of champagne anyway - and only then remembered that public drinking is against Glasgow bylaws. Drat it. We went out to lunch, the bottle went into the Department fridge, and we subsequently went round to her sisters' and drank it there while watching Layer Cake. Because we're that exciting.
link13 comments|post comment

LOLhacker? [May. 8th, 2008|02:20 pm]
[Tags|, , , , , , ]

I know I'm very late to the LOL$thing party, but what the hell:

Cut for size )

Now, I reckon about half of you will recognise the guy in the pictures, and about half will understand the captions. I'm interested to know how large the intersection is...
link17 comments|post comment

This is a test [Apr. 29th, 2008|04:35 pm]
[Tags|, , , , ]

=pod

... do not be alarmed.

What happened was that I was talking on Reddit with Masklinn about Literate Programming, and s/he wanted to know if there were any systems other than Literate Haskell which allowed for blog posts which are valid code. "Hrmmm," I thought, "I don't see any obstacle to doing that with POD... )

Right, back to work.
link22 comments|post comment

Why I like Perl [Apr. 28th, 2008|12:18 am]
[Tags|, , , ]

I wrote this in an email to a colleague of [info]totherme's a while back, and have occasionally felt the need to refer to it since. Fortunately, I have a place where I can post my ill-informed ramblings for all the world to see, so here it is :-) It's an attempt to convince a computer scientist, who I believe comes from the Haskell/static typing camp, why Perl is worth learning.

[If you're not a computer scientist, the two chief reasons to learn Perl are (1) it's incredibly useful, (2) it's great fun. But I digress.]

In many ways, Perl occupies the opposite corner of design-space to Haskell. To a first approximation, Haskell proceeds from the question "what if everything we think we know about language design is right?", whereas Perl proceeds from the question what if everything we think we know about language design is wrong? )
link20 comments|post comment

Pozorvlak's Conjectures [Mar. 30th, 2008|08:40 pm]
[Tags|, , , ]

For the past couple of years (longer, actually), I've been thinking a lot about this business of static and dynamic typing in programming languages. Here's my current position on the matter.

Static and dynamic typing encourage and reward quite remarkably different approaches to the creation of software: everything from the nitty-gritty, (sit and think?)-edit-(compile?)-run-(test?)-(debug?)-(repeat?) cycle to the design (at all levels) of the software to be created, taking in every aspect of the tools and process used to support this design and implementation. Also, the choice of static or dynamic typing is best understood as part of a larger attitude towards development. Unfortunately, the use of a dynamic mindset with a static language not only means that you can't take advantage of the tools available (or even see why they'd be useful), it actively hinders success. The same is true for approaching a dynamic language with a static mindset.

I would therefore like to propose Pozorvlak's Conjectures:
  1. If you find that a modern dynamic type system causes more problems than it solves, you're probably doing it wrong.
  2. If you find that a modern static type system causes more problems than it solves, you're probably doing it wrong.
For instance, I find Haskell's type system causes me many more problems than it solves. Discussions with more expert Haskell users suggest that I am indeed doing it wrong. This guy, on the other hand, finds that "the dynamic languages stick out like sore thumbs because of the whole class of dynamic run time errors that show up that don't even appear in the statically typed languages". If you find this, I claim that it's because your code is not polymorphic enough1. You can get away with having code which only accepts data of very restricted types when the compiler does all the checks for you statically. When it doesn't, you're better off writing code that behaves well for a wider class of inputs, and dynamic languages give you much more facility to do this. Once you learn to code like this, your problems largely go away. As a bonus, your code becomes more flexible, and whole classes of techniques become possible that would have been literally unthinkable before. Similar claims, it appears, can be made for static languages: at the higher levels of mastery, one can use a static type system as a theorem-prover to establish some quite nontrivial properties of your program automatically and across the entire codebase. This allows for some excitingly different approaches to program development.

A corollary is that if you ever finding yourself saying that your port of Feature X to Language Y is better than the original Feature X solely because it's (statically|dynamically) typed and the original Feature X was the other one, you should probably save your breath. It will probably also be worth your while to go back and determine what advantages the opposite choice of typing regimen gave to Feature X's users.

1 A less interesting, but probably valid conjecture is that you're also not testing enough, or at least testing the wrong things. But this can't be the only answer. Dynamic programmers, in general, are not idiots; they are usually also Lazy, in the good sense. They're smart enough to work out that writing the equivalent isa_ok() test every time they would have written a type declaration in Java or whatever is no time-saver at all. Hence, they must need less type information overall for their code to be correct.
link22 comments|post comment

Better living through shell scripting [Mar. 28th, 2008|03:31 pm]
[Tags|, , , , , ]

As I may have mentioned once or twice before, I'm writing up my thesis. This is an intensely slow and depressing process, and the temptation to slack off is overwhelming. Being a geek, I decided to write some code to help me. Writing code rather than writing thesis is still slacking off, obviously, but it's slacking off to a useful end. Writing blog posts about writing code that's meant to help me write my thesis is another matter...

Read more... )
link12 comments|post comment

Minor annoyances [Mar. 10th, 2008|08:47 pm]
[Tags|, , , , , , , ]

A guy on Reddit pointed me at this article today. It's the Wikipedia biography of the Welsh computer scientist Donald Davies. Like my father, he was from the Rhondda Valley; he was the co-inventor of packet-switched networks (like this big one you're using right now); and he once found a bug in Alan Turing's code, before the first computer had been built :-)

I think he may be my new hero.

In other news:
  • I've just finished Portal. It was great, but far too short :-( If you haven't played it yet, then you should go and buy/download a copy right now, and cover your ears and sing "La la la la la..." until it's loaded to avoid being spoilered like I was. The puzzles are still a lot of fun, but the plot and jokes would have been a lot better if I hadn't half-known they were coming.
    [And I didn't find "The Cake is a Lie!", even though I was looking out for it...]
  • Spent a lot of time sitting at the computer today, but didn't get any thesis done. Bah.
  • After a similarly unproductive morning yesterday, I went to the climbing wall, and had quite a good session: I did two 6as (which is good, for me), led a widely-agreed-to-be-undergraded 5+, and finally knocked off a 5+ with a big scary overhang that had been tormenting me for months. Yay!
  • This may be the most awe-inspiring programming war story I've ever read.
  • Letter from Linacre: I didn't get the job. Never mind.
  • The winter mountaineering course I was booked on next weekend has been cancelled due to lack of interest. Just when the snow's started up again! I'm much more annoyed about that than about the rest, to be honest.

Ah well, tomorrow will be better. Anyway, have a look at this video, which is the trailer for one of the films I saw at the mountain film festival on Saturday:



That sea arch he's climbing up the underside of, by the way, is provisionally graded as a French 9b :-)
link14 comments|post comment

Java is the new Ada [Mar. 6th, 2008|12:16 pm]
[Tags|, , , , , , , ]

There's a meme out there that Java is the new COBOL. The rationale is summarised nicely in the first couple of paragraphs of this Wiki page, before they ramble off into a rant about how Smalltalk should have taken over the world:
Is Java the new Cobol? A good argument can be made that yes, it is. Considering the billions of lines of Cobol code that have been (or still are) in production; that observation should in no way be considered a slur. Java has succeeded in the marketplace (partially) because it is a language of its time; not one behind the times - or ahead of them.

Java is the new COBOL because it's becoming the new de facto standard for enterprise applications. Like COBOL, it's a good language for its time, but there are better ones. Like COBOL, it's bloated with features. Like COBOL, it's being used beyond its original view.
This comparison is appealing, but false. As I've been saying for years, Java is the new Ada.

Consider:
Java Ada is a compiled, structured, statically typed, imperative, and object-oriented high-level computer programming language. It was originally designed by a small team led by James Gosling Jean Ichbiah. Java Ada emphasises "programming in the large", portability, multiprogramming using threads the rendezvous mechanism, and, in particular, the development of reliable software, which is aided by a combination of strong static typing and runtime checks inserted by the compiler. The restrictions of static typing are partially alleviated by the ability to create "generic" types and subroutines. Java Ada is particularly intended for development of software for embedded systems and hard real-time environments. The familiar C++ Pascal-like syntax aids new learners, and a large standard library provides much common functionality as standard.
It's instructive to ask why Java took off when Ada largely didn't. There's no single answer, but I think the following factors explain a lot:
  • More programmers were familiar with C syntax than Pascal syntax (or associated Pascal syntax with limited Pascal environments they'd used at school).
  • Java came from Sun, a company with programmer cred, and had the names of famous and respected hackers (James Gosling, Guy Steele) attached to it. Influence leaders in the hacker community took it seriously. Ada came from the DoD and Honeywell, and some guy that nobody'd ever heard of.
  • Sun marketed the hell out of Java, and did so to the right people.
  • Early Ada compilers were very poor, and by the time good compilers were available, the language had acquired a bad reputation.
  • Mostly, though, I think it was timing. Ada was developed just before OOP went mainstream, so missed out on that bandwagon. By the time Java came along, OOP was well-established, and the masses were ready for a language in which OOP was built-in rather than bolted on. They were also familiar with the horrible complexity of C++, and were ready for something like C++ but less painful. "Reliable software" was a less effective rallying call back in 1980, unless you were developing control systems for aircraft (Ada's original niche). Ada was ahead of its time in many ways; Java, as the Wiki poster said above, was very much of its time.
There are some other suggestions here, from someone who appears to have been around at the time and is thus more reliable than me.

The new COBOL is, of course, Visual Basic.
linkpost comment

Haskell doesn't need macros, eh? [Mar. 6th, 2008|11:25 am]
[Tags|, , , , , , ]

A comparison of the Haskell argmunger with its Arc equivalent (or even its Perl equivalent) should make something clear. It's been claimed that Haskell doesn't need macros, because most of the things that Lispers need macros for can be done in Haskell using lazy evaluation and so on. But the argmunger example makes it clear that there are things for which Lispers don't need macros and Haskellers do - if not Template Haskell macros, then SYB or DRiFT or some other macro-like facility.

Lispers often say that coding in other languages feels like manually generating macroexpansions. I'm nobody's idea of a Lisp hacker, but I often feel like this when I'm writing Haskell. Which is why I'm learning about Template Haskell even though I'm not yet au fait with things like do-notation and monad transformers, which most Haskell experts would probably consider more basic. Would you choose before or after you'd walked to Moscow to staunch the blood from your severed arm?
link4 comments|post comment

Argmunging in Arc [Mar. 5th, 2008|11:28 pm]
[Tags|, , , ]

By the way, here's what an argmunger looks like in Arc:
(def argmunge (munger victim) (fn args (apply victim (map args munger))))
It's used like so:
arc> ((argmunge '(1 0) cons) 'x 'y)
(y . x)
arc> ((argmunge '(2 3 1 1 0 3 2) list) 'a 'b 'c 'd 'e 'f 'g)
(c d b b a d c)
That took a couple of minutes to write, and worked first time. Sw33t! Though I thought I'd got it wrong at first, as there was a bug in my test code :-) Note, by the way, that I'm mapping one list over another, to get the moral equivalent of Perl's list-slicing: this is a spin-off of the way that Arc treats function calls and data-structure indexing as indistinguishable. I'd hoped that I could write an argmunger that could be handed either a list or a function as its munger and Do The Right Thing, but unfortunately I don't think there's any way of determining the domain of an Arc function (the equivalent of the list's length) automatically.

I've changed the method signature so the munger is the first argument: that's because (argmunge m1 (argmunge m2 f)) is equal to (argmunge m1:m2 f). It's usual in operad theory to have the munging functions acting on the right: this is because they usually only consider munging functions which are invertible (ie, permutations), and use the definition (sticking with Lisp notation):
((argmunge' f m) x(m 0) x(m 1) ...) = (f x0 x1 ...)
So (argmunge' f m) is equal to (argmunge m-1 f). With this definition (which is fine if you only allow permutations) then (argmunge' (argmunge' f m1) m2) is equal to (argmunge' f m1:m2), so it makes more sense for the arguments to be that way round. But when you allow your munging function to be noninvertible, you have to use the definition I gave, and then it makes more sense to have the mungers acting on the left.
link2 comments|post comment

Template Haskell, argument munging and operads, part I [Mar. 5th, 2008|10:37 am]
[Tags|, , , , , , ]

[The hope was that this post would come in three somewhat independent sections: one pure programming, in which we develop a small utility in Template Haskell; one largely mathematics, at the upper-level high school to beginning undergraduate level, wherein we describe another approach to constructing our utility; and one purely mathematical, more sophisticated but fairly handwavy, wherein I relate all this stuff to my research interests and describe where it leads. The idea was that you could skip the code and jump to the maths, or read the code and skip the maths, or whatever. However, just the first section has now taken far longer than I'd budgeted, both in time and in space, so I'll save the other two for a later post.]

In a recent post, Hitesh Jasani writes about Haskell's flip operator, which takes a function f and returns a function which behaves like f with the order of its first two arguments reversed. So (flip f) x y z w = f y x z w (we write function application without brackets, as is customary in Haskell). I pointed out to Hitesh that actually, we could write such a function in almost any language which supports higher-order functions, and in dynamic languages (like Perl or Lisp) we can go further, and write a function argmunge, which accepts two functions and permutes the arguments of the first one (the "victim") according to the second (the "munger"). So
(argmunge f g) x1 x2 x3 x4 ... = f xg 1 xg 2 xg 3 xg 4  ...
Here's an implementation of argmunge in Perl, and some code to exercise it:
sub argmunge {
    my $func = shift;
    my $munger = shift; # not necessarily a permutation
    return sub { $func->(@_[@$munger]); }
}

sub myprint {
    print "Called with args ".join(", ", @_)."\n";
}

argmunge(\&myprint, [2,5,5,6])->(0,1,2,3,4,5,6);
argmunge(\&myprint, [3,2,1])->("fred", "barney", "betty", "wilma");
When run, this displays
Called with args 2, 5, 5, 6
Called with args wilma, betty, barney
Here we don't pass the munger in as a function, but rather as a list of values [g(0), g(1), ..., g(n)]. I'm prouder of that code than I probably should be, because it relies on some nice Perl features to work as it does; namely, Perl's argument-passing convention (in which all arguments are passed to a function as a single array called @_), list slicing (in which you can index into a list with another list), and list flattening (in which inclusion of one list in another splices the inner list into the outer list, resulting in a flat list). I remarked that it wouldn't be possible to write a general argmunger in Haskell, because the type of the result depends crucially on the actual value of the munging function. It ought to be possible to write one in a dependently-typed language like Cayenne - anyone care to do so?

[Edit: it's possible to write an even nicer version in Arc.]

Anyway, it may not be possible in vanilla Haskell, but it is possible using templates. )

The final code can be found here. As always, all suggestions for how I could improve my code or my development practices are gratefully received!
linkpost comment

Template Haskell: baby steps [Mar. 4th, 2008|11:43 am]
[Tags|, , , , , , , ]

My post about design patterns and if-statements in Smalltalk yesterday got a very pleasing reaction, garnering some informative comments from knowledgeable people and making the front page of programming.reddit. I guess I should have checked my facts on Smalltalk semantics more carefully before clicking "Post" :-) One comment that particularly interested me was this one (sadly anonymous), which shows a rather cute trick for using Smalltalk-style keyword methods in Haskell:
data Then = Then
data Else = Else

if' :: Bool -> Then -> a -> Else -> a -> a
if' True Then t Else f = t
if' False Then t Else f = f
Now that's pretty cool, and could even be useful for DSL implementation1. But there's a problem. See the repeated code?
data Then = Then
data Else = Else
Here, let me show it to you the way it looks to me:
data Then = Then
data Else = Else
Literally half the elements that aren't pure syntax on those lines are repeated. What I'd like to do is define a keyword function, and then just write
keyword Then
keyword Else
Or, better,
keywords Then Else
Not a big deal, you might think, but what if you were writing a whole EDSL with many keywords? Or many different EDSLs? And it's not just the repetition: by defining a keywords function, I'd move the code up an abstraction level, making my intent clearer. We could of course write
data Keywords = Then | Else
but then we lose the benefit of compile-time syntax checking of our EDSL. Well, I guess our pseudo-keywords are syntactic sugar anyway, so it doesn't really matter. But still.

A few days ago, someone asked me for an example of code that's repetitive in Haskell but wouldn't be in Perl, and here's one. In Perl, and probably in Python, I could write a keywords function. It would be ugly, and would involve hairy symbol-table hacking or calls to eval, but the user wouldn't need to know that and I'd only need to write it once (never mind the fact that the "pseudo-keyworded functions" pattern wouldn't actually make any sense in Perl...). In Lisp or Ruby, I wouldn't need to write it at all, because I could use symbols instead. But perhaps this kind of thing (and other, more egregious examples) are just the price we pay for Haskell's type system, and are more than balanced out by greater opportunities for concision and abstraction elsewhere?

Nah, bollocks to that. We can do better.

Template Haskell to the rescue! )

The final version of Main.hs is here, and the final version of Keyword.hs is here. Not entirely straightforward, but we pretty much got there in the end. Would it be worth posting these code samples to the TH wiki, and perhaps linking here? Anyway, it's nice to have finally got this simple stuff to work: hopefully I'll be able to get some more difficult things to work soon, and this should reduce the amount of frustration and needlessly duplicated code in my Haskell programming experience.

1 Did you know you can do this in (plain) TeX, too?
\def\fred #1 barney #2 betty{#1#2}

\fred Hello there, barney Wilma betty !
produces "Hello there, Wilma!".
link6 comments|post comment

If-statements in Smalltalk [Mar. 3rd, 2008|01:32 pm]
[Tags|, , , , , ]

I did warn you...

A while back, [info]markdominus wrote an article about the Design Patterns movement, in which he claimed that design patterns are basically signs of weaknesses in programming languages; if a language forces you to implement the same pattern of code over and over in different programs, that's a sign that your language is insufficiently high-level with respect to problems that your users actually encounter, so language designers should focus on patterns as places where their languages could be improved. This prompted some reaction in the tech blogosphere, including this response from Ralph Johnson, one of the authors of the original Design Patterns book. Dominus responded here, correcting some of Johnson's misunderstandings and commenting further; in fact, though, they're mostly in agreement (and I'm pretty much in agreement with them both, FWIW).

Everyone up to speed? Good.

Something Dominus didn't seem to get was Johnson's distinction between things that are in the language and things that are in the library. Johnson seems to think that there's a three-tier hierarchy:

1) Language features
2) Library code (available to every application)
3) User code (must be written for each application).

He claims that it can be a good tradeoff to leave something as a pattern, because the alternative might be to overcomplicate the standard library or, even worse, the language itself - he seems to have visions of a language with decorator, abstractFactory etc. as keywords. Dominus largely refutes this claim in his response. But more interestingly, Dominus thinks that the distinction between 1 and 2 is basically artificial - is C's printf (or Haskell's standard prelude) part of the language or the library? It might matter to language implementers, but to the average programmer, the distinction's pretty unimportant. Now, this is a good point, but I think I can see what Johnson's getting at. Remember that Johnson's a Smalltalker. Let's consider (finally) how Smalltalk handles if-statements, which in most languages are built-in syntactic elements of the language.

In Smalltalk, booleans (ie, True or False) are objects: specifically, they're instantiations of the abstract base class Boolean, or rather of its two subclasses True and False. So every boolean has type True or False, and no actual member data. Bool has two virtual functions, ifTrue: and ifFalse:, which take as their argument a block of code. Both True and False override these functions; True's version of ifTrue: calls the code it's passed, and False's version does nothing (and vice-versa for ifFalse:). Here's an example:
a < b
  ifTrue: [^'a is less than b']
  ifFalse: [^'a is greater than or equal to b']
Those things in square brackets are essentially anonymous functions, by the way. Except they're objects, because everything is an object in Smalltalk. Now, what's happening there is that we call a's "<" method, with argument b; this returns a boolean. We call its ifTrue: and ifFalse: methods, passing as arguments the code we want executed in either case. The effect is the same as that of the Ruby code
if a < b then
  puts "a is less than b"
else
  puts "a is greater than or equal to b"
end
but what other languages do with special syntax, Smalltalk does as a special case of method-dispatch. (Code samples from here). This completely blew me away when someone ([info]pdcawley?) first told me about it. Haskell does something similar, of course. [Edit: no it doesn't - see comments. But it could. I've also got some details of the Smalltalk wrong.]

Now, back to Johnson. Smalltalk's designers had three choices: bake special syntax for if-statements into the language, implement it in Smalltalk library code in terms of more general concepts that were part of the language, or force the programmer to do the work him/herself every time (using, I dunno, computed gotos or something). They made the unusual choice to go for the second option. While this doesn't matter if all you want are if-statements, it affects the language in other ways: the powerful abstraction mechanism needed to do this is available to the user to define new features.

This, I think, is the real distinction between "language" and "library": if the feature in question could have been implemented by your users using a combination of other features, it might as well be part of the library. Smalltalk's if-statements pass this test, as do (say) Lisp's looping constructs. Haskell's monads fail, because of do-notation: if a Haskell programmer wanted to add similar syntax for (say) comonads, would they be able to? I don't think so, and so it follows that monads are actually baked into the language. Several of Perl's built-in functions do things that user functions wouldn't be able to do, and thus should count as part of the language, even though they feel like part of a library.

So here's where it applies to design patterns: if your programmers find themselves having to implement essentially the same code over and over again, it's because you don't provide powerful enough abstraction mechanisms for programmers to write library modules that would do the job for them. Programmers are (rightly) lazy, and don't do work many times if they can do it once and then use that solution over and over again. So the fact that it's a design pattern means that it can't be in the library, and your language needs fixing: either by special-casing extra language features in or (preferably) by making your abstraction features more powerful, so the necessary library code can be written.
link40 comments|post comment

(quote pozorvlak) [Feb. 23rd, 2008|10:47 pm]
[Tags|, , , , , ]

I observe to my astonishment that I've made the "Quotes of the Week" section of this week's Haskell Weekly News. Um, gosh.

Now if only I could work out if I've been quoted because dons agrees with me or wishes to hold me up to public ridicule :-)
link14 comments|post comment

Emacs calc [Feb. 22nd, 2008|12:25 am]
[Tags|, , , ]

Did anyone else know that Emacs' Calc mode is effectively a full-featured computer algebra system? Symbolic manipulation, vectors, matrices, calculus, graphing (provided via gnuplot), all the stuff you'd expect.

No gamepad integration that I could see, though :-)
link1 comment|post comment

[Feb. 21st, 2008|04:53 pm]
[Tags|, , , , , , ]

I went to an all-day sales pitch conference sponsored by Wolfram Research yesterday, all about just how damn cool the new version of Mathematica is. There's a lot to like: as a language, it seems to have a nice blend of Lisp-like and APL-like features, so you can do all your standard functional programming tricks and what looks like a decent subset of array programming tricks, as well as writing normal imperative code. The standard library is, of course, vast, with loads of clever symbolic, numerical, graphics and GUI code built in, and in the new version there's also lots of standard geographical/scientific/financial/etc data available, import and export filters for loads of standard formats, and other niceties. One thing I really liked was the Manipulate[] function: hand it an expression (which can evaluate to a number, a symbolic form, a graph, a 3D plot, a sound file, an animation, or whatever) and a list of parameters, and it will automagically construct a GUI widget with sliders and checkboxes that allow you to manipulate the parameters interactively and observe the result. You can even control the parameters using a gamepad, if you want... They seem to have made a major effort to make everything interoperate smoothly in the new version - one slightly silly demo they showed us was putting slider bars as the limits of an integral, and changing the value of the result as the bar was dragged about. That was always the major problem with open source mathematics software, from my limited experience - nothing does everything, so you have to learn N different incompatible sublanguages, write loads of glue code, and constantly switch applications. The Sage guys seem to be working on this, though - I'll have to check it out.

Have a look at the big collection of Mathematica demos at http://demonstrations.wolfram.com, which includes a lot of examples of Manipulate[]. There are videos, or you can download a free-as-in-beer notebook reader.

In other news, I've been having a bit of a play with the NetBeans IDE for Java, and really liking it. I've got used to doing everything in vi and the command-line, which has its upsides, but IDEs can make life so much easier for the beginner. In particular, NetBeans' wiggly red underlining has been a huge help in learning the language, and the integrated documentation browser is very nice. I haven't needed the automated refactoring support yet, but it's fun to play with - select! Click! Extract Method! :-)

But here's my question - why is it so slow? I know it's written in an interpreted language, but so is Emacs, and that runs without too much complaint on 1980s hardware. And the compiler's written in C, unless I'm much mistaken, and that's slow as hell too. Or, conversely, why were the compilers with Delphi and Turbo Pascal so fast? Simple Java programs take several seconds to compile on my 1GHz machine, where their Pascal equivalents would have compiled in an eyeblink on its predecessor's predecessor1. Is there something about Pascal that makes it especially easy to compile, and if so, what is it? Java seems at least as regular to me, and generating bytecode ought to be easier than generating native code. Or is Anders Hejlsberg just a ninja?

Thesis now at 63 pages and 22563 words, according to wc *.tex, which means that I've written 20 pages and, um, several thousand words in the last sixteen days (nearly 1000 words today, but many of those were "XXX proof here"). Progress is being made, though there's an awful lot still to do.

1 I'm sure I've mentioned our fifteen-minute link times for our medium-sized C++ app when I was working at $company: while our network of file dependencies wasn't as bad as it could have been, it still resulted in the linker having to do a lot of work. And while compiling can be distributed easily around a network, linking can't :-(
linkpost comment

[Feb. 16th, 2008|01:20 am]
[Tags|, , , , , ]

No thesis today - I had a six hour job interview through in Edinburgh, for the maths consultancy people (who, it turns out, are university friends of my Canadian friend Jeff - small world!). The interview went reasonably well, though it could have been better - I was a bit stressed out by the whole interview situation and wasn't as sharp as I could have been. The maths questions (all based on tasks they've actually encountered in the field) were completely outside my area, and hence somewhat challenging for me, but I managed to come up with not-entirely-stupid answers to them without too many hints. The programming questions were mostly straightforward (what does this bit of recursive Prolog do, implement the following standard mathematical functions in Java, write a simple method against this random spec), apart from one where I had to find an error in some threaded Java code. Did I mention that I've never written threaded code before, and I don't speak Java very well? Then they gave me lunch, then brought me back to the office and asked me all the questions from the first round again. Apparently the answer I gave to the "where would you like to be in five years?" question was very good :-)

Anyway, the company looks really cool, and the people all seemed to be good guys, so fingers crossed on that one. They've got another couple of people to interview, and they'll get back to me some time in March.
link4 comments|post comment

Onageristic speculation [Feb. 12th, 2008|10:26 am]
[Tags|, , , , , , , , , , , ]

I'm going to make what should be an uncontroversial statement: if you don't understand and use monads, you are at best a quarter of a Haskell programmer. A corollary of this is that, since using monad transformers is the only (or at least the approved) way to use two or more monads together, if you don't understand and use monad transformers you are at best half a Haskell programmer.

[Another corollary is that I am, at best, about an eighth of a Haskell programmer: though I understand monads well on a theoretical level, I invariably emerge defeated from any attempt to bend them to my will.]

But we'll come back to that later.

Something I've been thinking about for a while is this whole business of designing languages to make programs shorter. )

1 There really ought to be a word that means "would never use a twopenny word when a half-crown word would do", but I can't think of one. English grads? Edit: sesquipedalian! Of course! Thanks, [info]fanf! (Originally, I used "prolix")
2 I actually came up with this list by thinking about languages whose users were the most passionate. But they're also extremely concise, which I think is a large part of the reason for the passion. If I were focusing purely on concision, I should probably consider Forth, but I don't know enough about it.
3 J has "boxed arrays" too, which are something like two-dimensional s-expressions, but let's leave those aside for now.
4 You might want to raise this objection against Smalltalk, too: objects are members of classes, which are something like types. Now, I've hardly used Smalltalk, so I'm probably talking out of my elbow, but: since everything is an object, and the language has powerful reflection features and duck typing, we can in fact write generic operators that work for objects of many or all classes. But maybe I'm entirely wrong about Smalltalk programming: in which case, please delete all references to the language from my argument.
5 Do you find yourself wanting to go out and strangle small fluffy animals every time you have to type out an instance declaration that would be entirely unnecessary in a duck-typed language? I do. Particularly when it doesn't work and spits out some ludicrous error message at me, telling me that I've encountered another stupid corner case of the typeclass system.
6 I learned to my surprise the other day that I'm a member of the Geometry and Topology research group, and not the algebra research group as I'd always assumed - apparently universal algebra is now considered a branch of geometry!
link37 comments|post comment

Code-walking in Arc [Feb. 5th, 2008|02:35 am]
[Tags|, , , , , , , , , ]

[info]totherme kindly drew my attention to this blog post today. The author, Slava Akhmechet, tries to explain away that horrible feeling of unproductivity and frustration that I know so well from my attempts to use Haskell: his claim is that it's just that my expectations are miscalibrated from using imperative languages. A Haskell solution to a given problem, he claims, will take the same amount of thought as a solution in another language, but much less typing: by simple statistics, therefore, you're going to spend a lot of time staring at the screen not doing anything visible, and this can feel very unproductive if you're not used to it.

As an example, he gives the code
extractWidgets :: (Data a) => a -> [String]
extractWidgets = nub . map (\(HsIdent a)->a) . listify isWidget
    where isWidget (HsIdent actionName)
              | "Widget" `isSuffixOf` actionName = True
          isWidget _ = False
Bleh! :-( This function takes a parse tree representing some Haskell code, and extracts all the identifiers ending in "Widget", then removes the duplicates. Slava challenges any Java programmers reading to do the same in five lines or fewer.

Pointless language pissing match, including some Arc coding )

On language concision in general: I typically find that Haskell requires fewer lines for a given program, but Perl requires fewer characters, and they both use about the same number of tokens. Lisp is longer and messier than Haskell for easy problems, but quickly gains ground as the problems get harder.1 The APL family own on all three axes. This is extremely unscientific, of course, and because I don't know much APL/J I can't be sure how it extends to harder problems. I did once email Paul Graham asking why, if succinctness was power, he didn't switch to a member of the APL family; he has yet to reply, but I don't attach any great significance to this.

And having got all that stuff out of my head, I'm going back to bed. Hopefully I'll be able to sleep this time :-)

1Fun exercise: translate the example code in On Lisp into Haskell (or Perl, Ruby, etc.). It really helps you to get to grips with the material in the book. I found that the Haskell solutions were shorter and cleaner than the Lisp solutions up until about a third of the way through the book, at which point Lisp started to catch up with a vengeance: shortly thereafter, he was doing things in a few lines of Lisp that simply couldn't be done in finitely many lines of Haskell. I'd be very interested to see solutions written by someone who knew what they were doing, though!
link7 comments|post comment

navigation
[ viewing | most recent entries ]
[ go | earlier ]