2017-05-07 15 views
5

シンプルな数学トークナイザを書き、新しいC#pattern matching機能を使用しようとします。私はif-else ifチェーンを使用せずに、条件によって一致させたいので、私はcase var _を使用していパターン一致の場合

public IEnumerable<IToken> Tokenize(string input) 
    { 
     const char decimalSeparator = '.'; 
     string inputWithoutSpaces = input.Replace(" ", string.Empty); 
     var numberBuffer = new StringBuilder(); 
     var letterBuffer = new StringBuilder(); 
     foreach (char c in inputWithoutSpaces) 
     { 
      switch (c) 
      { 
       case var _ when IsTerm(c, letterBuffer): 
        if (numberBuffer.Length > 0) 
        { 
         yield return EmptyNumberBufferAsLiteral(numberBuffer); 
         yield return new Operator('*'); 
        } 
        letterBuffer.Append(c); 
        break; 
       case decimalSeparator: 
       case var _ when IsDigit(c): 
        numberBuffer.Append(c); 
        break; 
       case var _ when IsOperator(c): 
        if (numberBuffer.Length > 0) 
        { 
         yield return EmptyNumberBufferAsLiteral(numberBuffer); 
        } 
        if (letterBuffer.Length > 0) 
        { 
         yield return EmptyLetterBufferAsTerm(letterBuffer); 
        } 
        yield return new Operator(c); 
        break; 
      } 
     } 
     if (numberBuffer.Length > 0) 
     { 
      yield return EmptyNumberBufferAsLiteral(numberBuffer); 
     } 
     if (letterBuffer.Length > 0) 
     { 
      yield return EmptyLetterBufferAsTerm(letterBuffer); 
     } 
    } 

が、私はvar variableNameを指定せずにcase whenを書き込むことができませんでしだ:

トークナイザは非常に簡単です。

このような操作を行うための方法はありますか?あるいは、これらのことを行うための推奨される方法ですか?

+1

まあ、スイッチ文で定数を使用するという要件を回避するために、パターンマッチングを悪用しているので、実際に回避する方法はありません。さらに、私はあなたのロジックがおそらくは/ if文と同じように良く適合していると思います。 – DavidG

+1

@DavidG逆に、アクティブパターンのように見えます。これはトークナイザとパーサの実装をもっと簡単にします。 C#7のパターンマッチングにはいくつかの重要な機能がありません。アクティブパターンはその1つです。 –

+0

@PanagiotisKanavosはい、でも私は今すぐ利用できる言語について話しています。私はかなり多くのパターン一致するものが将来C#に入ってくるのを確かめるでしょう。(主にF#と思っています) – DavidG

答えて

2

一般的にアクティブパターンと呼ばれるものを使用して、このようなパターンマッチングを行うための「派手な」方法があります。 C#は(まだ)アクティブパターンをサポートしていませんが、see this answer for an example of what they might look like if/when implementedです。あなたは、C#、please upvote it on the csharplang github repoの将来のバージョンでこの機能を確認したい場合は

switch (c) 
{ 
    case Term(letterBuffer): 
     ... 
     break; 
    case decimalSeparator: 
    case Digit(): 
     ... 
     break; 
    case Operator(): 
     ... 
     break; 
} 

だからアクティブなパターンを使用して、あなたのコードのようなものを探して終わるでしょう。

一方、ifのステートメントは、他の人が言っていたとおりにするか、ガード時に使用するかを選択するのが制限されています。あなたは本当に好みのスタイルの問題です。

+0

「逃した」ケースを防ぐために、最初に徹底的にマッチングされています。 –

+1

@PanagiotisKanavosは完全に同意します。残念ながら私は、他のオブジェクト指向関連の機能が好きで、適切なパターンマッチングが後ろに押し戻されると思っています。 Opの疑似アクティブパターンはしばらくの間のやり方です。 –

関連する問題