Hacker News new | comments | show | ask | jobs | submit login

I can't take Katz' suggestions for JavaScript seriously. He desperately wants JS to be his blub (ruby) and doesn't seriously think about how to accomplish his goals with what the language provides.

> There are two very common problems here. First, this has changed contexts. We can fix this by allowing a binding as a second parameter, but it means that we need to make sure that every time we refactor to a lambda we make sure to accept a binding parameter and pass it in. The var self = this pattern emerged in JavaScript primarily because of the lack of correspondence.

Or, you could use Function.prototype.bind where it's needed. Only functions where an execution context is frequently provided should accept an execution context (as sugar, basically), and it's generally better to assume prudent use of bind(). But I guess I'm crazy.

He then proposes a wholesale change to function semantics in the language. There are no "acrobatics" performed if you want to return a value passed to forEach(). You just enclose a variable and assign from within the callback. Any experienced JS dev will tell you that the disadvantage of forEach() and relatives is not that you can't easily return, but rather, that you can't easily break. However, proponents of a functional style would argue that you should be filtering your list first so that you only have to deal with interesting values, and so that there is no need to break: If you need `break`, use for ()!

I mean, come on, this is the same guy who wrote a reopenClass function in Ember.js -- for a language with plainly open prototypes.

This is nothing but a post glorifying Ruby and bashing JS for not being Ruby. There are plenty of valid nits to pick with JS, but being unlike Ruby is not one of them.




If you need to break, the built-in way is to use every or some, not forEach.

Yes, Yehuda is a Rubyist and that colors his presentation. But let's rise above ad-hominem arguments. You invoke blub but your argument in defense of JS is pretty much blubby, where it doesn't miss something already in JS (some and every).

Shorter and/or better function or lambda syntax and semantics have been on the agenda for years. Just shortening 'function' is not enough. Various half-baked proposals having failed, last year I went through detailed design exercises for both CoffeeScript-inspired (Dart took some of that inspiration)

http://wiki.ecmascript.org/doku.php?id=strawman:arrow_functi...

and Ruby- (but really Smalltalk; also E)-inspired

http://wiki.ecmascript.org/doku.php?id=strawman:block_lambda...

The latter won on many technical points, even though it's not yet in Harmony. It may make it.

Briefly, arrows require a new grammar validation formalism (not LR(1) with special rules for ASI and lookahead restrictions), arrows leave users confused about when to use fat-arrow, and @jashkenas vouches "arrows or curly braces, not both". Blocks win by requiring no new standard parsing algorithm for validation, and more: for refactoring, iteration with built-in control effects (break/continue/return), and guaranteed |this| inheritance -- all owing to TCP.

BTW, Rust has Ruby-like blocks now.


"He then proposes a wholesale change to function semantics in the language."

He isn't proposing a change to how functions works at all. He is proposing the addition of blocks, which would not break any current functionality. And he isn't the one proposing it, he is endorsing Brendan Eich's proposal.

"This is nothing but a post glorifying Ruby and bashing JS for not being Ruby."

I don't think it is. He mentions that Javascript feels elegant for code with a lot of callbacks. He doesn't seem to be bashing js at all, just pointing out places where blocks lead to more straightforward refactorings than lambdas. Hammers vs. wrenches and all that good stuff. He's not asking that all the hammers be replaced with wrenches, he's just asking for the additional option to use wrenches when it would be better to use a wrench.

Blocks are a useful tool in the toolkit. Javascript is not a purely functional language so it's not like some functional purity would be violated. In fact, your proposed solution: "If you need `break`, use for ()!" is much farther from the functional mindset than blocks are.


He then proposes a wholesale change to function semantics in the language.

Actually, I linked to a proposal by Brendan Eich, the creator of JavaScript.

I mean, come on, this is the same guy who wrote a reopenClass function in Ember.js

JavaScript's open prototypes suffer from the inability to define a number of new properties at once using an object literal. reopen (not reopenClass), provides that functionality.

This is nothing but a post glorifying Ruby and bashing JS for not being Ruby

Nope. It's a post glorifying the correspondence principle, which Smalltalk and Lisp had before Ruby, and arguing that JS would be better with it.


...glorifying the correspondence principle, which Smalltalk and Lisp had before Ruby...

But Lisp doesn't need two different kinds of lambda (at least neither Common Lisp nor Scheme has anything like that).

I'd be interested to know exactly what about JavaScript forces it to need blocks to obey the CP, when Lisp doesn't need them - I haven't quite wrapped my head around that yet. Is it just the problems with 'return' and 'this'? Could that be fixed by instead adding Common Lisp's 'return-from', and fixing 'this' somehow, instead of by adding blocks?


Well, it does need two kinds of lambda, in a sense. In Lisp, something like with-file would be a macro, which solves the same problem that "blocks" are solving here.


Also, Lisp has (return-from) which lets you do a non-local return by specifying which enclosing function to return from by name.


In Common Lisp, LAMBDA doesn't automatically define a return point; you have to use BLOCK NIL (or some macro (like DO or LOOP) whose expansion includes a BLOCK NIL) in order to be able to use RETURN.

  > (defun foo ()
      (block nil
        (funcall (lambda () (return 3)))
        4))
  FOO
  > (foo)
  3
So the problem is that JavaScript's `function' always creates a return point.


Your example does not make much sense, because you can return-from foo in lambda, without enclosing it in a block.

The solution proposed by OP (distinguishing "lambda" callables from "block" callables) is in my opinion misguided, because it only solves a problem partially, in a confusing way and creates new, unnecessary entities. The return-from mechanism is simpler and more intuitive.


> Actually, I linked to a proposal by Brendan Eich, the creator of JavaScript.

Naming names doesn't change the idea: It is surely a wholesale change to function semantics in the language.

> JavaScript's open prototypes suffer from the inability to define a number of new properties at once using an object literal. reopen (not reopenClass), provides that functionality.

Sure, that's why you use a general-purpose merge function, prototypes just being objects themselves.

  var merge = function(o, o2, force) {
      for (var p in o2)
          if (o2.hasOwnProperty(p) && (!(p in o) || force))
              o[p] = o2[p];
      return o;
  };

  var C = function() { /* ... */ };  
  merge(C.prototype, {
      foo: function() { /* ... */ },
      bar: function() { /* ... */ }
  });
In any case a name like reopenClass() sounds very much like an attempt to make JS smell like Ruby even if all the function does is perform a merge.


  I can't take Katz' suggestions for JavaScript seriously.
  ...
  Naming names doesn't change the idea.
I’m confused! Are we judging ideas by the source or by their merits?


He named a name rather than challenge the suggestion ... I named a name to show that I am noticing a common quality in Katz' recent foray into JavaScript, that being his desire that it be like Ruby, the language for which he's best known.


That's not what happened. You started out with "I can't take Katz' suggestions for JavaScript seriously." and he pointed out that it wasn't his, but Brendan Eich's proposal.

To which you answered "Naming names doesn't change the idea."


For what it's worth, I've been writing JavaScript for longer than I've been writing Ruby, and have contributed rather extensively to JavaScript libraries over a number of years.


And when you look at the Ember source this is basically what reopen is doing.

But (!) writing

  C.reopen({
    foo: function() { /* ... */ },
    bar: function() { /* ... */ }
  })
instead of

  /*window.*/merge(C.prototype, {
    foo: function() { /* ... */ },
    bar: function() { /* ... */ }
  })
makes for easier reading, which is worth a lot in my opinion.

It's the same as Cocoa providing -[NSMutableArray removeLastObject] in addition to -[NSMutableArray removeObjectAtIndex:] and -[NSMutableArray length]

Sure you can express one with the other, but readability matters.


"""Naming names doesn't change the idea"""

Oh, but it does. First, it shows that you didn't understood what you read (re: who wrote the proposal).

Second, it shows that the thing that you deemed as unfit for the language is considered as fit by the VERY CREATOR of said language.

"""It is surely a wholesale change to function semantics in the language."""

So what, if it's needed?


He's really just complaining about JavaScript's lack of a non-local return which cripples the ability to use lambda's to create your own control structures in many cases.


> This is nothing but a post glorifying Ruby and bashing JS for not being Ruby.

People would like JavaScript to be more like Ruby, idiomatic Perl 6 resembles Ruby… Maybe we need a new law: «widely used programming languages are modified until they resemble Ruby». :)


> «widely used programming languages are modified until they resemble Ruby»

This is an interesting observation, and it has echoes of Greenspun's Tenth Rule. I'm not sure exactly how true the statement is, but I suppose it used to be (or still is?) the case that the same thing could've been said with C in place of Ruby.


Everything's converging towards CLispScript: http://www.jerf.org/iri/post/2908


Ah, yes. Jerf's CLispScript Principle of Descriptive Programming Linguistics: Any sufficiently popular language contains as many practical features as possible with a C++esque syntax bolted on, and is approximately the same as contemporary sufficiently popular languages.

It should be noted that sufficiently popular languages incorporate as many buzzwords and design patterns as possible, which I suppose can be accounted for as 'features'.

(Excellent article, by the way).


I personally believe (hope) that all languages try to become Smalltalk. :)


And Ruby resembles Perl and Smalltalk.

I like it, but I stick with Perl because it adds the OO stuff with Moose and being an older project has made more mistakes that have been fixed. Oh and CPAN of course,

Still telling people to either learn Ruby, if they want to get up to speed quickly. Else I tell them to learn Perl. It's a bit harder to learn, but easier to use. Well for some people (linguists, etc.) Perl is easier to learn too.


If you're calling Ruby "blub" in comparison to JavaScript, I think you completely missed the point of what blub was supposed to be in pg's original essay.

On the contrary, you seem to be acting like a blub programmer looking up the power continuum and failing to understand the importance of Tennent's correspondance principle. You fail to see the importance of function(){ ... }() being equivalent to ...

Meanwhile, I look at JavaScript and go "how can anyone get anything done when 'this' is a painful violation of correspondance?"




Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | DMCA | Apply to YC | Contact

Search: