2016-09-28 20 views
3

エリクサーでかstructかどうかを確認するには、のようにKernel.is_map/1を呼び出すことで確認できますが、その2つを区別したいと思います。私はそれがモジュール名です取得するために構造体に__struct__を呼び出すことができることを知っているが、法線マップがスローにそれを呼び出す:マップが構造体でもあるかどうかをチェックする方法?

** (KeyError) key :__struct__ not found in: %{} 

だから私の質問があり、変数がマップまたは構造体であればはどのようにチェックします?


例のユースケース:

# I want to handle struct and map inputs differently in my Module 

defmodule DifferentThings do 
    def do_something(arg) when is_map(arg) do 
    # Do something with Maps 
    end 

    def do_something(arg) when is_struct(arg) do 
    # But handle Structs differently 
    # Issue is, `is_struct` does not exist 
    end 
end 

答えて

11

マップが構造体であるかどうかを確認する:異なるメソッド宣言のために

Map.has_key?(struct, :__struct__) 

(より一般的な方法は秒):

defmodule DifferentThings do 
    def do_something(%{__struct__: _} = arg) do 
    # ... 
    end 

    def do_something(arg) when is_map(arg) do 
    # ... 
    end 
end 
+0

これはガードでは動作しません –

+1

パターンマッチが必要な場合は、 '%{__ struct__:_} = struct'を使用できます。 –

2

あなたはMap.keys/1で簡単にkeys現在のマップのを確認することができます。マップと構造体is_map/1両方がtrueを返すが、あなたの例のでしょうについては

Map.keys(%{}) will return [] 

Map.keys(struct) 

例えば、キーのコレクションを返します。 [:__struct__, :name, :age]

だから、単純に使用することができます。

:__struct__ in Map.keys(struct). 

あなたはこのis_structが、それはマクロ作成したい場合。

一般に
+0

のようなマップ!ありがとうございました! – Sheharyar

+2

'Map.has_key?(構造体:__ struct __)' –

+1

@OleksandrAvoyants - これははるかに優れています。回答として投稿してください。 – Sheharyar

3

あなたが地図に別々の機能ヘッドを持つことができません構造体とガードがありますが、パターンマッチングで行うことができます。

defmodule Guard do 

    def foo(%{:__struct__ => x }) do 
    Struct 
    end 

    def foo(x) when is_map x do 
    Map 
    end 

end 
5

これは、構造体の間にパターンマッチすることが可能である。これは完璧です

以下
defmodule DifferentThings do 
    def do_something(arg = %_x{}) do 
    IO.puts "This is a struct" 
    end 

    def do_something(arg = %{}) do 
    IO.puts "This is a map" 
    end 
end 
+0

' arg =%_x {} ' _ {} '。 – mljrg

関連する問題