notes-computer-programming-programmingLanguageDesign-programmingLanguageDesignNotes

note most of this file consists of text written by others, not me, copied here into my notes

"

pg 748 days ago

link

Occam's Razor suggests that the reason there is no dialect of Lisp as popular as less expressive languages is that no one happens to have created one yet. What languages are has changed. Languages used to be specs. Now they're open source projects. Open source projects seem to succeed based more on the energy of their initial organizers than anything else. There are only a few big language-project organizers, and none of them happens to have chosen to implement a language that is a dialect of Lisp. That's the sort of thing that's true until it's false. E.g. Clojure could be the counterexample.

Maybe there's more to it than a small sample size, but that seems the likeliest explanation. The second most likely explanation is almost as mundane: that the reason new dialects of Lisp have trouble attracting adherents is that mainstream programmers are put off by s-expressions.


abstractbill 748 days ago

link

What languages are has changed.

In fact, when it comes to choosing languages, I think things have changed even more. At justin.tv, we've chosen nearly all of the languages we use because of a particularly good library that each one has (Python, because of Twisted; Ruby because of Rails, etc). The actual features of the languages have been almost irrelevant. We would definitely jump on a Lisp dialect if it happened to have a great library we wanted to use.


"

pg 748 days ago

link

That is true to a degree. I agree with what abstractbill says, that libraries are the dominant factor in most people's language choices (after familiarity of course).


brlewis 748 days ago

link

Kawa Scheme makes it easy to call all the Java libraries, yet that hasn't made it huge yet.


abstractbill 748 days ago

link

FFIs just always seem to add some amount of friction. Stack traces, runtime error messages and documentation will all be referring to a language you're not using day-to-day, for example.


sesqu 747 days ago

link

When you look at lisp code, all you have to go by are the names of functions. The code could do anything, and you won't find out what until you dig. By contrast, other languages have hints like types and standard, well-understood libraries and restrictions on what might happen.

This suggests lisp code is less approachable for second authors, precisely because of its expressiveness.

" Clojure favours discrete components that do one particular job. For instance, protocols were introduced to Clojure to provide efficient polymorphism, and they do not attempt to do anything more than this.

Ruby is an object orientated language, and tends to favour grouping together a wide range of functionality into indivisible components. For instance, classes provide polymorphism, inheritance, data hiding, variable scoping and so forth.

The advantage of the Clojure approach is that it tends to be more flexible. For instance, in Sinatra you can write:

  get "/:name" do |name|
    "Hello #{name}"
  end

And in Compojure, you can write:

  (GET "/:name" [name]
    (str "Hello " name))

Superficially they look very similar, but their implementation is very different. The Sinatra code adds the enclosed block to a hash map in the current class, whilst the Compojure code just returns an anonymous function. The Clojure approach sacrifices some convenience for greater flexibility. For instance, in Compojure I can write:

  (context "/:name" [name]
    (GET "/email" []
      (str name "@example.com"))
    (GET "/greet" []
      (str "Hello " name)))

Because each route is discrete and independent of any larger construct, I can easily take routes and use other functions and macros to group them together.

I may be wrong, but I don't think there's an easy way of doing this in Sinatra, because routes are bound to a class when they are created. "

--

" You can replace all letters in a Java program with “x” and you’ll still be able to instantly guess the basic structure:

xxxxxx xxxxxxx xxxXxxxxx(xxx xxxXxxx) { xx (xxxXxxxx == xxxx) { xxxxxx xxxxx; }

    xxx (xxx x = x; x < xxxx.xxxxx; x++) {
        xxx[x] = xxxXxxx(x);
    }
    xxxxxx xxxx;}

" -- http://www.teamten.com/lawrence/writings/the_language_squint_test.html

---

guelo 748 days ago

link

Perl5 has had many OO libs but that has not helped. It is when the community standardizes on best practices and standard libs,such as DBI, that you get big advancements. Recent community efforts around "Modern Perl" and the Strawberry Perl distro are helping the language stay strong.

Another example is JavaScript?'s recent big leaps forward stemming from the community's embrace of jquery and the best practices from "JavaScript?: the Good Parts".

--

haberman 748 days ago

link

I agree that basic OO is easy, but inheritance (particularly multiple inheritance), virtual functions, RTII, etc. add significant complication.


randrews 748 days ago

link

It's more complication in design than implementation though, and doing it in Lisp instead of C won't help that any. Once you decide what you actually want to write, it's not a whole lot harder to write it in C than Lisp. It's harder, but it's still something that anyone who can do it in Lisp would be comfortable doing in C.

---

bergie 747 days ago

link

Lua is another great example of this curse because there's no module system or standard library to speak of

I think this, instead of syntax, is the main cause of fragmentation. The more strongly a language community recommends and bundles a module system and a package manager for it, the easier it is to build an ecosystem

---

ChuckMcM? 748 days ago

link

An alternative explanation is that Lisp doesn't have a person with a strong vision, program management skills, a thick skin, a diplomatic way to saying no, and a big ass repository.

The same argument is repeated throughout the essay, "Its not that Lisp doesn't have X, it has {X0,X1,..Xn)!" and that is the problem. Using lisp I get no or very low re-use for any code out there. Ergo I must write a lot of it myself. He recognizes it and laments:

"Look more closely: Large numbers of the kind of people who become Lisp hackers would have to cooperate with each other."

At the solution. But here is the rub, the qualities of the lisp user today are, in part, derived from how difficult it is to re-use code. People who could write anything they wanted enjoy the expressive power of lisp and tolerate the requirement to create from whole cloth basic things that should exist already.

Now posit a world where there was the Lisp equivalent of CPAN, and an aggressive authoritarian requirement on documentation, coding standards, and unit testing. Once sufficient mass had built up in this repository, even dweebs who don't know the difference between arrows and monads could use Lisp to make something useful, and they would take on the false mantle of 'lisp hacker' and the population of lisp users would swell and there would be still more things checked in and poof a thriving 'lisp' community, except it wouldn't look at all like the current community.


jleader 748 days ago

link

You make it sound like CPAN has "an aggressive authoritarian requirement on documentation, coding standards, and unit testing" (or at least that Lisp would need that to make a hypothetical LPAN successful).

CPAN definitely does not have that. What it does have are fairly strong social pressures in favor of those things, and extensive frameworks making it easier to provide those things (I'm thinking in particular of cpantesters.org providing free cross-platform unit testing support for all of CPAN).


gphil 748 days ago

link

This idea kind of reminds me of the notion that ideas are cheap, and that execution and hard work are what it really takes to create a valuable company.

It seems to me that the hard part of developing language features is developing the documentation and the tools, and it's this work that will drive language popularity much more than the features themselves.


---

Peaker 747 days ago

link

Familiarity is probably the prime factor in readability. And it is indeed a subjective one.

But there are also objective factors.

Infix function application allows for easier visual parsing of the expression tree's components. There's a reason mathematicians have been using infix notation for centuries before we had arbitrary other constraints for choosing notation.

In fact, if you look at mathematicians' notation, you will see that not only is it horizontally infix (arguments left and right of the function), it is also vertically infix, and arguments are placed above and below (Sigma, Integrals, etc.).


silentbicycle 747 days ago

link

People have come up with many rationalizations, but really, anything that doesn't have a mostly C/Java-style syntax just pisses off the majority of programmers.

When you look at languages that actually, consistently use infix and mathematical notation (http://nsl.com/k/ray/rayq.k), they seem to give most programmers fits.

Infix also only really works for unary and binary operators, of course.


forensic 747 days ago

link

since 99.9% of every language is in prefix notation i cant buy this.

when mathematicians type f(x,y) they are using prefix notations.

likewise when programmers type run(x, y);

Anecdotally, most advanced mathematicians prefer Lisp because it is more conducive to a mathematical way of thinking. I am a very mathematical programmer and I prefer lisp specifically because I don't have to deal with operator precedence. Everytime you use infix notation you introduce a bunch of unnecessary complexity and often you complicate the ability to use simple recursion.

Gregory Chaitin, eminent mathematician, writes his proofs in Lisp for a reason.

Is it truly easier to write

   print(a + " " + b + " " + c + " "); 

rather than

   (print a " " b " " c " ")

?

I greatly prefer the latter. The first one is weighed down with unnecessary special cases, unnecessary complexity.

The benefits of Polish notation are apparent with math as well. You don't need to reformulate the entire calculation and figure out messy operator precedence rules when you want to add a term. I think RPN lends itself to bug free code and easy modifiability.

To each his own I suppose. C-syntax to me is completely nonsensical and I don't see what problem it is meant to solve. I'm sure Russians view the Latin alphabet in the same way though.


Peaker 746 days ago

link

Mathematicians have few prefix functions. Most functions are infix and many in more than one dimension.

I think a statement like "Most advanced mathematicians prefer Lisp" is pretty extraordinary and demands extraordinary citations.

Your comparison was dishonest, as you compared manual concat and print with a function that concats and prints. You really meant to compare full infix (e.g: in Haskell):

    print $ a ++ " " ++ b ++ " " ++ c ++ " "

with full prefix:

    (print (++ a (++ " " (++ b (++ " " (++ c " "))))))

Which do you find more readable?

The anti-precedence notion behind putting () around each application requires parenthesis even when associativity laws show that there is absolutely no difference between difference precedence interpretations. In this sense, the () are pure noise in this example.

Of course, if you use ++ so many times, you'd prefer to just use (in Haskell) something like:

    print . intersperse " " $ [a, b, c]

Lisp's print has to embed the concatenation of its arguments or else it would look as horrible as shown above. It is still disingenuous to compare it as equal.


mcn 746 days ago

link

One consequence of the parenthesis and prefix notation is that n-ary operators are idiomatic in lisps. So, the above example would more likely be written:

(print (++ a " " b " " c " "))


Peaker 743 days ago

link

For flat expressions, prefix is fine, and using n-ary operators is a great way to flatten many trees. n-ary operators cannot flatten every tree, though. When your tree isn't flat, and is built from primarily binary operators, infix makes the tree structure more apparent. The way we would draw trees on paper is how it would appear in the infix expression.


jhuni 748 days ago

link

The beauty of Lisp is in its simplicity. Lisp has the simplest syntax in the world, and the entire language is based upon five simple primitives.

All other mainstream languages complicate matters with operator precedence tables, multiple operator notations (prefix, infix, postfix, postcircumfix, etc), and many other syntactic weirdities.

---

I remember writing a java library to do SNOBOL/Icon-style pattern matching in college because I hated the java way so much... every once in a while, I think about doing it again.

---

Steve Yegge's most recent post takes a right angle turn about a third of the way through, and begins a comparison of Emacs Lisp and JavaScript?.

And the winner is ... Clojure!

OK, Steve didn't say that. What he did do was call out things he liked about JavaScript? and Emacs Lisp.

For JavaScript?:

    momentum
    (namespace) encapsulation
    delegation (polymorphism?)
    properties (by Steve's definition)
    serialize to source

For Emacs Lisp:

    Macros
    S-Expressions

I first picked up Clojure looking for many of the same things that Steve wants. I found them. Clojure can do all the things on both lists above. (Serialize to source isn't formal yet, but check the mailing list. And of course, you will have to judge "momentum" for yourself.)

The scary thing is that Clojure wins the language war before you even learn about its signature features. When I started exploring Clojure, I quickly realized it had everything I wanted, which could be summarized as "Lisp that really embraces the Java platform."

Then Clojure changed the definition of what I wanted. Now I also want

    persistent data structures
    functional programming
    STM and agents

If you have half an hour, watch a compelling vision of what software development will look like in 2010.

---

bayle: a good way to keep up with some useful software:

http://www.sigplan.org/Awards/Software/Main