Elixir、Rust、JavaScriptの構文の比較

# Elixir、Rust、javascriptの構文の比較

- [Elixir、Rust、javascriptの構文の比較](#elixirrustjavascriptの構文の比較)
  - [標準出力に出力](#標準出力に出力)
  - [反復処理](#反復処理)
    - [for](#for)
    - [while](#while)
  - [制御構文](#制御構文)
    - [if](#if)
    - [パターンマッチ](#パターンマッチ)
  - [リスト(と配列)](#リストと配列)
    - [リスト内包](#リスト内包)
  - [マップ](#マップ)
    - [構造体(とオブジェクト)](#構造体とオブジェクト)
  - [文字列](#文字列)
    - [結合](#結合)
  - [関数](#関数)
    - [無名関数](#無名関数)
  - [イテレーション処理、高階関数](#イテレーション処理高階関数)
  - [try、エラー処理](#tryエラー処理)
  - [日付](#日付)
- [用語](#用語)
  - [Box](#box)
  - [イテレーション処理と高階関数](#イテレーション処理と高階関数)


## 標準出力に出力

大体

Elixirでは<font color="chocolate">`IO.puts`</font>を使用する。

```elixir
IO.puts "Hello, World."
```

Rustでは<font color="chocolate">`println!`マクロ</font>を使用する。
```rust
println!("Hello, World");
```

JavaScriptでコンソールに出力したいなら<font color="chocolate">`console.log()`</font>を使用する。

```javascript
console.log("Hello, World");
```



## 反復処理

### for

Elixirは要素とイテレータを<font color="red">**`<-`**</font>で区切る。
形式: <font color="chocolate">`for 要素 <- イテレータ do ... end`</font>

Rustは要素とイテレータを<font color="red">**`in`**</font>で区切る。
形式: <font color="chocolate">`for 要素 in イテレータ {}`</font>

JavaScriptは要素とイテレータを<font color="red">**`()`**</font>で囲み、<font color="red">**`in`**</font>で区切る。
形式: <font color="chocolate">`for (要素 in イテレータ) {}`</font>

### while

Elixirには`while`や`loop`は<font color="red">存在しない</font>。
なので再帰関数を使用するとよい。

```elixir
defmodule Loop do

  def while(0) do
    :ok
  end

  def while(num) do
    IO.puts "Hello, World!"
    while(num - 1)
  end
end

Loop.while(10)
```

Rust

```rust
while 条件 {
  ...
}

loop {
  ...
  break;
}
```

JavaScript

```javascript
while (条件) {

}
```
## 制御構文

### if 

Elixirの<font color="chocolate">`cond`</font>を使用するとコンパクトに記述できる。
論理積、論理和に<font color="red">`and`</font>と<font color="red">`or`</font>を使用する

```elixir
if :a == :a do
  ...
else
  ...
end

if :a == :b, do: ..., else: ... 

x = :c

cond do
  x == :a or x == :c -> ...
  x == :b -> ...
  true    -> ...
end
```

Rustでは論理積、論理和に<font color="red">`&&`</font>と<font color="red">`||`</font>を使用する。

```rust
if "a" == "a" {
  ...
} else if "b" == "b" || "c" == "d" {
  ...
}
```

Javascriptのifは条件式を<font color="red">`()`</font>で囲む。
論理積、論理和に<font color="red">`&&`</font>と<font color="red">`||`</font>を使用する。

```javaScript
if ("a" === "c") {
  ...
} else if ("b" === "b" || "c" === "d") {
  ...
}

"a" === "a" ? ... : ...
```

### パターンマッチ

Elixirでは<font color="red">`case`</font>を使用する。
また<font color="chocolate">`->`</font>を使用し、条件と処理を区切る。

デフォルトの処理は<font color="chocolate">`_`</font>で記述する。

```elixir
x = :a

case x do
  :a  -> ...
  :b  ->
    ...
  _   -> ...
end
```

Rustでは<font color="red">`match`</font>を使用する。
また<font color="chocolate">`=>`</font>を使用し、条件と処理を区切る。
<font color="chocolate">`,`</font>で区切る。

デフォルトの処理は<font color="chocolate">`_`</font>で記述する。

```rust
let x = "a";

match x {
  "a" => ...,
  "b" => {
    ...
  }
  _   => {}
}
```

JavaScriptでは<font color="red">`switch`</font>を使用する。
また条件を<font color="chocolate">`case`</font>で記述する。

デフォルトの処理は<font color="chocolate">`defalut`</font>で記述する。

```javascript
let x = "a";

switch (x) {
  case "a":
    ...
    break;
  case "b":
    ...
    break;
  default:
    ...
} 
```



## リスト(と配列)

ElixirのListは異なるデータ型を格納することができる。

```elixir
list = [1, :ok, "hello"]

IO.puts "[0]: #{Enum.at list, 0}, [1]: #{Enum.at list, 1}, [2]: #{Enum.at list, 2}" 
# [0]: 1, [1]: ok, [2]: hello
```

Rustの**Vec**は型安全によって<font color="red">異なるデータ型を持つことができない</font>。

ただし<font color="magenta">`std::any::Any`</font>を使用し<font color="deepskyblue">`Box<dyn Any>`</font>型にすることにより異なるデータを保持することができる。([Boxについて](#Box))

```rust
// 実行時に型が決定
let list = vec![1, 2, 3]

use std::any::Any;

let list_with_any: Vec<Box<dyn Any>> = vec![
    Box::new(1 as i32), 
    Box::new("a".to_string()), 
    Box::new(false)
];  

list_with_any
.iter()
.for_each(|item| {
    if let Some(integer) = item.downcast_ref::<i32>() {
        print!("[0]: {:?}, ", integer)
    } else if let Some(string) = item.downcast_ref::<String>() {
        print!("[1]: {}, ", string)
    } else if let Some(boolean) = item.downcast_ref::<bool>() {
        print!("[2]: {:?}", boolean)
    }
});

// 配列
let l: [isize; 4] = [1,2,3,4];
println!("{:?}", l);
```

JavaScriptの**Array**(配列)は異なるデータ型を格納することができる。

```javascript
let array = [1, "a", false];

// バッククォート(``)で囲む
console.log(`[0]: ${array[0]}, [1]: ${array[1]}, [2]: ${array[2]}`);
```

### リスト内包

Elixirでは以下のように記述してリスト内包を行う。

形式: <font color="red">`変数 = for 要素名 <- 1..5, do: 値の計算`</font>
例  : <font color="chocolate">`list = for x <- 1..5, do: x * 2`</font>

Rustには**リスト内包が存在しない**。
が以下のよう記述することはできる。

```rust
let list: Vec<u32> = 
  (1..5)
    .map(|i| i * 2)
    .collect();
```

JavaScriptには**リスト内包がない。**

## マップ

Elixirでは異なる型のキーと値を保持できる。
2種類の記述があり、どちらかに統一して記述する。

```elixir
m1 = %{"name" => "Taro", "age" => 34, :adress => "Tokyo"}
# すべてのキーがアトムの場合
m2 = %{email: "aaa@aaa.com", blood_type: "X"}
```

Rustでは<font color="magenta">`std::collections::HashMap`</font>を使用する。
異なるキーと値の型を保持したいときは**Box型**を使用する。([Boxについて](#Box))

```rust
use std::collections::HashMap;

let mut map: HashMap<String, String> = HashMap::new();

map.insert("name".to_string(), "Taro".to_string());
map.insert("age".to_string(), "34".to_string());

println!("{:?}", map);

// 値をBox型にする
let mut map_with_box: HashMap<String, Box<dyn Any>> = HashMap::new();

map_with_box.insert("name".to_string(), Box::new("Taro".to_string()));
map_with_box.insert("age".to_string(), Box::new(34 as u32));

// downcast_refで値を取得
&map_with_box
  .iter()
  .for_each(|(k, v)| {
      if let Some(string) = v.downcast_ref::<String>() {
          print!("{}: {} ", k, string);
      } else if let Some(integer) = v.downcast_ref::<u32>() {
          print!("{}: {:?} ", k, integer);
      }
  });
```

JavaScriptでは**Mapクラス**を使用する。

```javascript
let map = new Map();

map.set("name", "Taro");
map.set("age", 34)
```

### 構造体(<font color="gray">とオブジェクト</font>)

Elixirはフィールドのデータ型を<font color="red">宣言しない</font>。
名前付きマップと比べて、フィールドが欠けていることを防止できる。

```elixir
defmodule User do
  # 初期値を定義している。
  defstruct name: nil, age: nil
end

taro = %User{name: "Taro", age: 34}

# 名前付きmap
satoshi = %{name: "Satoshi", age:38}
```

Rust

```rust
struct User {
  name: Stirng,
  age: u32
}

struct Address(String);

let taro = User { name: "Taro", age: 34 };
```

JavaScriptでは一般的に定義と生成を同時に行うほうが一般的。

```
// 定義と生成を同時に行っている
const taro1 =  {
  name: "Taro",
  age: 34
}

// オブジェクトの定義を行っている
const userTemplate = {
  name: "",
  age: null
}

const taro2 = Object.create(userTemplate)
taro2.name ="Taro"
taro2.age = 34
```

## 文字列

### 結合

Elixirで<font color="chocolate">`<>`</font>を使用する。
```elixir
t = "World."

s = "Hello, " <> t
```

Rustでは<font color="chocolate">`+`</font>を使用する。なお、`String`(<font color="gray">文字列</font>)と`&str`(<font color="gray">文字列スライス</font>)の順でないと<font color="red">結合できない。</font>
```rust
let t: &str = "World.";

let s = "Hello, ".ti_string() + t;
```

JavaScriptでは<font color="chocolate">`+`</font>で結合する。

```javascript
let t = "World."

let s = "Hello" + t
```

## 関数

JavaScriptでは戻り値をreturnで

### 無名関数

Elixirでは**fn関数式**を使用するだけ。

形式: <font color="red">`変数 = fn 引数 -> 処理 end`</font>

```elixir
func = fn i -> i * i end

func.(10)

long_func = fn i ->
  ans = i * i
  IO.puts "result: #{ans}"
end

long_func.(10)
```

Rustでは**クロージャ**(<font color="chocolate">`||`</font>)を使用して無名関数を定義する。

なお型推論が行われるため戻り値の型を記述する必要はない。

形式: <font color="red">`let 変数 = |変数: 型| {一行であれば{}は必要ない };`</font>

```rust
let func = |i: i32| i * i;

func(10);

let long_func = |i: i32| {
  let ans = i * i;
  println!("result: #{}", ans);
};

long_func(10);
```

JavaScriptでは**アロー関数**を使用することが一般的(<font color="gray">2つ目</font>)

形式: <font color="red">`let 変数 = (変数) => {処理}`</font>

```javascript
// function()を用いる
let func = function(i) { return i * i }

func(10)

// arrow()関数を使用して簡略化
// functionを省略できる。
// 引数が一つなら()も省略できる。
let arrow_long_func = i => { 
  let ans =  i * i;
  console.log(ans); 
}

arrow_long_func(10)
```

## イテレーション処理、高階関数

[イテレーション処理と高階関数について](#イテレーション処理と高階関数)



Elixirでは<font color="chocolate">`|>`</font>を使用して関数の結果を別の関数に渡すことができる。

Enum.<font color="red">each</font>()なので注意。

```elixir
list = [1,2,3,4,5]

list 
  |> Enum.each(fn i ->
    // ここで処理
    if rem(i,2) == 0 do
      IO.puts i
    end
  end)

list
  |> Enum.filter(fn i -> rem(i, 2) == 0 end)
  |> Enum.map(fn i -> IO.puts i end)
```

Rust

.<font color="red">for_each</font>()なので注意。

```rust
let list: Vec<u32> = vec![1,2,3,4,5];

for i in list.iter() {
  if i % 2 == 0 {
    println!("{}", i);
  }
}

list.iter().filter(|&i| i % 2 == 0).for_each(|&i| println!("{}", i));
```

JavaScript

```javascript
let list = [1, 2, 3, 4, 5];

for (i in list) {
  if (i % 2 === 0) {
    console.log(i);
  }
}

list
  .filter(i => i % 2 === 0)
  .forEach(i => console.log(i))
```

## try、エラー処理

Elixirでは`try`を使用する。各記述は以下の用途で使用する。

* `rescue` - エラー、特定のエラータイプごとの処理を行う。
* `catch` - `throw()`で処理を受け取った値を処理。
* `else` - `throw()`で値を受け取らなかったときの処理。
* `after` - try文のあとに行う処理を記述。

Javascriptのcatchとは<font color="red">意味が異なる</font>ので注意。

```elixir
try do
  # ここで処理
  # throw()で値をcatchに渡すことができる
rescue
  エラー -> エラーの処理
catch
  # throwで値を受け取ったときの処理  
  x -> ...
else
  # throwで値を受け取らなかったときの処理
  _ -> ...
after
  # try文のあとに行う処理を記述
end
```

Rustの<font color="red">Result型</font>は**エラーハンドリング**のための型である。
Rustでは例外が発生するような関数の戻り値はResult型である。
ので、`match`で処理する。

```rust
x = ... // ここでResult型が戻り値の関数を実行しているものとする。

match x {
  Ok(_) => // 処理
  Err(_) => // 例外処理
}
```

JavaScriptのcatchはエラーを処理する

```javascript
try {
  // 処理
} catch (e) {
  // エラー処理
} finally {
  // 後処理
}
```

## 日付

<font color="gray">NaiveDateTimeは省略(多用したらよくないらしい)</font>

Elixirではタイムゾーンを指定するために<font color="magenta">`tzdata`</font>、<font color="magenta">`timex`</font>をインストールする必要がある。

```elixir
to_day = Date.utc_today()
utc_now = DateTime.utc_now()

tokyo_time = DateTime.now("Asia/Tokyo")
```

Rustでは<font color="magenta">chrono</font>クレートを使用する。またタイムゾーンを使用するために<font color="magenta">chorono_tz</font>を使用する。

```rust
use chrono::{Utc, Local};
use chrono_tz::Asia::Tokyo;

let to_day = Utc::now.date_naive();
let utc_now = Utc::now();

// タイムゾーンがAsia/Tokyoであれば、以下2つは同じ
let tokyo_time = Utc.now().with_timezone(&Tokyo);
let local_time = Local::now();
```

JavaScriptでは**Dateクラス**を使用する。

```javascript
let to_day = new Date();
```

# 用語

## Box

1. Rustにおいて値は**スタック**に保存される。
2. <font color="deepskyblue">`Box<T>`</font>を生成することで、値は**ヒープ**に保存される。またスタックには<font color="red">ヒープへのポインタ</font>が保存される。
3. Vecはコンパイル時に格納するデータ型(<font color="gray">`Vec<T>`のTのこと</font>)が決まっている必要がある。
4. よってVecがBox型を格納することで、**異なるデータ型の要素を格納**することができる。

## イテレーション処理と高階関数

大体はイテレーション処理 ≒ 高階関数

2つは以下の点で異なる。

* イテレーション処理はforを使用して**一要素ごとに処理**を行うイメージ。
* 高階関数は**関数ごとにすべての要素を処理する**イメージ。