2016-07-06 9 views
11

関数ヘッドのマップキーでパターンマッチングを行う方法が見つからないようです。これを行う方法はありますか?私は何をしようとしているが、特定のキーがすでにマップ内に存在するかどうかに応じて異なるコードを実行される(とも避けたかった/ elseと同様であれば)エリクシルの関数頭でマップキーのパターンマッチングを行う方法

これは私のコードは

次のようになります

私にマップキーマッチ内部変数キーの**(CompileError)不正使用を、このエラーが発生します

def my_func(key, %{key => _} = map), do: ... 

、マップは唯一^キー

を使用して、既存の変数に一致させることができます

キー^もちろん

私もその後、

**(CompileError)を与える^

def my_func(key, %{^key => _} = map), do: ... 

を使用して、それを試してみまし結合していない変数私は万能薬1.3.1を使用しています/ erlang 19.0 x64をWindows 8.1マシンにインストールします。 読んでいただきありがとうございます! IEXで次に

defmodule Test do 
    def my_func(%{"a" => value}), do: {:a, value} 
    def my_func(%{"b" => value}), do: {:b, value} 
    def my_func(_), do: :error 
end 

:あなたが必要とするキーを持つ

答えて

12

ただ、パターンマッチが

iex(1)> Test.my_func(%{"a" => 1}) 
{:a, 1} 
iex(2)> Test.my_func(%{"b" => 2}) 
{:b, 2} 

また句の順序は重要です。

iex(3)> Test.my_func(%{"a" => 1, "b" => 2}) 
{:a, 1} 

あなたはすべてのキーのために何かを生成したい場合は、一致させることができます:あなたは%{"b" => 2}に一致するようにしようとしているが、あなたは、次のマップ%{"a" => 1, "b" => 2}を持っている場合、最初の句であるので、例えば、キー"a"は、最初に一致します私は別のアプローチをお勧めします。たとえば、あなたがそれらのキーに機能をマップする場合:

defmodule Test0 do 
    def my_op({"times_2", value}), do: {"times_2", value * 2} 
    def my_op({"times_3", value}), do: {"times_3", value * 3} 
    def my_op({key, value}), do: {key, value} 

    def my_func(m) do 
    Enum.map(m, &my_op/1) |> Enum.into(%{}) 
    end 
end 

だから、あなたは次のようになるだろう:

iex(1)> Test0.my_func(%{"times_2" => 2, "times_3" => 3, "whatever" => 42}) 
%{"times_2" => 4, "times_3" => 9, "whatever" => 42} 

更新この回答

あなたはのコメントによると変数にキーを一致させることはできません。問題は、コンパイラが未知のものを検索するコードを生成する必要があることです。パターンマッチングを行うときには、通常、コンパイラに何が得られるかのヒントが与えられます。マップ内のキーのヒントはキーそのものです。この場合、最初の引数が探すべきキーであることを指摘しても、コンパイラにとっては十分ではありません。だからあなたのアプローチは、ifステートメントを使用する必要があります:

defmodule Test2 do 
    def my_func(k, m) do 
    if Map.haskey?(k, m), do: warning(k, m), else: foo(k, m) 
    end 

    def warning(k, m) do 
    #Warning 
    m 
    end 

    # In this function you could apply the pattern matching 
    # described in the first part of this answer. 
    def foo(k, m) do 
    value = # do something 
    %{m | key => value} 
    end 
end 

これはあなたの質問に答えることを望みます。

+0

こんにちは、お返事ありがとうございます。しかし、私はおそらく、 'my_func(key、_)'のキーが実行時に決定される変数であることを明確にするべきです、コンパイル時には知られていません。 – bottlenecked

+0

OK、今私はあなたが何をしようとしているのかを部分的に理解しています。あなたの機能はまさに何をしていますか? –

+0

Um、関数本体を追加するのは関係ないと思いましたが、終了コードは「キーが既に存在する場合は警告を出し、そうでない場合はfooを実行してマップに追加してください」 – bottlenecked