My paradigm is better than your paradigm

On twitter I participated in the short snarky exchange:

@stevedekorte – Threads sharing state by default is like variables being global by default.
@luqui – state is like globals :-)
@stevedekorte – @luqui only shared state – which is why FP ultimately fails – it trades comprehensibility for shared state optimizations
@luqui – @stevedekorte, wow, sneaking “FP ultimately fails” as if an obvious truth in a reply to a Haskell programmer
@stevedekorte – @luqui, a bit like sneaking in “[all] state is like globals” to an OO programmer? :-)
@stevedekorte – @psnively @luqui my only issue with FP is the decision to trade expressivity and reusability for less state while calling it progress

The conversation goes on (and on) between many twitterites, having a fun but serious argument about this and that benefit of this and that style. Dynamic/static types come up, OO vs. functional, usefulness, mathematical foundation, learning curves; none of the standard artillery is spared. What irritates me about this style of argument is all the sweeping adjectives (1) used with no definition, thus impossible to support with evidence, and (2) synonymized with better.

In this post, I will draw attention to this irritating vocabulary, so that the next time you use it you can realize how little you are saying.

(Disclaimer: this post is not intended to criticize stevedekorte specifically, even though I identify two of the terms he used below. It was a long, typical programming zealot argument, and all parties involved were being equally dumb :-)

Expressive

A person is expressive if he expresses himself — he has an idea and wants to write it down. So I would say a language is expressive if it allows or enables the programmer to be expressive. Languages that restrict expression are not expressive. So we have the following facts:

  • Dynamically typed languages are more expressive than corresponding statically typed ones, because statically typed languages forbid you from expressing some ideas.
  • Multiparadigmatic languages are more expressive than languages which are paradigmatically pure, because the former allow you to express yourself if you are not thinking within the framework.
  • A language which you are fluent in is more expressive than a language you do not know very well.

By these observations, we might guess that Perl is the most expressive language, Haskell is the least.

Do you notice yourself already equating expressive with good, and thus perhaps feeling offended? Everyone wants an expressive language, right? Here are some reasons some programmers might not want an expressive language:

  • Most of my ideas are made of bullshit. Have you ever had a great idea, gone to write it in your blog, and realized it was nonsense because you were unable to write it? So writing is less expressive than thinking. Is thinking better than writing?
  • Every programmer has a different way of structuring their thoughts. An expressive language will bring out the differences in thought structure between programmers, and introduce impedance mismatches between programmers on a shared project.

I’m not arguing that expressiveness is bad. I’m just arguing that it doesn’t mean good, it means expressive.

Reusable

A language “is reusable” (to abuse language a bit) if code written in that language can be easily reused.

This “obvious” statement is hiding something very important; namely, reused how? For what? We are in an unfortunate situation in programming: code is designed to be reused in a particular way, and if you want to reuse it in a different way you are pretty much out of luck. An OO widget library is designed for the addition of new types of widgets, but if you want to reuse a program written in the library on a new platform you are in for a lot of work. A functional drawing library is designed so that you can transform and export your drawings in an open-ended variety of ways, composing new ways out of old ones; but if you need to draw a circle you have to build it out of lines, even if there is a much better way to draw a circle on your target. (This is essentially the expression problem).

An abstraction will always expose some things and conceal others. Different languages enable abstraction in different ways, which makes exposing certain things easier and others harder. The zealot will reply, “but in my experience, real-world programs are naturally organized around <insert preferred paradigm>, and <insert uncomfortable paradigm> doesn’t support that style as easily.” I would suggest to this zealot to look deeper into the definition of “real-world” to discover its many facets of subjectivity. (What domain do you work in? Who architected the real-world software you have worked on, and what was their background? What kinds of programs do you consider not to exist in the real world, and what values are you using to minimize them?)

Easy to learn

A language is easier to learn than another language if it takes less time to become competent/fluent programming in that language.

I don’t think this one is as automatically synonymized with “good”. Haskell programmers are aware how much relative effort was required to learn Haskell, and are usually grateful that they put in the effort. But all other things being equal, a language easier to learn ought to be better than one harder to learn.

The deadly omission in the above definition is that people are doing the learning. A language is easier or harder to learn to a single person, and that is entangled with their background, their approach, and their ambitions. When arguing “X is easier to learn than Y”, I encourage you to add one of the following phrases to the end:

  • for programmers who already know Z.
  • for people with a mathematical background.
  • for people with a non-mathematical background.
  • for children.
  • for me.

Or something similar. The following phrases do not count.

  • for almost everyone.
  • for people with a typical background.
  • for people who want to do useful things.

I’ll close this section with this remark: Haskell is the easiest language to learn, because I already know it.

Conclusion

I know I am frequently irritated by many of these kinds of words, and I’ve only mentioned three here. But you see where I am going. Respect the values of your fellow engineers. If you are a polyglot and like a paradigm, it probably comes from a set of values you have — a set of things you consider important, and that differ from the values of others. Concentrate on that; communicate your values, and try to understand the values of others. If you have toyed with a paradigm and quickly lost interest because of some surface feature (I have — e.g. I will throw out a language without support for closures) or impression, consider the possibility that you like what you like because simply because it is familiar (other equivalent notions: easy, natural). Which is fine, some people like to tinker with their thinking patterns more than others, but remember that you have trained yourself to think in a particular way, so consider that your “objective” judgements about these ultimately human languages could be biased.

(For the record, that last phrase originally read: “all of your ‘objective’ judgements about one of these ultimately human languages are biased”, which is quite a bit stronger than what I had intended)

Flattr this

About these ads

17 thoughts on “My paradigm is better than your paradigm

  1. Haskell *is* an uncommonly hard language to learn simply because it is quite different from OO languages which are what most people learn at university and in their jobs. It’s not that Haskell itself is hard, it’d just based on unfamiliar set of principles to most people. But like most things in life, the easy things to acquire are rarely worth having and the best things take more effort.

    Being a C++, Java and Objective-C programmer, I could easily learn C# but it won’t teach me anything new or make me a better programmer.

  2. I don’t think things are as subjective as you make them out to be. You almost make it sound like claiming paradigm A is better than B is on the same level as saying one ice cream flavor is better than another. Aren’t there certain realities that are common to all of programming, and don’t these realities influence how effective certain programming techniques / languages / paradigms are? Yes, there are personal preferences and differing values involved, but let’s not totally bullshit ourselves!

  3. @Paul, “things” can be more or less subjective, depending on what things you are talking about. I am claiming that these three terms (and many like them) are subjective and, in particular, not synonymous with good. Summary: * Expressive does not mean good; * Reusable is not a linear scale; * Easy to learn depends on who is doing the learning.

  4. > facts:
    >
    > Dynamically typed languages are more expressive
    > than corresponding statically typed ones, because
    > statically typed languages forbid you from expressing some ideas.

    This is not a clear cut fact to me. Whilst it’s true that statically types languages (STLs) forbid you from expressing some ideas allowed in dynamically typed languages (DTLS), it’s also the case that STLs let you express ideas about the _types_ of values that cannot be expressed in DTLs.

  5. Andrew :
    Haskell *is* an uncommonly hard language to learn simply because it is quite different from OO languages which are what most people learn at university and in their jobs. It’s not that Haskell itself is hard, it’d just based on unfamiliar set of principles to most people. But like most things in life, the easy things to acquire are rarely worth having and the best things take more effort.

    I’m learning lisp and haskell at the same time at the moment, in an attempt to get whatever ‘functional’ means into my head, and am finding lisp A LOT nicer than haskell.

  6. > Haskell is the easiest language to learn, because I already know it.

    If you already know Haskell, if you’ve already learnt Haskell, then that of itself tells us nothing about how easy it was “to learn” – so we should reject the conclusion.

    If the suggestion is that, if you’ve already learnt something about Haskell then it should be easier to learn something else about Haskell, then “to learn” is being used with different meanings – so we should reject the conclusion.

  7. @Luke – I was with you up until the conclusion of your OP. I do agree that those three terms are subjective and nearly useless… I just thought your conclusion went too far in making it seem like there are no objective realities when it comes to the relative merits of different programming paradigms.

    Or perhaps this wasn’t you were saying and I’m misreading what you wrote. :)

  8. Tim Docker :
    > facts:
    >
    > Dynamically typed languages are more expressive
    > than corresponding statically typed ones, because
    > statically typed languages forbid you from expressing some ideas.
    This is not a clear cut fact to me. Whilst it’s true that statically types languages (STLs) forbid you from expressing some ideas allowed in dynamically typed languages (DTLS), it’s also the case that STLs let you express ideas about the _types_ of values that cannot be expressed in DTLs.

    Not just that – Dynamically-typed languages are provably a subset of statically-typed languages. Pierce proves this in TAPL. Essentially, every type in a dynamic language has one tag in a giant tagged union, and you only pass around values of that giant tagged union type.

    This is all orthogonal to “expressiveness,” the subjective measure of the ease of expressing an idea.

  9. Like others, I think you take the point too far. Of course, that is what one does on blogs to make a point isn’t it. So, I think I shall acknowledge your point anyway.

    You are right that we spend too much time trying to one-up each other and either trumpeting the “one true way” or mocking the poor souls who have not seen the light. We would all be better off learning from each other and showing what is possible in a positive way.

    @Isaac – If you respond to a post about being more open and reasonable with self-congratulatory contrarianism then you are a wanker – so we should reject the conclusion.

  10. Measure Productivity, everything else is subjective or irrelevant.

    Turing equivalence undermines ‘X is more Expressive than Y’ as both X and Y are equally expressive languages. It is possible to talk in limited terms about “Ease of Expression” for different sets of users, but again once someone gains an understanding of an odd paradigm they soon become habituated to this new mode of thought and start evangelising its benefits to anyone they can get to listen to them.

    “By relieving the brain of all unnecessary work,
    a good notation sets it free to concentrate on more advanced
    problems, and in effect increases the mental power of the race.” – Alfred Whitehead

    “I have regarded it as the highest goal of programming
    language design to enable good ideas to be elegantly expressed.” – Peter Landin

    “Science is what we understand well enough to
    explain to a computer. Art is everything else we do.” – Donald Knuth

    “Point of view is worth 80 IQ points.” – Alan Kay

    Note: a language notation does not need to be ‘Easy to Learn’ if it adopts patterns that its users are already accustomed to – hence: traditional mathematical notation is superior to LISP (prefix some (thing)) and verbs should precede objects in English style scripts rather than the more Germanic O.f(x) crap we’ve had thrust upon us, but it doesn’t end there as Language Oriented Programming has shown that it is worthwhile to develop a notation, in which concepts can be captured, that can be used by domain-expert users themselves to directly model the important aspects of their business. At worst this approach forces both client and programmer to communicate properly – even if the only result is a prototype.

    It doesn’t matter to me whether OOP = REUSE; is the most preferred route to REUSE, etc.

    My point is that REUSE is a false goal.

    I feel that all the effort that is being spent on designing class taxonomies for future adaptation or wholesale reuse is dubious. Not for any computer scientific ‘formal’ reason, but simply because thinking about how your code should be to suit a future unspecified project on the off-chance that you will be in a position to find that code again and use it, more or less, immediately (thus justifying your extra design effort) is a tragic waste of development time. Programming is hard enough as it is without software developer’s having to be distracted about the goal they are persuing. Solve the immediate problem in the current project and forget about future reuse.

    I have read interesting things lately about XP (Kent Beck’s extreme programming) and I feel that the culture of REUSE (which is one of the main advertisments for OOP) is a symptom of poorly designed programming languages. C, C++, Java and C# all have a syntax that dates back to about 1972; C++ can justify it’s C syntax on the grounds of backwards compatiblity, but the other two have no such excuse.

    We need to make our code clear, concise and comprehensible, but our languages aren’t helping us do so. If code was easier to read and write then it follows that it would be easier to ADAPT and re-write. We don’t really need OOP abstractions as much as we need flexible language syntaxes. I think programmers like the IDEA of reuse because it promises to compensate them for all the time they have wasted expressing themselves through the awkward syntax of their programming language. I feel it would be better to trade this unquantifiable potential benefit for rapid development. We need protoyping languages that can be tuned-up to work as final implementation languages once the required optimisations are known.

    P.S.

    I recommend that you lurk at http://lambda-the-ultimate.org/ and stop wasting your time on a bunch of self-identified ‘twits’.

  11. @Justin – Is your name-calling response in a discussion you say is “about being more open and reasonable” supposed to be knowingly ironic?

    This post describes itself as being about “a style of argument”.

  12. @Isaac, I was hoping that the obvious ridiculousness of my statement would encourage my readers to generalize to my larger point. Haskell is the easiest language to learn because I already know it — thus, languages similar to Haskell are easier to learn because they are similar to something I know, etc. We are not blank slates, we learn by connecting to our prior knowledge; ease of learning is *highly* relative.

    @Paul, hmm, I said “all of your ‘objective’ judgements about one of these ultimately human languages are biased”. Yes, the word “all” was a bit strong; I don’t know where that came from. Maybe replace that last sentence with “consider that your ‘objective’ judgements about these ultimately human languages could be biased”.

    @Nicholas, I interpret your response as loudly proclaiming your values while presupposing that all programmers share them. Thank you for the clear example of the overarching point of my post.

  13. @Luke – the obvious ridiculousness of my statement

    Don’t say what you mean; don’t mean what you say – is a great way not to communicate ;-)

  14. “Easy” is the most overused and poorly defined term in programming. There is hardly a product demo or a conference presentation these days without a claim about something being “easy”. Of course, the exact wording varies: extensible instead of easy to extend or usable instead of easy to use. It is marketing vocabulary penetrating what is supposed to be an engineering discipline.

    Forget about computing for a second and think about a civil engineer claiming that building a bridge is easy. Do you have a clue what he means? Will it be quick? Will it cost little? Perhaps a pre-fabricated bridge will be floated in place by barge or a bridge will be made from barges tied together overnight? And easy compared to what? To an alternative bridge five miles upstream or to a bridge between Russia and Alaska across the Bering Strait?

    Scientists and engineers need precise terms to communicate. Salespeople and marketers on the other hand love to use warm and fuzzy words. In our industry these two worlds often collide, hence the kind of debates described in your post.

  15. I think ‘Reuse’ is better formalized in terms of Composition. I.e. the goal is to use a software artifact in a different context (a) without modifying it, and (b) without knowing its implementation details. Composition has three aspects:

    A set of composition operators (e.g. +, *, |, .).
    An set of operands that are closed under composition.
    A set of compositional properties that can be predicted inductively across composition operators.

    In general, we want a rich set of operators and compositional properties. This makes it easy to reuse code in new contexts and understand the consequences of doing so. Functional purity does offer some nice compositional properties. So does object capability model, though most OOP languages do not follow it.

    However, this must be balanced against achieving a rich set of operands, which allows our program to be used in a wider range of contexts. Domain specific languages, for example, are often very compositional but the operands are, well, specific to a domain. <a href="Purity constrains operands, especially with respect to distribution and concurrency, often to a point of being counter-productive.

  16. “Easy to Learn” seems a difficult property to pin down. It is a function not just of the language, but also of the entire community surrounding it. How good are the tutorials? How effective is the documentation? What about the quality of the IDEs, or compiler-generated error statements? Are there ravenous geeks on StackOverflow just waiting to pounce on your questions?

    And, yes, it’s also a function of the user.

    But I believe there is a more important property: that the “intuitions” we achieve are actually valid and useful. This isn’t a matter of ‘easy to learn’ so much as ‘learning right and useful things’.

    OOP does poorly here. There are many ways to ‘understand’ any given real world object – but the same cannot be said of OOP objects. The intuitions we bring to programming with objects are not valid. A lot of new OOP developers start each project by writing a simulator (where most objects represent entities in the real world – people, places, tax documents), and eventually finagle it into a data and control flow system (where most objects represent program entities – queues, threads, messages, subscriptions, connections, functors).

    Unlearning the wrong lessons then cracking open a GoF book to learn the right ones seems a phenomenal waste of productivity.

    It seems a lot of concepts widely used in FP are not initially intuitive – monads, comonads, iteratees, categories, Kleisli arrows, etc. But there is a nice property here that, once we learn these concepts, we rarely need to unlearn them. The intuitions they offer are ‘valid’, protected by composition laws.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s