【Node.js】REPLを活用したインタラクティブなプログラミング学習方法

# Node.jsのREPLを活用したインタラクティブなプログラミング

Node.jsの`REPL（Read-Eval-Print Loop）`は、即時フィードバックを得ながらプログラミングを行う強力なツールです。

https://nodejs.org/docs/latest-v21.x/api/repl.html

`REPL`は略称で、ユーザーがコマンドを入力すると、そのコマンドを読み取り（Read）、評価（Eval）、結果を出力（Print）し、次の入力を待つ（Loop）という一連のプロセスを繰り返します。

（ちなみに他言語のREPLはといえば、Rubyなら`irb`、Pythonなら`python`でお馴染みですね）

Node.jsの標準ライブラリの機能や、サードパーティ製ライブラリを試すのに`REPL`はとても便利です！

## REPLの基本的な使用方法

Node.jsのREPLを起動するには、ターミナル画面で`node`と入力します。

```terminal: terminal
$ node

Welcome to Node.js v18.18.0.
Type ".help" for more information.
```

このコマンドでREPL環境が開始され、JavaScriptのコードを実行できます。


```terminal: .helpで使い方を見てみましょう
> .help
.break    Sometimes you get stuck, this gets you out
.clear    Alias for .break
.editor   Enter editor mode
.exit     Exit the REPL
.help     Print this help message
.load     Load JS from a file into the REPL session
.save     Save all evaluated commands in this REPL session to a file

Press Ctrl+C to abort current expression, Ctrl+D to exit the REPL
```

:::note warn
前提情報
Node.jsのREPL環境でES Moduleの構文（import文）を直接使用することはできません。これはREPLが標準的にCommonJSモジュールシステムを使用しているためです。

しかし動的インポート（import()関数）を使用することで、ES Moduleのモジュールを読み込みは可能です。
※ESModuleのモジュール読み込みについては、最後に取り上げます
:::

## `process`モジュールの使用

ここでは、Node.jsの標準ライブラリでコアモジュールの`process`を例にしてみます。
REPLでは`process`オブジェクトを利用して、現在のプロセスに関する情報を取得できます。

```javascript
> process.version
'v16.13.0' // 実行中のNode.jsのバージョン
> process.env.PATH
'/usr/local/bin:/usr/bin:/bin' // 環境変数PATHの内容
```

https://nodejs.org/docs/latest-v21.x/api/process.html


## `events`モジュールとEventEmitter

`events`モジュールを使ってカスタムイベントを扱います。

https://nodejs.org/docs/latest-v21.x/api/events.html#class-eventemitter

```javascript: REPL実行中に以下を入力
// // eventsモジュールをインポート
> const EventEmitter = require('events');

// EventEmitterのインスタンスを作成
> const myEmitter = new EventEmitter();

// 'event'イベントに対するリスナーを登録
> myEmitter.on('event', () => { 
  console.log('an event occurred!');
});

// 'event'イベントを発火
> myEmitter.emit('event'); 
```

```terminal: 実行結果
 an event occurred!
```

ここでは、カスタムイベント`event`を発生させ、それを処理しています。

## `yargs`モジュールの活用
サードパーティライブラリであるyargsを例にしてみます。

https://github.com/yargs/yargs/blob/main/docs/api.md

`yargs`モジュールをREPLで使って、コマンドライン引数の解析を試みます。

```javascript
> const yargs = require('yargs/yargs');
> const argv = yargs(process.argv.slice(2)).argv;
> argv
{ _: [] }
```

`yargs`を使うことで、コマンドライン引数を簡単に解析できます。




# REPLでESModuleのモジュールを読み込む方法

Node.jsのREPLでは、`.mjs`拡張子を持つES Moduleファイルを動的インポートを使用して読み込むことができます。
この方法を使うと、REPL内でES Moduleの機能を直接試すことが可能になります。

### ステップバイステップの指示

#### 1. モジュールファイルの作成

まず、`.mjs`拡張子でES Moduleのモジュールファイルを作成します。
例えば、`myScript.mjs`という名前のファイルを作成し、次のようなコードを記述します。

```javascript: myScript.mjs
export const sayHello = () => {
    console.log('Hello from ES Module!');
};
```

#### 2. REPLの起動

次に、ターミナルでREPLを起動します。

```terminal: REPLを実行
node
```

#### 3. モジュールの機能の利用（モジュールの動的インポート　と実行）
REPL内で、作成した`.mjsファイル`を動的にインポートします。

- 使用例1
Node.js v16.6.0以降ではREPLのトップレベルで`awaitキーワード`を使用できます。
以下のコードは、myScript.mjsモジュールを非同期的にインポートし、その結果をmodule変数に代入しています。
awaitキーワードは、Promiseが解決されるのを待ち、その結果をmoduleに格納します。

```javascript: REPLを実行中に以下を入力
// REPL実行中に、以下のようにインポートする
const module = await import('./myScript.mjs');
// インポートしたモジュール内の関数をREPL内で利用してみる
module.sayHello();
```

```terminal: 実行結果
Hello from ES Module!
```


- 使用例2
一方で、このような動的インポートと実行の方法もあります。
この例はプロミスを返すため、.then()メソッドを使ってモジュールが読み込まれた後の処理を記述します。
```javascript: REPLを実行中に以下を入力
import("./myScript.mjs").then(myScript => {
  myScript.sayHello();
  console.log("Goodbye myScript.");
});
```

```terminal: 実行結果
Hello from ES Module!
Goodbye myScript.
```


## まとめ

Node.jsを例にREPLを取り上げました。
言語の深い理解を得るためにREPLを使う事は大事だと思います。
コアモジュールの構造や仕様、動作を理解するのに役立ち、サードパーティライブラリを試すのにとても便利です。

プログラミングの学習、デバッグ、スクリプトの試作において、REPLのインタラクティブな特性を活用すると効果的です。
コードの試行錯誤を通じて、言語の豊富な機能をより深く理解していきたいですね。