2017-12-13 2 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}])을 쓰고 필요한 struct, typedef를 자동으로 생성 할 수 있도록 매크로에서 처리하는 것이 매우 유용 할 것입니다. 및 고정 크기의 임의의 명명 된 필드에 대한 언 패킹 (unpacking) 기능을 제공합니다. 이를 확장 할 수도 있지만 튜플에 세 번째 필드를 추가하여 가변 크기의 유형을 처리하는 함수를 전달할 수 있습니다. 나는 그것의 간단한 버전을하려고 할 때 불행하게도, (하나 개의 크기 필드를 복용하고, 만에 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

은 그 오류를 제공 전체 코드를 게시 할 수 있습니까? 두 번째 스 니펫은 typo (unqote)를 수정하고 RHS에서 바이너리를 사용하면 (정수와 패턴을 일치시킬 수 없음) 나를 위해 작동합니다. – Dogbert

+0

... 아니, 그 코드는 내가 테스트 한 iex 세션에서 직접 복사되었다. 분명히, 나는 오타를 놓쳤다. 글쎄, 그건 당황 스럽네. 삭제 중. –

+0

@ 도그 버트 (Dogbert) 문제가 작더라도 여전히 대답을합니다. 계속해서 응답으로 입력하면 승인됩니다. –

답변

1

두 가지 : 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