次のコードでは、反復ごとにアクティブパターンの結果を3回再利用する必要があります。すなわち
match tree.Parent, postion with
アクティブパターンの結果を保存できることがわかりました。すなわち
let pos = ((|Root|Nil|Single|First|Inner|Last|Unknown|) (tree.Parent, position))
私が理解できなかったのは、アクティブパターンの結果を一致ステートメントで使用できるかどうかでした。すなわち
match pos with
| ??? -> printf "("
問題は、保存されたアクティブパターンの結果をmatchステートメントで使用できるかどうかです。
もしそうなら、どのように?そうでない場合は、論理的に意味があるように説明する必要があります。
おそらくなぜそうではないかの例。つまり、言語仕様、シンタックスシュガーは、アクティブなパターンの結果をバインドすることを許可するべきではありませんでした。ExprItemsとPatItems
F#2.0言語仕様(2010年4月)を調べました http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/spec.html#_Toc270597500
しかし、私は答えを確認するものを何も認識しませんでした。
編集
コードをに変更した場合
let pos = (|Root|Nil|Single|First|Inner|Last|Unknown|) (tree.Parent, position)
match pos with
| Choice1Of7 (tree.Parent, position) -> printf "("
| _ -> ()
Choice1Of7の後に(tree.Parent、position)に対して次のエラーが発生します。
この式はユニット型であることが期待されていましたが、ここでは'a*'b型です。
ブライアンが提案したように
match pos with
| Choice1Of7 () -> printf "("
| _ -> ()
編集を終了
注:私がこれを試したコードは次のとおりですが、それが解決するものに対してより良いアルゴリズムを見つけました。
// An F# function to print a CommonTree as an s-expression
//
// Note: Because the CommonTree data structure was created allowing null values,
// the null value has to be handled.
//
let commonTreeToSExpression100 (tree : BaseTree) =
// Define Active Pattern to create new view of node, i.e. BaseTree
// for position in list instead of content.
// Note: The name of the active pattern function is "|Root|Nil|Single|First|Inner|Last|Unknown|"
let (|Root|Nil|Single|First|Inner|Last|Unknown|) (tree : ITree , position) =
let parent = tree :?> BaseTree
match parent with
| null -> Root
| _ ->
let list = parent.Children
match obj.ReferenceEquals(list,null) with
| true -> Nil // This should never happen.
| false ->
let count = list.Count
// TODO: Handle count = 0
if (count = 1) then Single
elif (count > 1) && (position = 0) then First
elif (count > 1) && (position = count - 1) then Last
elif (count > 1) && (0 < position) && (position < count - 1) then Inner
else Unknown // This should never happen.
// Define walk/print function
let rec printTree (tree : BaseTree) (position) =
// Start an s-expression
match tree.Parent, position with
| Root | Single | First -> printf "("
| _ -> ()
// Note: Can save the result of an active pattern which is type Choice<uint,uint,uint,uint,uint,uint,uint>.
// The question is can the saved active pattern result be used in a match statement?
// If so, how? If not, need to explain it so that it logicaly makes sense.
// Give examples of possibly why not. i.e. Language Specification, syntactic sugar,
// should not have allowed result to be bound, not in symbol table but other table.
//let pos = ((|Root|Nil|Single|First|Inner|Last|Unknown|) (tree.Parent, position)) // This works / is allowed
// match pos with
// | ??? -> printf "(" // Can this work? What should ??? be?
// | _ -> ()
// Visit the node
printf "%s" tree.Text
// Space out the values
match tree.Parent, position with
| Root | First | Inner -> printf " "
| _ -> ()
// Process the children
// Note: BaseTree holds the ChildIndex, if this property was not available
// then the use of Seq.iter whould have to be changed for a mechanism that
// would allow the calculation of the child index as the list is processed.
match tree.Children with
| null -> ()
| _ ->
tree.Children |> Seq.iter (fun x -> printTree (x :?> BaseTree) x.ChildIndex)
printf " "
// End an s-expression
match tree.Parent, position with
| Root | Single | Last -> printf ")"
| _ -> ()
// Call the walk/print function
printTree tree 0
// Since s-experssions print as single line,
// print a newline so that what is printed after this
// is not on the same line as this s-expression.
printfn ""