QA@IT
«質問へ戻る

質問を投稿

Gauche の util.match で効率よく木をマッチさせるには?

Gauche の util.match をつかって、次のような簡単な木のパターンマッチをしたいと考えています。

(define ex1 '((1 "two") ("three" 4)))
(define ex2 '(("one" 2) (3 "four")))

ここで、木は 2 つのリストからなり、それぞれのリストは文字列と数値が、1 個づつ順不同で格納されているとします。
文字列と数値のどちらが先にくるかで、全部で 4 通りの場合があるので、ひとつの match をつかって次のような関数を書きました:

(define (match-tree-naive t)
  (match t
         ((((? number? n1) (? string? str1))
           ((? number? n2) (? string? str2)))
          (print (list "number" n1 n2))
          (print (list "string" str1 str2)))

         ((((? number? n1) (? string? str1))
           ((? string? str2) (? number? n2)))
          (print (list "number" n1 n2))
          (print (list "string" str1 str2)))

         ((((? string? str1) (? number? n1))
           ((? number? n2) (? string? str2)))
          (print (list "number" n1 n2))
          (print (list "string" str1 str2)))

         ((((? string? str1) (? number? n1))
           ((? string? str2) (? number? n2)))
          (print (list "number" n1 n2))
          (print (list "string" str1 str2)))

         ))

しかしこれはあまりにも冗長で拡張性もないので、複数の match を組み合わせて再帰的に、以下のように書いてみました。

(define (match-tree t)
  (define (match-tip p)
    (match p
           ((? number? n)
            (print (list "number" n)))
           ((? string? str)
            (print (list "number" str)))))

  (define (match-part p)
    (match p
           ((tips ...)
            (for-each match-tip tips))))

  (match t
         ((part ...)
          (for-each match-part part))))

これで、リストの要素の数などには柔軟に対応できますが、何となく処理が行ったり来たりしてコードが分かりづらいです。

できれば match をたくさん使わずに、このような構造で簡単にパターンマッチする方法はないでしょうか?

Gauche の util.match をつかって、次のような簡単な木のパターンマッチをしたいと考えています。

    (define ex1 '((1 "two") ("three" 4)))
    (define ex2 '(("one" 2) (3 "four")))

ここで、木は 2 つのリストからなり、それぞれのリストは文字列と数値が、1 個づつ順不同で格納されているとします。
文字列と数値のどちらが先にくるかで、全部で 4 通りの場合があるので、ひとつの `match` をつかって次のような関数を書きました:

    (define (match-tree-naive t)
      (match t
             ((((? number? n1) (? string? str1))
               ((? number? n2) (? string? str2)))
              (print (list "number" n1 n2))
              (print (list "string" str1 str2)))
    
             ((((? number? n1) (? string? str1))
               ((? string? str2) (? number? n2)))
              (print (list "number" n1 n2))
              (print (list "string" str1 str2)))
    
             ((((? string? str1) (? number? n1))
               ((? number? n2) (? string? str2)))
              (print (list "number" n1 n2))
              (print (list "string" str1 str2)))
    
             ((((? string? str1) (? number? n1))
               ((? string? str2) (? number? n2)))
              (print (list "number" n1 n2))
              (print (list "string" str1 str2)))
    
             ))

しかしこれはあまりにも冗長で拡張性もないので、複数の `match` を組み合わせて再帰的に、以下のように書いてみました。

    (define (match-tree t)
      (define (match-tip p)
        (match p
               ((? number? n)
                (print (list "number" n)))
               ((? string? str)
                (print (list "number" str)))))
    
      (define (match-part p)
        (match p
               ((tips ...)
                (for-each match-tip tips))))
    
      (match t
             ((part ...)
              (for-each match-part part))))

これで、リストの要素の数などには柔軟に対応できますが、何となく処理が行ったり来たりしてコードが分かりづらいです。

できれば `match` をたくさん使わずに、このような構造で簡単にパターンマッチする方法はないでしょうか?