LoginSignup
2
0

More than 5 years have passed since last update.

ElixirでElixirインタプリタを作成していく(第2回 基本的な引数の分割)

Last updated at Posted at 2019-03-15

ElixirでElixirインタプリタを作成していく

第2回 基本的な引数の分割

前回に引き続き,今回は文字列として与えられる引数をリストとして返す関数を作成していく.
リストはapply関数に渡すものであり,

"1, 2.0, \"hello\"" |> function
# [1, 2.0, "hello"]

のようになるようにする.
しかし上記のように分割するために初めに文字列のリストとして分割すると変換しやすそうである

"1, 2.0, \"hello\"" |> function
# ["1", "2.0", "\"hello\""]

ここで関数functionを次のように定義する

定義

関数名:arg_convertion
引数:String
返り値:[String]

実装

今回は引数分割の実装を行っていく.
ここで通常,で区切れば引数を分割できると考えるだろう.
つまり次のように書くことができる

String |> String.split(",")

しかしよく考えてほしい,ListMap,Tupleにはそれぞれの中で,を使用する
次のような場合を考えてみよう

"1, [2, 3, 4]"

これは,引数の個数は2であることがわかるであろう.実際に関数を呼び出すとき

Example.function 1, [2, 3, 4]

となり,呼び出される関数はExample.function/2であるべきだ
しかしString.splitで分割してしまうと

["1", " [2", " 3", " 4]"]

となり,引数が4つあるように感じてしまう.
この状態から後ろ3つをListとして抽出することは不可能でないだろう
しかし,理想としては一発で2つに分割できる事が望ましい
そこで正規表現を用いたRegex.split関数を用いることとする
次にRegex.splitを用いたコードを示すが,このコードはすでにListや文字列などを考慮して作成したものだということを念頭にいれていてほしい

    Regex.split(~r/(\%.*\{.*\}|\[.*\]|\{.*\}|,|\".*?[^\\]\"|\s)/, arg, include_captures: true)

この時,include_captures: trueによって分割の指標となる文字列もListとして現れることとなる
実際に使用すると次のようになる

["1", ",", "", " ", "", "[2, 3, 4]", ""]

,やスペース,空文字列も分割されていることがわかるだろう,
そこでいらないものを排除する関数を作成する.

Core/utils.ex
defmodule ElixirInterpreter.Core.Utils do
  def drop_value(list, [head | tail]) when is_list(list) do
    list
    |> Enum.reject(fn x -> x == head end)
    |> drop_value(tail)
  end
  def drop_value(list, []) when is_list(list), do: list
end

上記の関数を作成して次のようにする

["1", ",", "", " ", "", "[2, 3, 4]", ""] |> ElixirInterpreter.Core.Utils.drp_value

すると結果は

["1", "[2, 3, 4]"]

となり,2つに分割できていることが確認できる.
これはListだけでなくMapTuple,Structにおいても分割が可能だ

以上の関数を関数として実装しておく,

core.ex
defmodule ElixirInterpreter.Core do
   ...
   def arg_split(arg) when is_binary(arg) do
    Regex.split(~r/(\%.*\{.*\}|\[.*\]|\{.*\}|,|\".*?[^\\]\"|\s)/, arg, include_captures: true)
   end
end

これで引数をListに変換する目途が立ったように思う
今回でInteger,Float,nilの実装も考えたが内容が大きなものだったので次回に持ち越そうと思う

第0回 目次
第1回 文字列からモジュールと関数を導き出す
第3回 文字列のリストを値として変換していく

以下ソースコード(マスターでゴリゴリ開発してるので悪しからず.)
GitHub: ElixirInterpreter

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0