Array.prototype.reduce() に親しむ
JavaScript の配列に reduce という関数がある。 MDM のドキュメント によると以下のように書かれている。
arrayObj.reduce(function(previousValue, currentValue, index, array){ // ... })
previous とか current いわれてもよくわからん。。 ただ、感覚を掴んでくるとこいつがなかなか便利だ。
たとえば、配列をループの中で処理する場合、そのままだと二重ループになっちゃって計算量がかさむってことがある。なので事前に配列じゃなくて連想配列だと嬉しい。そんなとき、こいつを使うと配列を連想配列に変換することができる。
array.reduce((map, obj) => { map(obj.key) = obj; return map; }, {});
また Object.assign()
とも相性がいい。これは、第一引数のオブジェクトに第二引数のオブジェクトをくっつけることができるというものだ。なので、たとえばオブジェクトの配列
const array = [ { "1" : { ... }, } { "2" : { ... } } ]
を使って
const result = array.reduce((map, obj) => { Object.assign(map, obj); }, {});
すると、
result = { "hoge" : { ... }, "fuga" : { ... } }
のように変換できる。たとえば Node.js でデータを配列として取得して、 key-value として扱いたいってときに超便利。
Node.js × TypeScript 勉強中 (2)
Node.js × TypeScript 勉強中 - take a keen edge から続いた。
JavaScript の拡張メソッド (って呼ぶの?) 書くときはこうなる。
Array.prototype.chunk = function (size) { if (!this.length) return []; return [this.slice(0, size)].concat(this.slice(size).chunk(size)); }
で、 Node.js でこいつを別ファイルに切り出したい。そんなときは、
Array.prototype.chunk = function (size) { ... } exports = Array;
として、呼び出し側で
require('arrayExtensions'); function hoge(array) { const chunked = array.chunk(100); }
してやる。モジュールじゃないので const extenstions = require('arrayExtensions')
する必要はない。 TypeScript でいうと import extensions = require('arrayExtensions')
みたいに書くと怒られる。
コピペばっかしてると import とか require とかがどの文脈のものなのかわからなくて詰みそうなところである。
ちなみに TypeScript の拡張メソッド (?) は ↑ だと怒られて、 interface を切る必要がある。
interface Array<T> { chunk(size: number): Array<T>; } Array.prototype.chunk = function (size) { ... } exports = Array;
打ち合わせで実現したいこと
良い打ち合わせは自然とは生まれないものです。自戒の意味も込めて考え直してみました。
参加者と、いわゆるファシリテーターの役割がごっちゃになっているので注意が必要かもしれません。
- 目的を明確にする
- 何のために集まっているか?
- 情報を知ってもらう / 案を出す / 決断する(どれか1つの場合もあるし、複数の場合もある)
- 進行する
- 上記の目的が複数に該当する場合、いまどの段階なのか意識する
- 参加者に意識してもらう、も大事
- 意見が少ない(が、何か言いたそうな)人にタイミングよく振る
- ある観点で情報が充足してきたら観点を増やす
- 意見が盛り上がらなかったとき用の話題を出す
- 事前に用意しとく
- 上記の目的が複数に該当する場合、いまどの段階なのか意識する
- 次の行動を決める
- 誰が / いつまで / 何を
- 何を、はとくに曖昧になりがち;参加者全員で具体的に認識をあわせることが理想
- もし早く終わったらさっさと終わる
- 誰が / いつまで / 何を
- 上記を準備しとく
- できれば事前に展開しとく
これらは文字にしたら誰にとっても当然なことに見えると思いますが、なかなか(部分的にですら)達成された打ち合わせには出会えません。
あと、教科書的にはこれらを「常に意識しましょう」とか言いたくなりますが、何かを常に意識するなんて(少なくとも自分には)不可能なので、チェックポイント的に時間を区切って確認する、とかの技術も別途必要ですね。
ドヴォルザークの序曲「オセロ」について
ドヴォルザークの序曲「オセロ」作品93は、ここ数年で出会ったクラシック曲の中で断トツに好きな曲だ。
この曲は序曲3部作の3曲目らしい。2曲目はドヴォルザークの作品の中でも有名な「謝肉祭」。アマチュアオケの演奏会情報を掲載されている i-Amabile さん をみてみると、これまでの演奏回数は2017年12月19日現在で「謝肉祭」が119回、「オセロ」が11回と、10倍以上の差がある。たしかに、謝肉祭と比べられたら派手さは少ない。というか地味。
そんな地味なこの曲のどこが好きなのかというと、上の音源でいうと序盤である4:00以降に現れる、映画音楽的な勇ましい旋律、この旋律が一瞬で終わってその後同じ形では二度と登場しないところ。 こんなに格好いいのに。チャイコフスキーだったらこれをもう2、3回は使ってるよ。8:30あたりでもう一度現れると思いきや肩透かし。9:50あたりから、すこし形を変えて登場。でもあの頃の姿じゃない。コーダでついに来るか!と思ったらやっぱり来ない。で、ドヴォルザーク特有のアクロバティックなコード進行で突然終わり!
で聴き終わって、あの旋律がまた聴きたくなるんだ... 序盤にいいところを持ってきて、期待感を膨らませたまま、そのカタルシスを解放させるでもなく終わる。もしこれが映画だったら不快だろう。でも音楽なんだから、そのまま繰り返しても誰も文句を言わないはずだ。しかしドヴォルザークはそうせず、敢えて手間をかけて変奏した。1回聴いただけでは満足できない音楽体験、それを彼は目指していたんだ(本当か?)。
それでいて、何回も聴いているうちに、前奏も内声が充実しててクソ良いことに気づいたり、各楽器のソロ、アンサンブルがめっちゃ良かったり、そういえばドヴォルザークのここまで洗練されて劇的な曲って知らないかも?と思いはじめたり、「ここ完全に新世界じゃん!」とツッコミをいれたり(オセロと新世界は作曲時期が重複している;新世界のほうが完成が3年ほど後)、いろいろな楽しみ方ができるようになっている。
いつか演奏したい。
Elasticsearch でつまづいた話 (5)
Bucket Selector Aggregation というのがある。Terms Aggregation を柔軟にしたようなもので、「あるフィールドで特定の条件を満たすレコードの単位で集計」というような記述ができる。
下の例では 2 つのフィールドをまたがって条件を指定している。
{ "bucket_selector": { "buckets_path": { "my_var1": "the_sum", "my_var2": "the_value_count" }, "script": "params.my_var1 > params.my_var2" } }
これを Nested Aggregation 等と組み合わせて使用したい場合、フィールド名の指定が素直にいかない。 Nested の外から Nested 以下のフィールドを指定しようとすると >
を使ってたどる必要がある。
{ "aggs" : { "nested_agg" : { "nested" : { "path" : "product" }, "aggs" : { "sum_values" : { "sum" : { "field" : "price" } } } }, "bucket_agg" : { "bucket_selector" : { "bucket_path" : { "var" : "nested_agg>price" }, "script" : { "var > 100" } } } } }
この >
でフィールドをたどるのはおそらく bucket_selector に限った話ではないと思うが、調べてもなかなか情報に当たらなかったので結構なハマりポイントだと思う。
Node.js × TypeScript 勉強中
Node.js × TypeScript の勉強中。いずれも触るのはほぼ初めてです。各種チュートリアル記事を読んで試していますが、「このおまじないは何?どっからきたの?」状態なので、今回疑問に思ったことがそれぞれがどの文脈に帰属する問題なのか (Node.js / TypeScript あるいは他のなにか) をまとめました。
こういう、新しいものを学ぶときの手探り感を大事にしていきたい。
知っていたこと
- Node.js はサーバーサイドで動く js だよ
- TypeScript をコンパイルすると JavaScript になるよ; pure js と違って型があるよ
- npm はパッケージをいい感じにインストール・管理してくれるやつだよ; 設定は package.json に記述するよ
export / import ってなんやねん
MyApp.js
export class MyApp { doSomething(){ ... } }
app.js
import {MyApp} from './MyApp' let app = new MyApp(); app.doSomething();
export / import は ES6 (もともとは CommonJS で生まれたらしい) で既定される構文で、 js ファイルをまたがってモジュール (変数や関数) を利用したい場合に使用します。サーバーサイド js の繁栄に伴いモジュール管理の重要性が高まってきたことによって導入された構文のようです。従来のワークアラウンドとしては、グローバルに名前空間を切って擬似的にモジュール化を実現するという手段がありましたが、依存関係を解決できませんし、グローバル汚染はやはり発生してしまっていました。 export / import によって、これをスマートに実現できるようになったわけですね。
経緯については こちらの記事 で大変わかりやすく書かれています。
typings ってなんやねん
Node.js × TypeScript のチュートリアル記事でよく登場するのが以下のおまじないです。
npm install -g typescript npm install -g typings
typescript はわかるとして typings はなんでしょうね。これは TypeScript の型定義を管理してくれるツールのようです。何もしないと TypeScript が Node.js の型を解釈できないわけですが、 typings install dt~node
のようなコマンドによって、TypeScript のコンパイルが通るようにしてくれます。
型のインストール設定は typings.json
に書きます。なので git 管理するときはこいつを突っ込んでおけば良いようです。
一方で、 typings を使わない記事では以下のようなおまじないが登場していました。
npm install @types/node --save
調べてみると、 @types
も TypeScript の型定義を管理してくれるようです。こちらの方が新しいんですね。package.json に追加するだけでよく、 typings のインストールや typings ファイル群 / typings.json を管理する必要がないため、シンプルに済みそうです。ただし、 TypeScript の中の人の記事 によれば this is still a work in progress. だそうですから、このあたりのエコシステムはまだ変わる可能性がありそうです。
typings 以前には tsd というものもあったらしいですが、もはや非推奨らしいので触れません。
npm install -g ってなんやねん
↑でも登場していました。npm install のオプションであることはひと目でわかりますが、多くのインストールのインストラクションで指定されています。
g
は global を意味するようで、どこで実行してもパスが通るようにするためのものです。 windows であれば /appdata/Roaming/npm
に配置されるようですね。
世間では高い頻度で使用されるオプションですが、できるだけ使いたくない派 の方もいらっしゃるようです。たしかに、ローカルで動いてたけど別の環境で動かなくなった、ということでハマることは容易に想像できますねー。
use strict ってなんやねん
TypeScript をコンパイルすると、生成された js ファイルの先頭行に "use strict";
が登場します。これは ES5 以降の規格で、指定すると js の構文チェックがより厳格に行われるようになるらしいです。
pure js でも、将来の ECMAScript への移行をスムーズにするため等の目的で、積極的に利用していきたいですね。
tsc はどこで実行するんじゃい
tsc
は TypeScript のコンパイルを行うコマンドです。プロジェクトのルートで npm とか叩いてて、ソースは src
ディレクトリの中にいる、みたいなときにルートでひたすら tsc
実行してて、「ヘルプしか出てこないやんけ!」と騒いでいましたが、ソースと同じディレクトリで実行する必要がありました。まあ当然なんですけど。
ターミナルでわざわざルートとソースのディレクトリを行き来するのはクソ面倒ですしオペミスのもとなので、 npm のスクリプトに追加しとくのが良いんでしょうね。
{ "scripts": { "build": "tsc -p src" } }
(-p
オプションで実行ディレクトリを指定できる)
セミコロンは要らんのかい
各種チュートリアル記事で Node.js / TypeScript の行末セミコロンが無いコードが沢山ありました。 JavaScript には自動セミコロン挿入という機能があるが害悪である、というのが一般的な認識だと思っていたので、こっちの世界では書かないのか正しいのか??と困惑しました。
これは結果的にはたまたまだったようです。セミコロンが無いほうが読みやすい、というのもわからなくはないですが、Node.js のコアコントリビューターであるFelix Geisendörfer 氏はセミコロンつけろと言っています。つけなくても大丈夫であるという確証は得られてませんが、好みの問題なのでしょうかね。
というわけで Node.js の実際の部分とかには全然踏み込めてないわけですが、そのへんは回を改めましょうかね。
仕事中のBGM
昨日の仕事中の BGM - tom-manabe’s kiroku に触発されて、仕事中にきく BGM について。
私は仕事中はほぼエレクトロニカかアンビエントか、できるだけ感情が動かないような曲を聴きます。だいたい垂れ流しなのですが、たまに凄い刺さるアーティストに当たるので紹介。
Fugenn & The White Elephants
いやー、もう単純にめちゃくちゃかっこいいですね。低音パートが押し付けがましくなく鮮明なところも良い。
Olafur Arnalds
ピアノとストリングス中心の穏やかな曲が多いですね。アルバム "...And They Have Escaped the Weight of Darkness" なんかは、夜寝る前に読書でもしながら流すのにもちょうどいいです。
Goldmund
こちらもピアノ中心 (このアルバム "Two Point Discrimination" はピアノソロ)ですが、この不安定さはなんですかね。でも不思議と安心するのです。ただし切羽詰まっているときに聴くとマジで追い詰められるので止めたほうがいいですね。
Akisai
アコギ中心。メロもシンプルでポップな曲が多いですね。
[.que]
彼はもう定番化していますね。ラジオなんかでもよくかかっています。ポップで親しみやすく爽やかで、かつ嫌味じゃない(個人的に、 No. 9 はちょっと嫌味くさい)。
Hammock
美しい!!!
(番外) Television
残業して行き詰ったときは Television を聴きますね。
Marqueen Moon は疑う余地のない名盤ですが、どこがどう名盤なのか全く説明できないところが凄い。