Primitives vs. Objects, Ruby-like features
On Mar 24, 2008, at 7:43 PM, Darryl wrote:
In current versions of JS there's some weird stuff where some primitives are equal to their object equivalents:
1 == new Number(1)
Use === for identity testing.
But in other cases they're not equivalents at all:
typeof(1) == "number" typeof(new Number(1)) == "object"
typeof does not convert object to its default value, as == does.
And sometimes theres weird syntax errors:
5.prototype //parse error
As in almost all programming languages, the parser breaks up input
into tokens and favors the longest token at each step. So 5. is a
floating point number, short for 5.0. This is the same in Java, C, C+
+, etc.
Another example of longest token winning: i+++5, which is (i++) + 5.
function N(n){ return n } N(5).prototype //== Number, wtf?
What did you expect? Same as 5..prototype or (5).prototype or
(5.0).prototype or ....
The ship sailed on these long ago, almost 13 years since the birth of
JS, over 12 years since Netscape 2, 11 years since ECMA-262 Edition 1.
But the all important problem with your argument, Brendan, is that Ruby manages to allow 5.0 to be a float, and 5.times to be a method call, without any ambiguity. If Ruby can do it, why can't JavaScript?
o/// Be seeing you...
____________________________________________________________________________________
Be a better friend, newshound, and know-it-all with Yahoo! Mobile. Try it now. mobile.yahoo.com/;_ylt=Ahu06i62sR8HDtDypao8Wcj9tAcJ
I'll grant you one thing tho: Ruby requires "99.0" where JS allows "99.". To be honest, saving that one character when making whole-number valued floats (which are indistinguishable form NON floats, i.e. 99 == 99. == 99.0), at the expense of being able to do 99.abs or something like that, is absolutely insane. The dot adds nothing because without it you get the same value, and with it all you need is a trailing 0 to be semantically equivalent. There's no good reason to have the dot as part of the spec for floats at the expense of being able to use methods directly on numbers.
o/// Be seeing you...
____________________________________________________________________________________
Never miss a thing. Make Yahoo your home page. www.yahoo.com/r/hs
I'd also point out that 5..prototype doesn't work, even tho "5." is a float, and therefore this should be valid syntax. That hanging dot pointless, AND inconsistent. This could just be implementation wise, ofcourse.
o/// Be seeing you...
____________________________________________________________________________________
Looking for last minute shopping deals?
Find them fast with Yahoo! Search. tools.search.yahoo.com/newsearch/category.php?category=shopping
On Mar 24, 2008, at 8:16 PM, Darryl wrote:
But the all important problem with your argument, Brendan, is that Ruby manages to allow 5.0 to be a float, and 5.times to be a method call, without any ambiguity. If Ruby can do it, why can't JavaScript?
Please don't ask dumb rhetorical questions.
Obviously we could change JS incompatbily to match Ruby or another
language. Doing so risks breaking some web scripts. Therefore the
change had better be of high value, and in any case it must be done
only with "opt in" versioning. But calling methods on integers is
uncommon, so the value is extremely low.
On Mar 24, 2008, at 8:52 PM, Darryl wrote:
I'd also point out that 5..prototype doesn't work,
I'm not sure what you mean by "work". 5 is not a function so it has
no pre-defined 'prototype' property. The result of 5..prototype is
therefore undefined (the undefined value), per ES3.
On Mon, 2008-03-24 at 19:43 -0700, Darryl wrote:
It'd also be nice to have non-mandatory function call parens like in Ruby
No it wouldn't. Functions get passed around a hell of a lot more in Javascript than they do in Ruby, which means that you'd need to rely on something akin to Ruby's Object#method(symbol) function all the time.
...and to have blocks-as-objects like in Ruby. Both of these things make Ruby delightfully easy to read.
Would JS2 special case the last argument to a function like Ruby does? Ruby's block syntax is nice, but it's not without its problems. Take for instance the fact that a method must be defined with the last argument prefixed by an ampersand if you'd like it to accept a block.
As you said, you could emulate the Ruby iteration pattern by doing the following:
Number.prototype.times = function(func) {
for (var i = 0; i < this; i++ ) {
func.call();
}
}
Number(5).times(function(){ alert("Foo!"); });
I don't see this as a problem, and that's coming from someone who develops with Ruby/Rails, Javascript & Actionscript 3. If you want to write as much as possible in Ruby, you can always go the post-processing route.
Cheers,
-- Nathan de Vries
Darryl wrote:
And sometimes theres weird syntax errors:
5.prototype //parse error
Just put a space before the dot if you want to get a property of the wrapper of the number 5:
5 .property
There are other, about equally useful scenarios where you need to insert spaces to lex tokens the way you want:
x//regexp/ should be expressed as: x/ /regexp/ so it doesn't look like a comment.
Waldemar
On Mon, Mar 24, 2008 at 9:43 PM, Darryl <psygnisfive at yahoo.com> wrote:
typeof(1) == "number" typeof(new Number(1)) == "object" [...] Will these be made uniform in JS2?
No, it would be a pretty big breaking change from ES3. ES4 is considering several small breaking changes, but nothing this major.
I feel your pain though.
5.prototype //parse error
function N(n){ return n } N(5).prototype //== Number, wtf?
In Mozilla's JS engine, at least, N(5).prototype
here evaluates to
undefined
.
N(5).whatever
and (5).whatever
and 5..whatever
are all
identical, as Brendan said. I'm pretty sure ES3 requires this. If it
doesn't work for you, there's a bug somewhere.
Anyway, the syntax error on "5.prototype" seems impossible to fix without breaking compatibility. Consider:
var x = 5.e6; // exponential notation or property lookup?
I like some things about Ruby, but language design isn't a matter of collecting all the language features you like. It's ok for ECMAScript and Ruby to be delightful in different ways. Adding some Ruby-like syntax to ECMAScript could surely be done, but it would radically change the feel of the language. I think most JS users would be dismayed.
The problems solved by Ruby's flexible syntax and Ruby blocks might be addressed in ES5 (or later) by a macro system. We'll see.
In current versions of JS there's some weird stuff where some primitives are equal to their object equivalents:
1 == new Number(1)
But in other cases they're not equivalents at all:
typeof(1) == "number" typeof(new Number(1)) == "object"
And sometimes theres weird syntax errors:
5.prototype //parse error
function N(n){ return n } N(5).prototype //== Number, wtf?
Will these be made uniform in JS2? I would think that all numbers should be Numbers, with addressable methods like any other literal object. This would be very convenient, because then we could have Ruby-like methods such as times.
It'd also be nice to have non-mandatory function call parens like in Ruby, and to have blocks-as-objects like in Ruby. Both of these things make Ruby delightfully easy to read. Consider this in Ruby:
5.times { puts "Foo! " }
which outputs "Foo! Foo! Foo! Foo! Foo! "
to do similar in JS, you need either
for(var i = 0; i < 5; i++ ){ alert("Foo!") }
or you need to something like this:
N(5).times(function(){ alert("Foo!") })
which, if we had the above suggestions in place, could instead be
5.times { alert("Foo!") }
JS already has blocks as .. "things", theoretically, but not addressably so. Surely having block objects would be plausible.
I'm sure this can be achieved. Ruby manages with fairly similar syntax as JS, in many . It even has similar hash notation: { foo => bar, baz => quux }
instead of { foo: bar, baz: quuz }, so having block objects wont conflict there. The only possibly conflict I can imagine is between
foo(n){ ... } as the argless foo returning a function that takes a block with block-arg n, and foo(n){ ... } as a function taking a single arg n and returning a function that takes a block as an argument. This, i think, can be handled by doing arg-number checking on foo: if it takes 0 args as defined, then it's foo( (n){ ... } ), but if it takes one or more args then its (foo(n))( { ... } ). Perhaps to avoid confusion, Ruby-like blocks can have block args specific differently, like ruby block args: { |x| ... } instead of (x){ ... }.
Having other ruby-like features ( object/hash args not requiring {} in the right contexts) would be very cool too. It'd be nice to be able to do
foo bar: 5, baz: "a"
instead of
foo({ bar: 5, baz: "a"})
Obviously this would have to have similar restrictions on where it can appear just like ruby's version, but still.
I know, I'm a Ruby whore, but you gotta admit, ruby has delightfully easy-to-read syntax and easy-to-read is easy-to-code.
o/// Be seeing you...
Never miss a thing. Make Yahoo your home page. www.yahoo.com/r/hs