毎年256日は #プログラマーの日 という以下のコードを Twitter で見かけました。
もとの開発言語は不明ですが、車載端末でも動くような JavaScript に移植してみます。
async/await と非同期イテレータを使ってみます。
while (everyYear) {
if (today().dayNumber == 256) {
celebrate("Programmers' Day");
}
}
https://twitter.com/TRIAD_Japan/status/1172412070769258496 より。
もとのコードの処理を頭の中でシミュレーションすると、
256日目に「Programmers' Day」のお祝いがずっと続いてしまう気がしますので、
どこかでウエイトが入っているはずです。
さらに、256日目以外のことも考慮すれば、while (everyYear)
の部分でウエイトが入り、
1日1回だけ while 文の中が実行されると解釈するのが妥当です。
毎日の処理ぽいのに everyYear
という変数名?を利用していたもとの命名規則は、
謎ですが、なにか意図があるかと思いますので、そのまま移植することにします。
1. async/await で実装した場合
JavaScript 移植では、最初の while (everyYear)
のところがクセモノです。
everyYear
を変数でなくて、関数呼び出しに変更してよければ、async/await で実装できます。
もとの while (everyYear)
が while (await everyYear())
になります。
const sleep = s => new Promise(r => setTimeout(r, s));
const celebrate = m => console.log(m);
const today = () => ({dayNumber: 256}); // TODO
const everyYear = async () => await sleep(1000) || true;
(async () => {
// ここから
while (await everyYear()) {
if (today().dayNumber == 256) {
celebrate("Programmers' Day");
}
}
})();
1年を待つのは辛いので、ここではデモのため、1秒ごとに「Programmers' Day」をお祝いします。
Top-level await が実装されると、(async () => {
と })();
を省けるようになるはずです。
実行結果:(node v10 と Chrome 77 で動作確認済)
Programmers' Day
Programmers' Day
Programmers' Day
ただし、while (await everyYear()) {
の部分については、
動詞 await の目的語が everyYear に読めてしまうので、英語として読み取りにくいです。
読みにくいコードは、安全の敵なので、イマイチです。
2. 非同期イテレータで実装した場合
あるいは、非同期ジェネレータ async function*
という呪文と for-await-of
構文を使えば
everyYear
を非同期イテレータの変数にできるので、関数呼び出しのカッコ ()
をはずせます。
もとの while (everyYear)
が for await (safety of everyYear)
のようになります。
const sleep = s => new Promise(r => setTimeout(r, s));
const celebrate = m => console.log(m);
const today = () => ({dayNumber: 256}); // TODO
const everyYear = (async function* () {
while (true) yield await sleep(1000) || true;
})();
let safety;
(async () => {
// ここから
for await (safety of everyYear) {
if (today().dayNumber == 256) {
celebrate("Programmers' Day");
}
}
})();
for-of
構文では、受ける変数が必要そうなので、safety
としてみました。
while (true) yield await sleep(1000) || true;
の1行は気持ち良いですが、
非同期ジェネレータ async function*
はまだ arrow function で書けなないらしく、そこは残念。
仮に for await safety of everyDay
であれば、日々の安全を求めて活動しながら、
256日目だけは Programmers' Day をお祝いするようなエモいニュアンスが込められそうです。
上記の JavaScript 移植版のライセンスは、もとのソースコードのライセンスに従います。
[余談]
そういえば、https://hack4.jp/relatedinfo/t-shirt/1st/ にある
Hack for Japan の T シャツに記載するコードを検討したときは、みんなでコードレビューして、
いくつかの言語でそのまま動きそうな感じに考慮した記憶があります。
while (Japan.recovering) {
we.hack();
}
事故を防ぐためには、ソースコードはレビューをしてもらうのが大事ですね。