lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


I am currently learning _javascript_ and read this book, which I can recommend:

  _javascript_: The Good Parts
  Unearthing the Excellence in _javascript_ By Douglas Crockford
.

The book is quite good and I wouldn't say that _javascript_ and Lua are so alike - actually, they are quite different.

For example, falsy values:

<_javascript_> // I tested the _javascript_s using Firebug in Firefox
console.log(""==0);  // true
console.log("0"==0); //true
console.log("0"==""); //false

console.log(undefined==null); //true
console.log(undefined==false); // false
console.log(false==null); // false

console.log(" "==""); // false
console.log(" "==false);//true
console.log("\n\r  "==false); //true
</_javascript_>

Crockford says "The lack of transitivity is alarming" and I couldn't agree more - it really is.
Crockford recommends because of this behaviour never to use the == or != operators (the evil twins) but using _only_ === and !== which work like expected.

It would require quite some code to implement such a comparission check like this. But I would go for implementing functions that emulate _javascript_s behaviour, i.e.

<_javascript_>
assert(value == undefined)
assert(!((value < 0) || (value > 0) || (value == 0)))
</_javascript_>

to

<lua>
local jsops = {
    ["=="] = function (a,b) --[[ a==b js equal]] end
    ...
}
function js (operator)
    return assert(jsops[operator],"Unknown operator: "..tostring(operator))
end

assert(js "==" (value,undefined))
assert(!(js "<" (value,0) or js ">" (value,0) or js "==" (value,0))
</lua>

(btw, if this _javascript_ tries to check if a value for being not a number (the code looks like this), it will fail if value = "").

Another pitfall is the variable scoping, which is horrible in _javascript_:

_javascript_:

<_javascript_>
function valueofx () {
  alert(x);
}
var x = 4;
valueofx(); // 4
</_javascript_>

which is also why this doesn't work as intended:

<_javascript_>
var funcs = [];
for (var i=0;i<10;i++) funcs[i] = function(){return i;};

alert(funcs[4]()); // expected 4 but result is 10
</_javascript_>

The correct implementation would be

<_javascript_>
var funcs = [];
for (var i=0;i<10;i++) {
    funcs[i] = function(j) {
        // closure is keeping j - but not i!
        return function(){return j;};
    } (i);
}

alert(funcs[4]()); // expected 4 but result is 10
</_javascript_>

Then, the context for functions is passed in _javascript_ in a different manner.
For Lua, we know:

<lua>
foo = {}
function foo:bar ()
    -- self = hidden first argument
end

foo:bar() -- self = foo
foo.bar() -- self = nil
foo.bar(_G) -- self = global table
</lua>

In _javascript_, this is a bit different - and I haven't yet understood it completely - it seems to me like there are special cases I haven't yet figured out (or it works differently).

<_javascript_>
foo = {};
foo.bar = function () {
    // this = depends on function origin
    alert(this);
};
foo.bar (); // this == foo
foo.bar.apply(null,[]);  // this == global scope (window)
</_javascript_>

I would not use the metatable approach. I think this would make your Lua code working in a very different way than you would expecting it to work (i.e. in case of comparisions).

I think _javascript_ has some concepts in common - but some things are quite different.

Eike

2009/2/22 Duncan Cross <duncan.cross@gmail.com>


On Sun, Feb 22, 2009 at 2:03 PM, Duncan Cross <duncan.cross@gmail.com> wrote:

On Sun, Feb 22, 2009 at 12:34 PM, David Given <dg@cowlark.com> wrote:
You know how we (well, I) keep saying that _javascript_ has almost
identical semantics to Lua? Well, unfortunately that's not the case. I'm
trying to port a program in _javascript_ to Lua that's making extensive
use of some of these semantics and I'm not sure how to emulate them.

There's two so far that are biting me:

(a) the _javascript_ special values undefined and null are type compatible
with numbers, so (0 > null) is valid (and false)

(_javascript_)
assert(value == undefined)
assert(!((value < 0) || (value > 0) || (value == 0)))

As far as I know there's very little you can do about this except wrap every "if" condition and "and"/"or" operand in a call to this:

local function jstrue(n)  return (n and n ~= 0);  end

...ugly - and will also break if you want (a || b) to return zero when a is false and b is zero, as the conversion (jstrue(a) or jstrue(b)) will evaluate to false.

I'm sorry about this bit, I skimmed over what you said and responded in non-sequitur, talking about 0 evaluating to nil/false rather than the other way around. That's an even bigger problem - you cannot override the comparison of two distinct Lua data types, so even giving boolean and nil custom metamethods won't help.
 
-Duncan