pozorvlak ([info]pozorvlak) wrote,
@ 2007-02-26 23:24:00
Previous Entry  Add to memories!  Tell a Friend!  Next Entry
Entry tags:beware the geek, computers, haskell, perl, programming, type systems

Tightrope walking
[Non-coders: it shouldn't matter if you don't know about the specific technical issue that I'm discussing here. Hopefully, I've managed to convey something of what it feels like to code in different languages, which is the important thing.]

I was brought up on static languages. Admittedly, the first programming language I touched was BBC Basic, which had autovivification of variables, but it also had separate namespaces for string and numerical variables. Then I was taught programming properly on Turbo Pascal, which is all about the type system. I learned object-oriented programming on Delphi, which is what Turbo Pascal turned into, and was also heavily typeful (and, incidentally, one of the nicest development environments I've ever had the pleasure to use). When I first encountered dynamically typed languages, in the form of RSI's noxious Interactive Data Language (and later VB), I thought dynamic typing was an accident waiting to happen. Programming without static typing felt like walking a tightrope without a safety net, with the slightest wobble ready to pitch me into the abyss below. Wherever possible, I'd declare variables, turn off everything implicit, and curse if there was no way to do these things.

It wasn't until I started using Perl (and I discover with surprise that I can't remember exactly when that was - presumably around 2000-2002, when I started using Linux regularly) that this began to change. Perl offers no facilities for static typing - it's dynamic all the way. More than that, it's mutably typed - if I ask for "3" + 4, it won't die at compile-time like Haskell, or at run-time like Python, it'll simply convert the "3" to a 3 and return 7. If you ask for an array element that's out-of-bounds, it won't die with an "array subscript out of bounds" error, it'll just lengthen the array so it's big enough and autovivify the extra elements. Yes, this can be slow. But there are plenty of ways of finding out how big an array is, so obviously you did that because you wanted to.

This was presumably painful at first (I can't remember). But after a while, I started to get it. All my old fears were revealed, in the light of day, to be groundless, and even slightly ridiculous - if I wobbled, then the tightrope moved under me, to counterbalance my movement and hold me up. I could walk along the rope as easily as if it were pavement, and on the few occasions where I fell off, it turned out that the bottom of the abyss was actually covered with big trampolines. The sense of liberation was wonderful. Why should I, as a thinking human being, have to worry about the trivial difference between 3, 3.0, "3" and (3), when a machine could do it for me and leave me free to concentrate on the important stuff? I started to code in tune with the language, and as a result my code became simpler, clearer, more robust. I could Say What I Meant, and perl1 was smart enough to Do What I Meant.

Which is why it's so jarring coming back to static typing for Haskell. After grokking dynamic typing, static typing just seems antediluvian. Every time a compilation dies because of a type error (and actually, having to compile code before running it seems pretty antediluvian too), it's like the hip young guy I thought I was talking to has suddently adopted the tone of a boarding school headmaster circa 1950 and caned me for having my shirt untucked and misusing the optative. And if you have no idea what an optative is or in what context you might wish to use one, then you have some idea of my bewilderment at most GHC error messages.

Maybe I'll grow to love static typing again, as I grew to love dynamic typing before it. Maybe (and this is what I'm hoping for), I'll be able to transcend the dichotomy, and come to a deeper understanding in which I realise there is no real opposition. But right now, it's hella frustrating.

1 As any fule kno, Perl is the name of the language, and perl is the name of the interpreter for that language. PERL is something different :-)




(Post a new comment)


[info]elvum
2007-02-27 12:40 am UTC (link)
I took a similar path to you, but when I got to Perl, I hated it. Perhaps the fact that I learned Java instead of Delphi was significant. Also, I had tried (and found impossible to debug) Javascript and PHP. I've heard that the existence of unit testing frameworks for Perl makes debugging more bearable though. I've yet to try Haskell, but I'm a huge fan of static typing. Except on the occasions where I say things like "if only Java had duck typing, $vital_thing would be possible..."

(Reply to this) (Thread)


[info]pozorvlak
2007-02-27 12:42 pm UTC (link)
Perl took a long time to get, certainly (and thanks must go to the incredibly helpful and friendly members of London.pm for a lot of that). I remember with a shudder the first time I tried to use references (and I still find Perl's reference syntax pretty unmemorable). Perl's unit testing frameworks are, indeed, brilliant, as are things like Data::Dumper (or Data::Dump::Streamer for code that uses closures).

What are your main languages? Java and Python?

(Reply to this) (Parent)(Thread)


[info]elvum
2007-02-27 12:45 pm UTC (link)
Pretty much Java atm. Python, Ruby and Haskell have all been on my to-learn list for about a year now, but stuff like the Goolge Web Toolkit keeps distracting me...

(Reply to this) (Parent)(Thread)


[info]pozorvlak
2007-02-27 01:00 pm UTC (link)
Python's nice, and tends to be liked by people who react badly to Perl :-) Ruby's on my to-learn list too, but I'd like to get my head round Haskell first...

(Reply to this) (Parent)(Thread)


[info]pozorvlak
2007-02-28 10:36 am UTC (link)
Further to that: Python is a modern language, Perl is a postmodern language :-)

(Reply to this) (Parent)


[info]michiexile
2007-02-27 08:30 am UTC (link)
I must admit I do not even know how to use the optative in english, given that I cannot seem to find any kind of subjunctive forms in my latent grammar storage.

However, in swedish, latin and german, I would most probably be capable of using the optative correctly. AND I always tuck my shirt. :P

(Reply to this) (Thread)


[info]pozorvlak
2007-02-27 12:45 pm UTC (link)
I'm not sure English even has an optative mood. It has a subjunctive, but it's not used much these days. My dim memory of the optative is as a particularly recondite and hairy part of Ancient Greek, a language with enough grammar for any two normal languages :-)

(Reply to this) (Parent)


[info]neoanjou
2007-02-27 09:20 am UTC (link)
You make me embarrased that I don't know how IDL works in this respect; leading me to doing weird things which just seem to work, for instance addressing a float as an element of an array (i.e. look up element 23.456 of this array) and such odd things as:

points = FLOOR( FLOAT(n) / series )

(where both n, points and series are ints. I have no idea why I wanted n is become a float, but not series, and I am aware that I could have just used integer division but I have no idea how that works [i.e. whether it is a CEIL, FLOOR or just closest integer function]).

(Reply to this) (Thread)


[info]pozorvlak
2007-02-27 12:57 pm UTC (link)
Sounds like it's weakly (== dynamically + mutably) typed, and Wikipedia agrees, but see the caveats. As for integer division, it sounds like the kind of thing you ought to know, and it would take five minutes to find out! :-)

(Reply to this) (Parent)


(Anonymous)
2007-02-27 10:47 pm UTC (link)
If the difference between 3 and "3" is trivial, then so is the difference between 3 + 3 and "3" + "3". Right?

(Reply to this) (Thread)


[info]pozorvlak
2007-02-28 10:34 am UTC (link)
Only if you use the same operator for addition and string concatenation. Which is a bad idea anyway, as string concatenation doesn't behave much like addition: it's not commutative, and it's only associative if you ignore performance issues.
pozorvlak@delirium:~>perl -le '$x = 3; print $x . $x; print $x + $x'
33
6
:-)
[You'll note that Haskell doesn't use "+" for string concatenation either.]

Secondly, the dynamic philosophy is that errors caused by this kind of thing are a) mostly trivial, b) easily detected by testing running code, which you need to do anyway to find the real bugs. I've found that this accords pretty well with my experience, tbh. But hey, I've never tried to write climate-modelling systems or real-time control software for nuclear missiles, so maybe that's just a reflection of the limited scope and relatively small scale of the code I write. But, you know, there are a hell of a lot of things you can do in ten lines of Perl, so features that only make sense for small programs should not be dismissed. And other people have successfully written large, scalable, maintainable systems in Perl.

Thirdly, I'm not really talking about whether or not static typing is better than dynamic typing - if I didn't think this was an open issue, I'd be learning Lisp instead of Haskell! (Or even Jaskell, which I must say looks fascinating). I'm talking about what it felt like to grok dynamic typing. I used to think like you until I got it. Then I gradually learned that I could rely on my tools to take care of most of this stuff for me, which led to the wonderful sense of freedom described in the main post (have you ever tried using a dynamic language seriously, ie as your main language for a year or two? Think about it - you might be pleasantly surprised, and you might even learn something). Now I'm going back to static typing and, of course, hating it - if I didn't enjoy the functional side of Haskell so much I'd probably have given up long ago! But increasingly, I'm convinced there's something deeper going on here, which is far more interesting than your tired mutterings about "3" + "3" - I think that Haskell development is about pushing axioms you want your code to satisfy into the type system, and then using your compiler as an automated theorem-checker. This is fascinating (and possibly powerful) stuff, and I want to re-wire my brain to think in this way. But, as I keep saying, it's uphill work :-(

(Reply to this) (Parent)(Thread)


(Anonymous)
2007-02-28 07:17 pm UTC (link)
"Only if you use the same operator for addition and string concatenation. Which is a bad idea anyway, as string concatenation doesn't behave much like addition: it's not commutative, and it's only associative if you ignore performance issues."

Fair enough, I guess I am a bit accustomed to it.

"And other people have successfully written large, scalable, maintainable systems in Perl."

Yes. I certainly didn't say that it can't be done! For that matter, probably someone managed to build large, scalable, maintainable systems in Visual Basic.

"Thirdly, I'm not really talking about whether or not static typing is better than dynamic typing"

The issue I am talking about is strong dynamic typing (Ruby/Python) versus weak (mutable, as you call it) dynamic typing (Perl/PHP).

"have you ever tried using a dynamic language seriously, ie as your main language for a year or two? Think about it - you might be pleasantly surprised, and you might even learn something)."

Ruby is presumably not dynamic enough, as it doesn't have mutable typing?

"Now I'm going back to static typing and, of course, hating it"

Well, even after Ruby I quite like expressive static typing (as in Haskell/OCaml/Nemerle/F#/...) I don't think I could go back to Java or C#, though.

"I think that Haskell development is about pushing axioms you want your code to satisfy into the type system, and then using your compiler as an automated theorem-checker."

Yes. Unfortunately, dependent types (which are needed for many desirable axioms) are ugly to express in Haskell. And Epigram, Cayenne or Sage (now there's a really nice type system!) are not ready for prime-time (and may never be).

(Reply to this) (Parent)(Thread)


[info]pozorvlak
2007-02-28 10:35 pm UTC (link)
Yes, I was (to some extent deliberately) fudging the weak/dynamic distinction - and I must say, I prefer the term "mutable typing" because it doesn't sound like an insult! Dynamic strong typing is a combination that's never made much sense to me, but other people seem to like it.

So, you're a Ruby hacker? Interesting. I have no idea who you are, you see, so can't infer much about your choice of languages - but I've heard your comments about string concatenation versus addition a dozen times and don't find them in the least convincing, for reasons I've hopefully explained :-)

My problems with Haskell's type system are that 1) it causes me lots of grief and frustration (and will do until I rewire my brain to do stuff that a Perl interpreter would do for me >:( ), 2) I find it's often insufficiently expressive for my needs (and many of its more recondite aspects seem rather ad-hoc). As in, I can't do things in Haskell (or can't do them without going to ridiculous lengths) that are straightforward and standard practice in C++ or Ada. Still, I'm very interested by the automated-theorem-checker aspect, and some very smart friends of mine assure me that I'll come to like the type system eventually, so I'm persisting, with the occasional rant here to let off steam.

I'm aware of dependent typing, but haven't yet looked seriously into it. I hadn't heard of Sage - I'll check it out...

(Reply to this) (Parent)(Thread)


(Anonymous)
2007-02-28 11:14 pm UTC (link)
Here is the link to Sage: http://sage.soe.ucsc.edu/

All types are values of the type *, so Haskell's Maybe is simply a function of the type * -> *, and -- here is what you wanted -- you can have Vector of the type Int -> *. You also have Dynamic type which can be cast to and from anything, so you can be as dynamic as you want, or as static as you want.
You can also have "refinement types", for example the type of positive integers: {x:Int | x > 0}. Since I tend to think of static typing as expressing contracts, this makes a lot of sense to me.

(Reply to this) (Parent)(Thread)


[info]pozorvlak
2007-03-01 12:51 pm UTC (link)
That does sound good :-)

# (1 + 2) - 4;;
Type: (Refine Int (fn (z:Int) => (inteq z (sub (add 1 2) 4))))
Evaluation: -1

Hmmmm. Looks rather Lispy...

(Reply to this) (Parent)


[info]johnckirk
2007-03-10 09:51 pm UTC (link)
A delayed response on this one...

I've never got very far with Perl; I bought a copy of "Programming Perl" (2nd edition) about 10 years ago, but it's been on my unread stack ever since. So, it's possible that I'd have a similar reaction to you if I used it more, but for now I'm mainly coming from a VB background. Older versions were quite flexible (not requiring you to declare variables if you didn't want to), and Evil Type Coersion (TM) caused me trouble several times, so I now run with "Option Explicit On" and "Option Strict On" in VB.NET.

Taking the example you mentioned ("3"+4), there were two operators for string concatenation in VB6: + and &. So, you could say "3"+"4" or "3"&"4", and either one would return "34". Bearing that in mind, if I ask for "3"+4, do I mean:
a) Convert "3" to 3, do integer arithmetic, and return 7.
b) Convert 4 to "4", do string concatenation, and return "34".
c) Do a mixture, returning "7" or 34.
Would it make a difference if I asked for 3+"4"?

It gets even more complicated with a user interface involved. For instance, suppose that I have two text boxes in a dialog box or a webpage, and I tell the program to return "the contents of text box 1 + the contents of text box 2", and both boxes contain numbers. Do I want them to be concatenated or added together?

The way I see it, computers should know their place, and that place is to obey my commands. If they don't know what I mean, they can ask for clarification, and that's fine, but I don't want them to start guessing.

I suspect that this type of thing depends on what you're doing. If you're creating a utility program that you will just use yourself, and you can fix any problems that arise, that's fine. If one of your colleagues has written a program that's being installed on machines in South East Asia, and then you get a phone call at 3am demanding to know why it doesn't work, this type of thing is a real pain the arse.

Sorry for the rant :)

(Reply to this) (Thread)


[info]pozorvlak
2007-03-11 11:58 am UTC (link)
No need to apologise :-)

As far as I can remember, I've only had a tiny number of problems caused by type coercion in Perl. Mostly it just does the Right Thing. A lot of this, of course, is sensible choices of operators: for instance, string concatenation in Perl is always ".", so "3" + 3 has the unambiguous meaning of 'coerce the "3" to 3, then add' - see my response to Anonymous, above. Note that this is not simple or consistent1 - this requires hundreds of delicate balancing acts all over the language to get the magic right. See here for an excellent blog post on this kind of thing.

The way I see it, computers should know their place, and that place is to obey my commands. If they don't know what I mean, they can ask for clarification, and that's fine, but I don't want them to start guessing.
And again, I used to think like that. But it turns out that it is possible to guess with a (perhaps surprisingly) high degree of reliability, and besides, do you trust any code that you haven't tested properly? Having experienced this, I know find it unbelievably frustrating when GHC complains that it doesn't understand something, when it was completely obvious what I meant.

If you're creating a utility program that you will just use yourself, and you can fix any problems that arise, that's fine.
Well... you know that LiveJournal is mostly written in Perl, right? And Slashdot? And the code behind both of them is deployed on multiple sites all over the world. Oh, and the Human Genome Project did a lot of its data analysis in Perl, and the Oxford English Dictionary, and ... :-)

But as I said above, a surprising number of programs are small throwaway utilities (particularly if you've got something like CPAN to draw on, to do much of the heavy lifting for you), and so features which make those easier to write (even if they're no help for larger systems) are still interesting.

1 "In general, Perl will do what you want, unless what you want is consistency" -- Larry Wall

(Reply to this) (Parent)


Create an Account
Forgot your login?
Login w/ OpenID
English • Español • Deutsch • Русский…