Blogged by Ujihisa. Standard methods of programming and thoughts including Clojure, Vim, LLVM, Haskell, Ruby and Mathematics written by a Japanese programmer. github/ujihisa

Monday, January 7, 2013

Day 4 -- JavaScript in a week

previous post <-> next post

I accidentally started playing SimCity3000 and it ate big amount of my time..

return

https://github.com/ujihisa/jinaw/commit/2dbc9ed0b3240d9081932c5a519a9767a3763ee4

return is the only one feature to cancel executing the rest of statements, since there's no try/catch exception handling in this subset. Since the run- function to sequentially execute statements isn't something like a loop but an explicit recursion, to implement return, just simply don't recur.

(run '[(var f (function []
                        [(fcall 'console.log [1])
                         (return 9)
                         (fcall 'console.log [2])]))
       (fcall 'console.log [(fcall 'f [])])])

This outputs 1 and 9 but not 2.

typeof

https://github.com/ujihisa/jinaw/commit/c499b1bc23a11799ffe119d8a974729c6936c4ad

JavaScript has a unary operator typeof to tell the type of a value/variable-name.

> typeof 1
"number"
> var x = 1
> typeof x
"number"
> typeof y
"undefined"

Since typeof isn't a function it has more power than functions; it also accepts undefined variables without throwing ReferenceError.

(run '[(fcall 'console.log [(typeof 1)]);=> "number"
       (var x 1)
       (fcall 'console.log [(typeof x)]);=> "number"
       (fcall 'console.log [(typeof y)]);=> "undefined"
       (fcall 'console.log [(typeof (fcall '+ ['x 2]))])]);=> "number"

==

== is one of the most difficult aspect of JavaScript. The behavior is too tricky to understand.

> 1 == ['1']
true
> [] == []
false
> [] == ''
true
> 1 == true
true
> 1 == 'true'
false
> '1' == true
true

According to specification, the definition of == is

If the two operands are not of the same type, JavaScript converts the operands then applies strict comparison. If either operand is a number or a boolean, the operands are converted to numbers if possible; else if either operand is a string, the other operand is converted to a string if possible. If both operands are objects, then JavaScript compares internal references which are equal when operands refer to the same object in memory.

Well, I couldn't clearly understand it. What if one operand is a number and the other is a boolean? What is an operand is a number but the other operand isn't possible to be converted? They aren't written.

I gave up and made one that works fine for now..

(run '[(fcall 'console.log [(fcall '== [1 1])]);=> true
       (fcall 'console.log [(fcall '== [1 2])]);=> false
       (fcall 'console.log [(fcall '== ["1" 1])]);=> true
       (fcall 'console.log [(fcall '== ["1" 2])]);=> false
       (fcall 'console.log [(fcall '== ["1" "1"])]);=> true
       (fcall 'console.log [(fcall '== ["1" "2"])]);=> false
       (fcall 'console.log [(fcall '== ["aaa" "aab"])])]);=> false

[]

https://github.com/ujihisa/jinaw/commit/8878e40f5a21f8a79067aa822d088db12cb87029

[] is a unary operator for objects. Note that "object" is a hash-map or an array in JavaScript terminology. I named it as aref borrowed from Ruby's parser which means array ref, since Clojure doesn't recognize '[] as Symbol but as vector. To distinguish it with user-defined something which name is aref, I named it as -aref.

(run '[(fcall 'console.log [(fcall '-aref [{"0" "a" "1" "b" "2" "c"} 0])])]);=> "a"
(run '[(fcall 'console.log [(fcall '-aref [{"0" "a" "1" "b" "2" "c"} "1"])])]);=> "b"
(run '[(fcall 'console.log [(fcall '-aref [{"0" "a" "1" "b" "2" "c"} 3])])]);=> "undefined"
(run '[(fcall 'console.log [(fcall '-aref [{"0" "a" "1" "b" "2" "c"} "4"])])]); => "undefined"

No comments:

Post a Comment

Followers