98 comments

[ 3.4 ms ] story [ 154 ms ] thread

  >> printIfNotNull(foo.getBar().getName()); // pointless method

  >> in arc ...
  >> ... aif is a macro that expands this code to
  >>
  >>(let it ((foo 'bar) 'name)
  >>  (if it
  >>      (print it)))
Why is a macro not pointless, while a method/function apparently is? I don't think that makes sense personally. Surely a macro is just a function that's been inlined - which may be better, depending on if you're optimizing for speed or size. Anyone explain?

Also, I'm not sure if this was being serious or not:

  >> Priorities in language design
  >> A Language Should ...
If it was serious, it completely depends on what problem you're trying to solve as to what priorities you're going to have.
Because aif works with any expression, not just print. Granted, in a functional language like JS, one could say:

    ifNotNull(foo.getBar().getName(), function (it) { print it; });
but "function (it)" and all of the "().{}" are still blub. As PG points out on the arclanguage forums [1], an even simpler way of putting it is:

    (only.print foo!bar!name)
Which, without the Arc-specific syntax sugar, is:

    ((only print) ((foo 'bar) 'name))
So "only" is a modifier that makes a verb (function) happen only if its argument is truthy (think Python decorators).

Note to PG: the dot operator is undocumented, and f.g.h.3 does not at all what I expect - looks like it does (f g h 3), whereas I expected (f (g (h 3))), in the spirit of Python decorators.

1. http://arclanguage.org/item?id=9350

In js, if printIt is a function already defined, you don't need the function(it){}

ifNotNull(foo.getBar().getName(), printIt);

Granted, in java passing functions around is more of a pain.

Yep, a lot of the features mentioned in the presentation are possible with just first class functions, although the syntax will be messier (but arguably more consistent).

The strength and danger of macros is in allowing you to create new syntax, skipping all the extra blub that made your code conform (consistently) to the original parser. What I'd like to know though is how much humans depend on that blub.

It's one thing to write your own macros and use them consistently, or even for a group of people to come up with macros and use them consistently. But if people work independently, what happens when you read someone else's code and find they've come up with macros to do the same things as yours do, but with different names and different usage conventions?

Wouldn't that be a bit like having every scientist invent their own jargon?

Either humans can learn to translate that kind of thing on the fly, or they can't, and lisp with heavy macro usage will only ever be useful as a solo (or small group) language.

Wouldn't that be a bit like having every scientist invent their own jargon?

I don't know about "all scientists", but mathematicians do precisely this all the time! Each paper and each textbook begins by defining what symbols mean what, and which terms are used how. But a textbook is about as big a consistent block of terminology as you'll be able to find. In a grander sense, terms are constantly re-purposed and evolving over time [1].

Something as simple as "⊂" will mean "subset" in one book, and "strict subset" in another. In my experience, the older the book, the more divergent it'll be from current usage. This suggests that the language of mathematics evolves over time, precisely because every practitioner can change the language and push for her own terminology. There is no "Mathematics corporation" which creates languages people would be forced to choose from - no mathematician, no matter how great, would suggest that he would know what the "eternally right way" of expressing mathematics is.

This is especially apparent in more exploratory parts, where definitions start being named after their authors. I, personally, look forward to a time when I get to choose between a Norvig-garbage-collection and Graham-garbage-collection for each object in my code.

We're in this ridiculous stage of software engineering, where, if you're using Java, you have to do garbage collection The Java Way (you get to set a couple of settings, but that's it). No mathematician would ever be forced to make the decisions that Sun's engineers were forced to make when designing Java, because nobody could make those decisions correctly - how programs must interact with the call stack, the mechanics of method invocation, etc.

1. "Compactification" comes to mind as an example: http://en.wikipedia.org/wiki/Compactification_%28mathematics...

what happens when you read someone else's code and find they've come up with macros to do the same things as yours do, but with different names and different usage conventions? Wouldn't that be a bit like having every scientist invent their own jargon?

You can replace the word "macros" with "functions" and your point would be the same. Consistency in naming and usage is part of good programming, but the point is orthogonal to macros.

Edit: actually, it's not orthogonal: macros make it easier to be consistent because they let you write less code, so there's less code to contradict itself.

macros can introduce new syntax, functions do not.
So? If you don't understand what a function does, you read it; if you don't understand what a macro does, you read it. This whole "macros make new syntax so they make code unintelligible" thing is an argument made by the ignorant, for the ignorant.

The vast majority of Lisp macros don't create new syntax anyway. They integrate seamlessly into the s-expression format. That way they blend in nicely with the rest of a program and it's easy to write other macros on top of them. An experienced Lisp programmer would only introduce new syntax when there is a big win in clarity - big enough to justify breaking with the surrounding structure and certainly big enough to make the above objection pointless.

By the way, one of the real problems with Lisp macros is that it can be hard to tell a macro call apart from a function call. (Various techniques have been developed to deal with this, such as indentation and naming conventions.) If macros were so syntactically convoluting this would hardly be an issue.

For the toy example, sure. But as soon as the example gets at all more complicated, you'll need to throw the function(it){} back in.

Also, it's worthwhile to remember that aif does a bit more - it's semantically the equivalent of cond, which sometimes eliminates a ton of if/else blub.

    (def only (f)
      (fn args (if (car args) (apply f args))))
The . and ! operators got redefined so that x.y.z is ((x y) z) instead of (x y z). I think I posted the source on arclanguage.org.
That's what I was wondering too. Almost all examples use macro. And for this one the argument that you need a temp variable to avoid redundancy is kind of moot since his macro use one too (I'm not familiar with the syntax so I might be wrong)
a macro can be pointless sure. mostly if the same thing can be accomplished with a function (most of the time, but not exactly). a macro is not a function that's being inlined.
Is this similar for all the dialects of Lisp? Because if it is, I might start learning one tonight.
The macro definition abilities is mostly similar for most popular lisps around, Common Lisp, Scheme, Clojure
I like the argument, especially using the word "blub" to describe the cruft that is inherent to the language, but I have to question how much it's preaching to the choir, and how much will penetrate people who don't already agree.

Maybe it's indicative of my crowd and not the community at large, but even the smartest people seem to hit up Haskell-for-fun and Python-in-practice over Arc. It's hard to call them blub-programmers, since they're genuinely curious, hard-working people...

Haskell-for-fun and Python-in-practice

I am in exactly that camp, tho' I do fully intend to use Haskell for real once it becomes viable to do so. It's like the Python Paradox all over again.

The point about string concatenation is, umm, I don't want to say "wrong" because wrong sounds argumentative so I think I'll pick a circumlocution like "contrary to fact" or "a bedtime story to scare CS101 students with, second only to 'use left shift instead of dividing by two, it is faster'".

Also in modern Java (and Ruby) projects you can typically write:

logger.debug("This is a stupidly expensive calculation: " + stupidlyExpensiveCalculation())

and it will get executed regardless and logged only if your logging settings, which are configured elsewhere and can be toggled with a mouseclick, are set to log the debug level.

Now, don't get me wrong, Arc's solution of defining a macro which checks to see whether your debug setting, which is defined elsewhere and can be toggled with a mouseclick, is on or not is a good idea. Its just not a revolutionary new idea for us wizened Big Freaking Enterprise App Ugly Language Programmers. Nor was it really that new in the halycon days of yore when Log4j crawled out of the primordial ooze.

Agree.

isDebugEnabled() method is used to scare people since 2001, probably around the time when it came out of common use.

Macro that is being used for exactly that is not a distinguishing feature of the language. Java proponents may come out with, say, accessing array in constant time (how many car/cdr pairs you need for that?)

Important is that neither of the described facts add something to the value of one language against another and usually serve only as a basis for speculation.

Edit: when I'm saying "went out of common use", I mean that elegant alternatives like

logger.log("Expensive calculation is going to be: {0}", objectWithExpensiveToStringMethod);

have emerged.

I am not sure if I understood you correctly, so let me check: Did you mean that stupidlyExpensiveCalculation() will be always executed, regardless if debugging is enabled?

Seems to me you say this like it's a good thing. Or I am misunderstanding...

The real problem is not the string concatenation, it is that stupidlyExpensiveCalculation() will evaluate, regardless of whether debugging is on or not (at least in Java, not sure about Ruby), since Java doesn't do lazy evaluation of arguments.

In this case, that just slows things down. Worse yet is when it is stupidCalculationWithSideEffects(). And I have seen that before. :(

The reason is that logger.debug(...) should really be

    logger.debug {
       ...
    }
Which can be done trivially in a language with convenient blocks/lambdas. Then the debugging expressions will not run at all with debugging disabled.

Yes, having a meta-syntax as your syntax is very useful.

If it takes X characters to achieve something in language A, and X*4 to achieve the same thing in BLUB, I don't think this means BLUB is 4 times slower to develop in than A.

When I develop software, most of the big delays, and excuses for procrastination are in forcing my brain into action over the higher level concepts. I find a lot of the extra lines of code required when using BLUB can be written at high speed, with little "hurt" to the brain.

I'm not saying BLUB is just as fast to develop with, I'm just saying the benefit isn't as good as number of lines ratio good.

I wonder. If it were only limited to the ratio of time required to type it, maybe.

But I think during the writing of the program, you type the code, review the code, look at some other code, come back to that code, so you are writing/editing/modifying a particular piece of code multiple times.

I have a superstition that there is an element of polynomial effect on the size of the resulting program on the time to get it working or to parse code written by another person.

For me, I have found that a more concise language is easier to think in and write in. I recently worked on an application that was implemented both on the web using mostly javascript and as a desktop application in VB.Net.

One of the more complicated features I waited to implement in the web version, just because I found it rather difficult to think of the problem in VB. The javascript code was just easier to write and think in, and once implemented I could translate it to VB.

Although I do not know if there is a limit to the benefits of moving to a smaller language. Also, this is just my personal experience and I do not know how much it generalizes to other people.

It's not in writing 40 lines that something like "blub" hurts, it's in reading it afterward. As long as you don't end up in Perl one liners, shorter code will tend to better highlight the relevant content (e.g., there are four keys that perform one of four things).
Code generation isn't as powerful as late binding. Lisps would be more interesting if you could easily manipulate environments, and set the environment that functions are evaluated in. In this regard, Arc isn't as agile as some OO languages (Io for instance).
I am curious what you mean about "easily manipulate environments" for the functions to be evaluated in.
Probably, something similar to JavaScript's call() and apply() is meant here.

Though classical Lisps all have funcall and apply (not sure about Arc).

call and apply only let you change the meaning of the this pointer in Javascript. You can't change the meaning of other bound variables. In Io, you can take a Block and set the scope:

  makeOriginalScope := block(name := "originalScope"; block(writeln(name)))
  block(name := "newScope"; makeOriginalScope call  setScope(thisContext) call) call
  //newScope
Does this mean that you can change the meanings of your language's "words" for specific "contexts?" (Context meaning the semantic thing, not a stack frame, though that could be the implementation.)
Yes. The meaning of symbols within a closure can't change after creation. They are always bound to the same variable.

In Io, the meanings of symbols are determined when the block is activated.

I'll have to take a look at Io. I was just thinking of making contexts into semantic contexts by having users specify what the verbs mean, not just the nouns.
Isn't this similar to dynamic scope?
Similar but not the same. With dynamic scope, the variable lookup is performed up the chain of environments that the function was called in. The only way that you can influence this is by calling the function within a certain scope, you can't explicitly set the scope so it isn't as flexible as Io's scope and it isn't as fast as the lexical scope of most Lisps.
Original blub code should look like that: frame.addKeyListener(new KeyListener() { public void keyTyped(KeyEvent event) { switch (event.getKeyChar()) { case 'j': drop(); break; case 'h': move(-1); break; case 'k': move(1); break; case 'u': rotate(); break; } }

      public void keyPressed(KeyEvent event) {
      }

      public void keyReleased(KeyEvent event) {
      }
    });
About Arc code:

    (on-key-press frame
      'u     (rotate-shape)
      'j     (drop-shape)
      'h     (move-shape -1)
      'k     (move-shape 1))
Is this code ADDS NEW key event handler OR OVERRIDES old one? When it is invoked - when key is PRESSED or when key is TYPED?
ah, events as function calls. How so terribly 50's.

here's a way where events are objects... rather than an invocation. Much more flexible.

a python + pygame example...

cu,

key_handlers= dict(u=rotate, j=drop, h=lambda : move(-1), k=lambda : move(-1))

buttons = {1:'u', 2:'j', 3:'h', 4:'k'}

for e in pygame.event.get(): if e.type == KEYDOWN: key_handlers[e.key]()

    elif e.type == JOYBUTTONDOWN:
        key_handlers[buttons[e.button]]()

    elif e.type in [QUIT, MOUSEBUTTONDOWN, HTTPD]:
        quit()
The grandparent code is much easier to understand.
The claim is Arc is agile and short... The Arc one has too many ()() all over the place.

The arc one is also less powerful, because it uses different function invocations for different types of events.

It's also likely more people will understand the python+pygame version. More people do currently understand the python version... hardly anyone uses Arc.

You need to understand non-common concepts. You also need to understand how to create functions - rather than just call functions.

Does that Arc one mean when the key down happens, or when a key up happens? Or maybe it means in between the key press and key down. Also, when will that code be called?

It's magic. Will it be called from a separate thread, or some other Magic time... before or after the screen is to be updated? What else is going on at that time in the program? With the Arc version you have no idea... it's not explicit.

Also Arc doesn't have first class events. It could have yes, but it doesn't.

ps. the python code above was mangled by the buggy Arc program running this forum.

Here is the code redone for simplicity without the extra shortness and power expressed in the other version.

.

for e in pygame.event.get():

    if e.type == KEYDOWN: 
        if e.unicode == 'u':
            shape.rotate()
        elif e.unicode == 'j':
            shape.drop()
        elif e.unicode == 'h':
            shape.move(-1)
        elif e.unicode == 'k':
            shape.move(1)
Or the declarative python version:

.

dict( u=rotate , j=drop , h=lambda:move(-1) , k=lambda:move(-1))

The arc one is also less powerful, because it uses different function invocations for different types of events.

Actually, that would make it more powerful. You can use polymorphism.

It's also likely more people will understand the python+pygame version. More people do currently understand the python version... hardly anyone uses Arc.

Missing the point. Conciseness is not best measured by eyes familiar with the language/library. It's best evaluated from the POV of the uninitiated. I have to parse and run a model to understand your first version. Your second version is as easily understandable as the Arc example in one way, but it's got a lot more pollution and an enforced higher line count.

I am answering as someone not well versed in either Python or Arc. (Actually a little more familiar with Python.)

Yes, most of the examples in the non-Arc language were written with artificial duplication, which obscures the actual advantages of Arc.

There's the `printIfNotNull(foo.getBar().getName()); // pointless method`, also pointed out by axon, and the following code being duplicated instead of being a function:

    if (log.isDebugEnabled()) {
      log.debug("foo.valueOf(expression) = " + 
        foo.valueOf(expression));
    }
BTW: heads up on your comment formatting: HN needs a blank line between text and code for 4-space indentation to be recognized.
I like this PG quote from slide 24 a lot:

   "One way to design a language is to just write down the program you'd
    like to be able to write, regardless of whether there is a compiler that
    can translate it or hardware that can run it."
Test driven really works, even for language development.
Can't do much without batteries.
I think it's impossible to have any kind of meaningful conversation about language design when one side is just writing off everything they don't like as "blub". It's incredibly condescending, no better than people reflexively writing off Lisp users as "lisp weenies".
Would it be as offensive to call the extra repetition that is inherent in some languages as "blub code", and languages like Arc trying to get rid of the blub(ber) in code?
I'd lean toward avoiding "blub" entirely; it sounds like you're implying their code (and brain) is full of mush. You're probably making a face like a fish blowing bubbles while you say it. Be civil!

As novel as this may seem, most people who regularly program in languages other than Lisp also consider excessively verbose code to be a bad thing. (Hence the interest in refactoring.) If you're dealing with someone who just started programming a few months ago, they don't have enough experience to know why it's problematic, but then, they probably need someone to be patient and helpful, rather than smug.

You can say, "There are some things that are inherently hard to express in some languages that come naturally in others, and until you have experience with a couple different styles of languages, you'll only really know techniques used in your main language. Learning new languages adds new techniques to your problem solving toolkit. It takes a while, but it'll make you a much better programmer in the long run.", and it doesn't make you sound like you're sneering inside.

If you want to make the point that the way their language's object framework is designed makes any nontrivial program in it have a bunch of repetitive boilerplate, say that. Name-calling makes people defensive, not likely to consider new ideas.

I can't tell if you're trying to be funny or not. If we want to make a point about how a language is better at letting us build useful abstractions, we have to spell out exactly what we mean by that every time, even though somebody has invented a word that macroexpands to exactly that?
It macro-expands to that, but there's an occasional variable capture bug that has the side effect of making one sound incredibly smug.
"Blub" is offensive, I agree. I've been bemused at the name-calling. It undermines the factual content and alienates adopters. Why do it? I wonder if an explanation is that name-calling simply isn't regarded as offensive within the community. For example, there's a development environment called "Slime"; and of course the name "Lisp".
Those aren't personal, though. The way "blub" is used is:

"You're writing in 'blub', therefore you're a 'blub' programmer, and all you're capable of understanding is 'blub'. Maybe some day you'll wise up and use my 'language for smart people' (LFSP)."

Yes you're right. I was trying to find a way to excuse them, and see them in a kinder light. But you're right. :-(
I hate to be "that guy", but I think you all might be misunderstanding the meaning of "blub".

Remember, "Blub" comes from the Blub Paradox (http://paulgraham.com/avg.html) in which one paradoxically believes that his or her language of choice (let's call it Blub) is the overall best language and that others are no good, usually due to missing some particular feature, or that they are too complicated.

An ironic example is that Paul Graham, who I believe is the creator of said paradox, asks rhetorically "If LISP is so great, why doesn't everybody use it?" and later, "I will say that LISP is at the top of the power spectrum." In effect, he's guilty of falling into his own paradox by assuming his language is at the top of the power spectrum, which is no different from assuming some other hypothetical language (that may have more capability than LISP) is too complicated.

I'm aware of where it comes from. The idea is that people who don't use lisp are so profoundly ignorant, that they don't even know they are ignorant. That's an offensive idea to start with. The second thing is that the word used to denote that concept, blub, is itself offensive, and it's used in an offensive school-yard way ("blub programmer"). It's surprising to see people promoting arc with this approach.

But reading your post closely, you're saying that blub strictly only refers to people who believe their language is the best and others are no good. In the avg.html article, it also says "How can you get anything done in Blub? It doesn't even have y." and talks about people looking down on less powerful languages. Therefore, a person programming in Java (or assembly or whatever) isn't a blub programmer unless he believes that language is the best, that others are no good, and he looks down on less powerful languages (maybe a more accurate word for this attitude is "snob".) My experience is that most programmers don't do that.

Well that depends on Paul Graham's knowledge of other languages. If Paul Graham knows Lisp and only Lisp, perhaps he's falling into the Blub paradox when it comes to Prolog. But if Paul Graham knows Lisp, C, Smalltalk, and Cobol, and has all the necessary language concepts from those to understand Ruby and Perl even if he hasn't used Ruby and Perl extensively, then he's on decent grounds to claim that Lisp is more powerful than those languages.

The blub paradox comes from someone who only knows Pascal doesn't understand why you'd want classes or functional programming. (We're assuming he only knows classical Pascal, not Delphi.) It accounts for the resistance of C hackers to object oriented languages (as illustrated, rather passive-aggressively, in such books as Object Oriented Programming in ANSI C), the resistance of Java coders to first class functions (we have a design pattern for that! it's called "functor"!) and so forth. It doesn't apply to someone who knows Haskell criticizing Java for OO fetishism, or a Java programmer scoffing at Pascal for not having classes.

And the only place where I've ever read pg as critical of another language's abstractions is his remarks on Prolog. Now, that might be because he's fallen into the blub paradox, or maybe he has a good enough understanding of Prolog to authoritatively say it's only useful for 2% of problems and gets in your way the rest of the time. I can't read minds.

(comment deleted)
Perhaps Prolog isn't very relevant to the sort of problems Paul Graham works on? Much of Peter Norvig's _Paradigms of Artificial Intelligence Programming_ is about Prolog (and logic programming in general); he ultimately implements a Prolog engine in Common Lisp, because it's a more appropriate tool for the sort of problems he's dissecting.

I only know the basics of Prolog from PAIP and CTM (one of many things I hope to get into deeper over the summer...), but it seems like it would be incredibly useful, albeit within a very specific niche. I wouldn't try to write an OS in make, but that doesn't mean it isn't handy sometimes.

Undoubtedly there's a category of "languages" that, despite their power, are only really useful for a specific application (make, yacc, SQL, PostScript) distinct from more general purpose languages. Perl used to be in the camp of specialized languages (need to munge some text?) but now it's squarely a general purpose language.

I've always seen Prolog billed as a general purpose language. If it's intended as a special purpose language, then it doesn't even make sense to criticize it compared to Lisp or C.

Indeed. Yet I was also trying to illustrate (albeit unsuccessfully) how the language snobbery is basically the same thing--a failing to recognize a language for what it's worth. As you point out, languages often have specialties and are better suited than more powerful languages for certain tasks.
it sounds like you're implying their code (and brain) is full of mush

That might be how some people use it... heck that might even have been the original intention, but I'd still rather just use it to describe the extra code a language makes you write.

If you think about it, there is no name for that... you could call it "cruft", but that's usually used to describe unnecessary verbosity in a framework or library, not the language itself.

Not all language cruft is created equil. I find the more more that happens within a line the easer it is to write but the harder it is to read.

x = (a = 7 * (b = 14)) + (c = 9 * ((d > 7)? e:f));

Now toss in some casts and the line becomes harder to read, but at the same time it's considered poor from to have 4 assignments on one line. Yet that's valid C, C++, Java, C# etc and it's got fewer symbols so it must be better according to the arc view of the world.

So is reqiring one assignment per line cruft or a good idea? How about those assignments? I would argue that one of the most useful mesures of a language is how easy it is to read other peoples code, but then you end up with something like Pascal...

PS: I acutaly like mantaining pascal code more than most languages then again it could have more to do with the experence of the people who use Pascal.

That's one line, yes, but what a line! That's 20 tokens or so, many of which are weird and hairy (the ? operator, multiple assignments). And in Lisp style you'd have that as multiple lines anyway.
True, but my point is it's more tokens if you write it as several lines. a = b = c 2; vs b = c 2; a = b;

So token count is still not really what we want to measure even if it's better than line count.

"it's more tokens if you write it as several lines"

As several lines or several statements?

x =

____(a = 7 *

________(b = 14))

____+

____(c = 9 *

________((d > 7)? e:f));

Same statement, same token count, multiple lines.

Statments, that's in no way easer to parse than that some code on a single line. (Assuming you have collar coding for the ()'s in your IDE.)

  c = 9 * ((d > 7)?e:f);
  x = ( a = 7 * (b = 14)) + c;
IMO is not that bad, it's the mixing of all the assignments and the conditional that makes it hard to parse, and

  c = 9 * ((d > 7)?e:f);
  x = c + (a = 7 * (b = 14));
is fairly readable even if some of the ()'s are not needed.

PS: ;'s I thought it was clear that the ;'s denoted lines not the whitespace which is meaningless.

Semicolons do denote statements, but that doesn't prevent you from clever use of line breaks. I still think my version is more readable.
Edit: NM, reply is now working.

I just wanted to say that personaly I have tryed learn to ignore indention and other clues becasue it's far more costly to misunderstand what the code is doing than try and use hint's that may have become old over time. To paraphrase: in that way lay bugs that look like dragons.

I also tend to do the same thing with comments on the first pass though. It's only when I don't understand the code or or it looks "odd" that I start to notice the extras like that.

I can't reply to: "Semicolons do denote statements, but that doesn't prevent you from clever use of line breaks. I still think my version is more readable." for some reason.

I just wanted to say...

Edit: NM, reply is now working so I moved the comment.

(comment deleted)
Just because such code parses, it doesn't mean you should write that way. Rather than requiring a ludicrously dense or terse style, most real projects will just have fairly reasonable coding standards (whether formally specified or just commonly understood) and expect you to exercise good judgment.

Besides, I don't think anybody is really expecting you to cram as much into one line as possible.

The "blub" argument fairly applies just as much to Lisp as it does to, e.g., Java. For example, (any dialect of) Lisp is my blub language, as I understand Lisp quite well. I do not understand Haskell to anywhere near the same extent. I've tried to learn it several times, but monad transformers consistently make my eyes glaze over. I am perfectly comfortable admitting this, and I intend to try harder to understand programming language concepts with which I am unfamiliar, rather than write off Haskell advocates as condescending.
I get what you're saying, but I think dropping the "blub" term would make everybody better off. Using "blub" intrinsically frames the conversation in terms of one language being "the stupid one used by the stupid people", and that's likely to be counterproductive. The word always has that baggage.

It's not a linear continuum, with some "most powerful language" at the top. Different styles of languages have different strong points and weak points.

I think monad transformers are starting to do Haskellers up in knots, especially when there are many types of computations you want to do which are by necessity monadic in Haskell.

I, for one, find uniqueness types to be an easier to understand and use solution to the problem of maintaining referential transparency in the face of a stateful universe.

Care to suggest a short term that has the same denotational meaning without the connotations you dislike?
Anything Arc does better than Clojure that would be enough to offset the benefit of running on the JVM and full java interop?
A Clojure slogan could be "The Java De-Blubber!"
I believe it's called flensing.
I learned a new word today.
it's built on plt-scheme so Tail Calls are optimised
As much as it annoys me to be continually banned for minor transgressions (time_management, banned_man, et al) when 99% of this forum considered me a great poster, I have a lot of respect for Paul Graham, and I think Arc is a great language.

I use Clojure, because I'm at a 6-person startup that can't afford (yet!) to write its own libraries for certain cutting-edge functionalities available in the Java world, and the JVM provides a lot of benefits that are useful to us. But I think it's a tough call which of these competing new Lisps is a better language, and I'm glad they both exist because I think they have a lot to learn from each other.

A lot of the stuff presented here is mainstream practice in Tcl (e.g., new constructs, dbg evaluation). Tcl is seriously underappreciated language.

In my programming whenever I see myself writing blubber (I like that word), I just factor it out into a separate procedure and give it a descriptive name.

So when I'm reading the code of the calling routine, I rarely see blubber; it's contained in simple routines that are easy to read/verify.

Most of the examples here amount to thoughtful library development. With a good library, C++ and macro processor can also many of these things.

Here's a version of aif that works for most cases (I'm not claiming that C has the expressive power of Lisp):

    #define aif(expr, val, code...) \
      { if ((expr) != (val)) { \
          code ; \
        } \
      }
IMHO, this is good enough for blubber reduction.
That's not aif at all. In fact, you can't even do it for "most cases" in C because you don't know what type expr will evaluate to, but if we could cheat and assume it will be an int:

  #define aif(expr, code)  \
     {                     \
     int it = (expr);      \
     if (it)               \
        {                  \
        code;              \
        }                  \
     }
But this is still not close because in a Lisp, if is an expression that returns a value. We can't use the ternary operator because then there's no place to declare the "it" variable. You can't have an expression that declares a variable local to that expression in C no matter how hard you try.

And the above lacks the "do {} while (0)" weirdness needed to make a cpp macro behave syntactically roughly like a function.

I agree. My bad. I appreciate the clarificaiton.
This presentation could have been about Clojure instead. Just s/Arc/Clojure/
From the slides, it looks like Arc dumps lots of short words in to one giant global namespace where they can easily collide with local names. Is this correct?

For example, it looks like Arc uses the "t" as a global true value. Is it really safe to assume "t" wouldn't be accidentally used as a local variable?

Well, T has been the true value in Common Lisp, at least, and I don't remember it ever causing me a problem. Of course, in CL, you can shadow it in your own namespace, and that hasn't been possible in Arc without writing a namespace library first. :)