2017-12-13 5 views
0

私は、フォームの多くのコードを書くことにしそうだするプロジェクトに取り組んでいます:エリクサーマクロ、引用ビット列patternmatchタイプ

defmodule Kind 
    defstruct [name1, name2, name3] 
    @type t :: %Kind{name1: integer(), name2: integer(), name3: binary()} 
    def unpack(input) do 
    with <<name1::integer-8>> <- Enum.take(input, 1), 
     <<name2::integer-little-32>> <- Enum.take(input, 4), 
     <<name3::binary-10>> <- Enum.take(input, 10), 
    do: %Kind{name1: name1, name2: name2, name3: name3>> 
    end 
end 

(、inputを入力名とタイプの任意のセットについて

これはマクロで処理できるので、(例えば)use Unpack quote([{name1, integer-8}, {name2, integer-little-32}, {name3, binary-10}])と書くだけで、必要な構造体typedefを自動的に生成できるので、非常に便利です。固定サイズの任意の名前のついたフィールドに対して、アンパック機能を使用します。それを拡張して、タプルに3番目のフィールドを追加して、可変サイズの型を処理する関数を渡すこともできました。私はそれの簡単なバージョンを実行しようとする場合残念ながら、(一つだけのサイズのフィールドを取り、それだけに1をマッチング):

defmodule Unpack do 
    defmacro testmacro({name, kind}) do 
    quote do 
     <<unquote(name)::unqote(kind)>> = 1 
    end 
    end 
end 

システムは、それがquote/1に無効な引数を持っていると言われます。これは、ビットストリングパターンマッチングで使用される "タイプ"が一般的なビットストリングリテラルと同様に特別な形式であり、それらの特定のアイテムが他の場所では使用されないためと考えています。

どうすれば回避できますか?私は5つから20つの異なるフィールドのそれぞれを解凍するパックされた構造体のダース以上の種類があります。もし私がこれをしなければ、おそらく私の手を救うためにおそらくVimマクロに頼るでしょう...しかし、これは、維持するために大量の非常に反復的なコードを持つことを本当に助けません。

+1

は、あなたがそのエラーを与える完全なコードを投稿することができますか? 2番目のスニペットは、typo(unqote)を修正し、RHSでバイナリを使用すると(そのパターンを整数にマッチさせることはできません)、私のために働きます。 – Dogbert

+0

...いいえ、そのコードは私がテストしたiexセッションから直接コピーされました。どうやら、私は誤字が見つかりませんでした。まあ、それはむしろ恥ずかしいです。削除する。 –

+0

@Dogbert問題が小さくても、あなたはまだそれに答えています。先に進んで、それを回答として入れて、私は承認します。 –

答えて

1

2つの事柄:unquoteにタイプミスがあり、パターンが一致するようにRHSをバイナリにする必要があります。これらの変更により、あなたのコードは、私の作品:

defmodule Unpack do 
    defmacro unpack({name, kind}) do 
    quote do 
     <<unquote(name)::unquote(kind)>> = "a" 
    end 
    end 
end 

defmodule Main do 
    import Unpack 

    def main do 
    unpack({foo, integer-8}) 
    IO.inspect foo 
    end 
end 

Main.main 

出力:

97 
関連する問題