トラック
/
Elixir
Elixir
/
演習
/
キッチン計算機
キッチン計算機

キッチン計算機

学習演習

はじめに

タプル

Elixirでは、タプルはデータをまとめるデータ構造のひとつで、どんな型の要素でも決まった個数だけ保持できます。ただし、それぞれの要素に名前はありません。タプルは、メモリからの読み取りが多い処理でよく使われます。要素への読み取りアクセスが定数時間で済むからです。一方、要素を動的に追加したり削除したりする場面では、ふつう使いません。既存のタプルを変更するのではなく新しいタプルを作ることになり、そのぶんメモリを前もって確保しなければならないからです。

実際には、タプルは波括弧({})を使って作ります。タプルの要素には、elem/2関数と0から始まるインデックスを使って個別にアクセスできます。

empty_tuple = {}
one_element_tuple = {1}
multiple_element_tuple = {1, :a, "hello"}

elem(multiple_element_tuple, 2)
# => "hello"

まとまった情報としてのタプル

タプルは、まとまった情報を表すのによく使われます。

Float.ratio(0.25)
# => {1, 4} indicating the numerator and denominator of the fraction ¼

パターンマッチング

パターンマッチングは、断定的で慣用的なElixirのコードで中心的に使われます。=/2は代入演算子ではなくマッチ演算子と呼ばれているのを覚えているでしょうか。マッチ演算子を使うとき、左辺のパターンが右辺とマッチすれば、左辺の変数が束縛され、右辺の値が返ります。マッチしなければ、MatchErrorが発生します。

2 = 2
# => 2
# Literals can be matched if they are the same

2 = 3
# => ** (MatchError) no match of right hand side value: 3

{_, denominator} = Float.ratio(0.25)
# => {1, 4}
# the variable `denominator` is bound to the value 4

マッチは右辺から左辺へと行われることを覚えておきましょう。

最後の例で、パターンマッチに変数が必要ない場合は、_を参照して捨てることができます。_で始まる変数は、ランタイムには追跡されません。

名前付き関数でのパターンマッチング

パターンマッチングは、複数の関数節を作るときにも役立つ道具です。関数の引数に対してパターンマッチングを使うと、どの関数節を呼び出すかが決まります。ファイルの先頭から順に見ていき、最初にマッチした節が選ばれます。変数は関数ヘッドで束縛し、関数本体で使えます。

defmodule Example do
  def named_function(:a = variable_a) do
    {variable_a, 1}
  end

  def named_function(:b = variable_b) do
    {variable_b, 2}
  end
end

Example.named_function(:a)
# => {:a, 1}

Example.named_function(:b)
# => {:b, 2}

Example.named_function(:c)
# => ** (FunctionClauseError) no function clause matching in Example.named_function/1

説明

友達のためにクッキーを焼こうと準備しているうちに、レシピで使われているいくつかの分量を変換しなければならないことに気づきました。メートル法にしか慣れていないので、アメリカのお菓子作りでよく使われる分量をミリリットル(mL)に変換する方法を、自分のために考えておく必要があります。

解答には、次の変換表を使ってください。

変換する単位 体積 ミリリットル(mL)
mL 1 1
アメリカのカップ 1 240
アメリカの液量オンス 1 30
アメリカの小さじ 1 5
アメリカの大さじ 1 15

プログラミングの腕を磨いているなら、表にあるどの単位から別の単位へも(同じ単位同士へも)変換しやすくするために、ミリリットルを中間の単位として使うのがよいでしょう。

1. 量のペアから数値部分を取り出す

KitchenCalculator.get_volume/1関数を実装しましょう。量のペアのタプルが与えられたら、その数値の部分だけを返します。

KitchenCalculator.get_volume({:cup, 2.0})
# => 2.0

2. 量のペアをミリリットルに変換する

KitchenCalculator.to_milliliter/1関数を実装しましょう。量のペアのタプルが与えられたら、変換表を使ってその体積をミリリットルに変換します。

複数の関数節とパターンマッチングを使って、各単位の関数を作りましょう。それぞれの単位を表すアトムは:cup、:fluid_ounce、:teaspoon、:tablespoon、:milliliterです。変換結果はタプルに包んで返します。

KitchenCalculator.to_milliliter({:cup, 2.5})
# => {:milliliter, 600.0}

3. ミリリットルの量のペアを別の単位に変換する

KitchenCalculator.from_milliliter/2関数を実装しましょう。量のペアのタプルと変換したい単位が与えられたら、変換表を使ってその体積を目的の単位に変換します。

複数の関数節とパターンマッチングを使って、各単位の関数を作りましょう。それぞれの単位を表すアトムは:cup、:fluid_ounce、:teaspoon、:tablespoon、:milliliterです。

KitchenCalculator.from_milliliter({:milliliter, 1320.0}, :cup)
# => {:cup, 5.5}

4. どの単位からでも別の単位に変換する

KitchenCalculator.convert/2関数を実装しましょう。量のペアのタプルと変換したい単位が与えられたら、与えられた体積を目的の単位に変換します。

KitchenCalculator.convert({:teaspoon, 9.0}, :tablespoon)
# => {:tablespoon, 3.0}
GitHubで編集する リンクは新しいウィンドウまたはタブで開きます
Elixir Exercism

キッチン計算機を始める準備はできましたか?

Exercismに登録すれば、58個のコンセプト168個の演習、そして本物の人間によるメンタリングとともに、Elixirを学んでマスターできます。すべて無料です。