2016-12-05 5 views
3

Swiftのパーサーコンビネータシステムのコードを理解するための練習としてコードを書いていますが、おそらく私が完全に理解していないため、Swiftのジェネリックスに問題が継続しています。私はエラーを説明しますが、まず、いくつかの背景について説明します。私のコードでは、Parserちょうどタイプの別名である:要するにパーサーコンビネータコードで問題を引き起こすスウィフトジェネリック

typealias Parser<T> = (String) -> (output: [T], remainder: String)?

、パーサは、いずれかの入力を受け取り、次いで返し:

  1. タプル出力項目のアレイと解析対象外と入力の残りの部分、または
  2. nil与えられた入力に対して失敗した場合。次のよう

私の問題を実証コードは次のとおりです。

struct Op { 

} 

func lineOfCode() -> Parser<Op> { 
    return { input in 
     return nil 
    } 
} 

func program() -> Parser<Op> { 
    return { input in 
     return anyNumber(of: lineOfCode()) 
    } 
} 

今、そこに何もしないコードのビットがあるが、問題はによって生成されたパーサのreturn文ですprogram()方法。これは、次のエラーが表示されます。

完全性については

Cannot convert call result type '(String) -> (output: [_], remainder: String)?' to expected type '(output: [Op], remainder: String)?'

は、anyNumber(of:)方法は、入力パーサの...効果的に0であるパー​​サ*を生成するパーサジェネレータです。そのシグネチャは次のとおりです。

anyNumber<T>(of parser: @escaping Parser<T>) -> Parser<T> 
、つまりこの「アンダースコアこのエラーは私にとって非常に不可解であると私は私がそれを作ることになっています何かを見つけることができないとして、私は非常に、私の非常に特定の問題上の任意の洞察力に感謝

私には神秘的な "タイプ"です。

+0

「anyNumber」は一般的であるため、戻ってくる配列の並べ替えに関して、もう少し仕様を必要としているように見えます。それは '出力:[_]'が示唆しているようです。 'anyNumber 'と書く方法はありますか? – sdasdadas

+0

@sdasdadas Swiftは残念ながらJavaではないので、メソッドを呼び出すときにジェネリック型のパラメータを明示的に指定することはできません。すべてのパラメータを推論する必要があります。 – Sweeper

答えて

3

私はprogramでコードを拡大し、問題の根本を発見した:

func program() -> Parser<Op> { 
    return { input in 
     let anyNum = anyNumber(of: lineOfCode()) 
     return anyNum 
    } 
} 

エラー今言う:

cannot convert return expression of type '(String) -> (output: [Op], remainder: String)?' to return type '(output: [Op], remainder: String)?'

それは今ではないがより明確です!

anyNumberは、Parser<T>を返します。クロージャ内で戻り値anyNumberを返したいとします。ただし、このクロージャの戻り値の型はParser<T>ではありません。それは(output: [Op], remainder: String)?です。型の不一致!

私はあなたがこれを代わりにしたいと思いますか?

func program() -> Parser<Op> { 
    return anyNumber(of: lineOfCode()) 
} 
+0

うん!あたかもパーサジェネレータではなく、パーサジェネレータジェネレータを実装しているかのように見えます。あなたが綿密に見ていないならば、その閉鎖の略語は消えるようです! – phrz

関連する問題