「Good Morning World」と「Good Night World」(ruby, javascript)

# はじめに

「Hello World」はプログラムの実行環境における文字列出力のための題材です。

大抵がファーストステップとしての位置付けですが、**プログラムがどう動くのか**の題材として[徹底解説](https://qiita.com/kazatsuyu/items/478c55de0f75ea5904bd)すると30K文字を超える文章が必要となることもあります。

「Hello world」に続く題材としては、「Fizz Buzz」や「[AtCoder 過去問精選 10 問](https://qiita.com/drken/items/fd4e5e3630d0f5859067)」等が定番です。

これらは**アルゴリズムを各言語でいかに実装するか**が主体となるため、**「Hello Wold」の次にプログラムがどう動くのかを考える題材は少ない**と感じています。

そこで、**同期/非同期処理の理解を深めるための題材**として、**「Good Morning World」**と**「Good Night World」**をRubyとJavaScriptで書いてみました。

# 【定義】 Good Morning WorldとGood Night Worldとは

## Good Morning World 

 **1. 「アラームセット(N秒後に"Ring!Ring!Ring!"と表示する)処理」に続けて、「"Good Morning World"と表示する処理」が記載されていること。**
 **2. 「アラームセット(N秒後に"Ring!Ring!Ring!"と表示する)処理」に続けて、「"Good Morning World"と表示する処理」が実行されること。**
 **3. "Ring!Ring!Ring!"と表示された後に、"Good Morning World"と表示されること**

実行結果例

```
Ring!Ring!Ring!
Good Morning World
```

## Good Night World 

 **1. 「アラームセット(N秒後に"Ring!Ring!Ring!"と表示する)処理」に続けて、「"Good Night World"と表示する処理」が記載されていること。**
 **2. 「アラームセット(N秒後に"Ring!Ring!Ring!"と表示する)処理」に続けて、「"Good Night World"と表示する処理」が実行されること。**
 **3. "Good Night World"と表示された後に、"Ring!Ring!Ring!"と表示されること**

実行結果例

```
Good Night World
Ring!Ring!Ring!
```

# 解答例

以下のコードは、[paiza.io](https://paiza.io/ja/projects/new)にて動作を確認しています。

## Rubyでの解答例

``` GoodMorningWorld.rb
def set_alarm n; sleep n; puts 'Ring!Ring!Ring!' end

set_alarm 0.1
puts 'Good Morning World'
```

``` GoodNightWorld.rb
def set_alarm n; Thread.new{ sleep n; puts 'Ring!Ring!Ring!' } end

t = set_alarm 0.1
puts 'Good Night World'
t.value # オンライン実行環境等で待受けるため
```

## JavaScriptでの解答例

``` GoodMorningWorld.js
const set_alarm = async n => new Promise( resolve => setTimeout( () => { console.log('Ring!Ring!Ring!'); resolve() }, n));

(async () => {
  await set_alarm(0.1);
  console.log('Good Morning World');
})();
```

``` GoodNightWorld.js
const set_alarm = n => setTimeout( () => console.log('Ring!Ring!Ring!'), n);

set_alarm(0.1);
console.log('Good Night World');
```

# (補足) 他の回答について

## callbackを用いたGoodMorningWorld

以下のJavaScriptのコードは、出力結果はGoodMorningWorldと同じになりますが、以下の理由で**GoodMorningWorldではない**と判定できます。

(理由)  「アラームセット処理」と「"Good Morning World"と表示する処理」の処理が、記載も実行も**「続けて」ではなく、「中に入って(ネストして)」いる**ため。

``` GoodMorningWorld_callback.js
const set_alarm = (f, n) => setTimeout( () => { console.log('Ring!Ring!Ring!'); f() }, n);

set_alarm(
    () => console.log('Good Morning World'),
    0.1
);
```

## 実行順を変えたGoodNightWorld

以下のrubyのコードは、記載順も正しく、出力結果はGoodNightWorld同じになりますが、**実行順を変えているため、GoodNightWorldではないと**判定できます。

``` GoodNightWorld_reverse.rb
def reverse_call *arg; arg.reverse.each(&:call) end
def set_alarm n; sleep n; puts 'Ring!Ring!Ring!' end

reverse_call(
  lambda { set_alarm 0.1 },
  lambda { puts 'Good Night World' },
);
```



## Promise.thenを用いたGoodMorningWorld

プログラムの記載順としてブロックも分かれていることと、thenはPromiseが成功した時に(続けて)呼び出す処理と解釈できるため、**GoodMorningWorldである**と判定できます。

``` GoodMorningWorld_promise.js
const set_alarm = (resolve, n) => setTimeout( () => { console.log('Ring!Ring!Ring!'); resolve(); }, n);

new Promise(resolve => set_alarm(resolve, 0.1))
    .then( () => console.log('Good Morning World'))
```

# さいごに

「Hello World」の利点は、初めてのプログラムでも、"Hello World"を表示するプログラムだと推測できる点です。

``` hogehoge.hogehoge
z % Hello World
```

同期/非同期処理は、新しい言語では理解が難しい部分が多いですが、「Good Morning World」と「Good Night World」で共通理解が進むと嬉しいなと思います。

(参考) scriptタグについて

``` GoodMorningWorld.html
<script src="./set_alarm.js"></script>
<script src="./good_morning_world.js"></script>
```


``` GoodNightWorld_.html
<script src="./set_alarm.js" async></script>
<script src="./good_night_world.js" async></script>
```

定義部分は、(特定言語によらない)同期/非同期プログラミングの分かりやすい共通定義となるように考えましたが、おかしい点や、他にもっといい定義があればコメント歓迎です。

更にアドバンスドな題材や、他の言語の「Good Morning World」と「Good Night World」や解説記事が書かれると嬉しく想います。