@kyanny's blog

My thoughts, my life. Views/opinions are my own.

JavaScript Weekly issue 221

操作を誤って公開済みの記事を削除してしまった。 morrita さんのコメントまで消してしまった。申し訳ありません。

JavaScript Weekly Issue 221: February 27, 2015


長いし ArrayBuffer とか疎い話題なので半分くらいで挫折。
これについて morrita さんからいただいたコメント(はてなブログのコメントお知らせメールに本文が残っていたのでここに貼り付けておく)

PJS: ArrayBuffer はさておき、かっこいい並列APIを考えるよりは、かっこいい高レベルAPIを作れる低レベルなAPIすなわちスレッド間のメモリ共有とロックを定義しましょう、さすれば JS の世界で後腐れなく試行錯誤できるようになるからよい、という話ですね。


最初の回答しか読んでない(Reddit だし)が十分言い尽くされているような…最近「AltJS はふつうのWebデベロッパが JavaScript を理解するための梯子(あるいは補助輪)だったのではないか」という思いが頭を離れない。

レベルの高い環境に身を置くことの是非

「レベルの高い環境に身を置く」をよしとしてきたが、よくわからなくなってきた。

周囲のレベルが高いということは相対的にみて自分のレベルが低くなるということで、それは自分が「頼りにならない・役に立たない」人材と化すことを意味する。自分は使えないやつなんじゃないか、という疑念を抱きながら過ごすというのは非常に強いストレスを感じる。

例えば、自分以外全員英語ネイティブか帰国子女か TOEIC 950 点以上か、というくらい周囲が英語に達者な環境で、英語のドキュメントや StackOverflow にはおじけづきません程度の英語力だったとすると、相当レベルが低いということになる。日々必要とされる英語力は十分まかなえる実力があったとしても、周囲のレベルが高いがゆえに満足も安心もできず、劣等感に押しつぶされないように自分を鼓舞し続けなければならない。

モチベーションは長期的にみれば枯渇することはないが、水道のように蛇口をひねっていつでも望む強さで出力できるようなものでもない。モチベーションが維持できている間は、レベルの高い環境は向上心を保ち努力を継続させるためにちょうどよい負荷となるが、負荷に耐えられなくなると仇となる。

自分がレベルアップし続けるために選んだはずの環境が、むしろ自分の意気を削いでいるとしたら、いったいなんのための選択だったというのだろうか。

ES6 Generator と Ruby の Fiber と Python 2 の generator

CodeGrid で ES6 Generator の記事を読んだ。

ECMAScript 6の新機能 - Generator | CodeGrid

Ruby の Fiber のようなものなのかな、と思って書き比べてみたら少し違うところがあった。

function* generatorFunc(a) {
  console.log(a);
  var b = yield 1;
  console.log(b);
  var c = yield 2;
  console.log(c);
}

var generator = generatorFunc('a');
console.log(generator.next('b'));
console.log(generator.next('c'));
console.log(generator.next('d'));

この結果は

$ node -v
v0.12.0
$ node --harmony generator.js
a
{ value: 1, done: false }
c
{ value: 2, done: false }
d
{ value: undefined, done: true }

ES6 Generator では初回の next() 呼び出しに引数を渡しても捨てられてしまう(ように見える)。そういうものなのだと CodeGrid の記事にも書いてあったし、初回の next() に渡した引数を利用する方法もドキュメントには書いてあるのかもしれないが、 Ruby の Fiber だとそういう振る舞いにならなかった。

generator = Fiber.new do |a|
  puts a
  b = Fiber.yield 1
  puts b
  c = Fiber.yield 2
  puts c
end

puts generator.resume 'a'
puts generator.resume 'b'
puts generator.resume 'c'
puts generator.resume 'd'

これの結果は

$ ruby -v
ruby 2.2.0p0 (2014-12-25 revision 49005) [x86_64-darwin14]
$ ruby generator.rb
a
1
b
2
c

generator.rb:12:in `resume': dead fiber called (FiberError)
        from generator.rb:12:in `<main>'

最後の resume で例外になるのはいいとして。同じような機能のように思えるのに、同じように作られていないのはなぜなんだろう、と不思議に感じた。


2015/03/06 追記

Python にもジェネレーターってのがあったよなと思って書きくらべてみたらいろいろ勉強になった。

$ python -V
Python 2.7.9

next() に引数を渡すことができない。

def generatorFunc(a):
    print a
    b = yield 1
    print b
    c = yield 2
    print c

generator = generatorFunc('a')
print generator.next('b')
print generator.next('c')
print generator.next('d')
$ python generator.py 
Traceback (most recent call last):
  File "generator.py", line 9, in <module>
    print generator.next('b')
TypeError: expected 0 arguments, got 1

ジェネレータに外部から値を渡したいときは send() を使うようだ。だが、初回の send() の呼び出し時に渡す引数には制限があるようだ。

def generatorFunc(a):
    print a
    b = yield 1
    print b
    c = yield 2
    print c

generator = generatorFunc('a')
print generator.send('b')
print generator.send('c')
print generator.send('d')
$ python generator.py 
Traceback (most recent call last):
  File "generator.py", line 9, in <module>
    print generator.send('b')
TypeError: can't send non-None value to a just-started generator

エラーメッセージに従い None を渡したらうまくいった。

def generatorFunc(a):
    print a
    b = yield 1
    print b
    c = yield 2
    print c

generator = generatorFunc('a')
print generator.send(None)
print generator.send('c')
print generator.send('d')
$ python generator.py 
a
1
c
2
d
Traceback (most recent call last):
  File "generator.py", line 11, in <module>
    print generator.send('d')
StopIteration

ES6 の Generator のように受け取った値を黙って無視するよりは、 Python 2 のように例外が出るほうがへんに悩まずに済みそうで好みだ(ES6 の立場では、言語仕様書に書いてあるから熟読してから使え、ということなのかもしれない)