差別化された組合員の名前付きフィールドにアクセスするにはどうすればよいですか?DUメンバーの名前付きフィールドへのアクセス
例:一般的に
type Point = | Point of x : int * y : int
let p = Point(3, 1)
// how to access x-value or y-value of p here?
差別化された組合員の名前付きフィールドにアクセスするにはどうすればよいですか?DUメンバーの名前付きフィールドへのアクセス
例:一般的に
type Point = | Point of x : int * y : int
let p = Point(3, 1)
// how to access x-value or y-value of p here?
、名前のフィールドを持つ組合はちょうど、他の組合タイプのように動作:あなたはmatch
を経由してフィールドにアクセスします。
let x, y =
match p with
| Point (x1, y1) -> x1, y1
The F# documentationもマッチングの方法に言及していますいくつかの名前付きパラメータのみ。あなたのケースでは、これはあなたが書くことができます意味:
let xOnly =
match p with
| Point (x = x1) -> x1
あなたが持っているすべてを単一のケースの場合は、@ p.s.w.gで解答を参照してください。その答えのコードは、すべての差別化された組合に対して一般的です。名前のフィールドを持つシングルトン労働組合のために、あなたは上に示した特別な構文を使用して書き込むことができます。
let Point(x = myX) = p
これはmyX
にフィールドx
の値をバインドします。
PSコメントごとに:p.x
を実行すると、すぐにフィールドを読み取れないのはなぜですか?差別化されたユニオンを小さなオブジェクト階層と考えることができます(そして、そのようなものを使用してください。discriminated union documentation:「小さなオブジェクト階層のより簡単な代替手段として識別されたユニオンを使用することができます」を参照)。
type Shape = | Circle of r: float | Square of float
Shape
をスーパークラスとして表示できます。 Circle
およびSquare
は2つの派生クラスであり、それぞれが単一のfloat
プロパティを持ちます。作成するCircle
またはSquare
の各インスタンスは、アップキャストされてShape
になります。
これで、フィールドをすぐに読み取ることができない理由が明らかになります。最初に、派生したクラスのうちのどれを探しているのかを特定する必要があります。 。
このオブジェクト階層ビューは、川下ユーザーは、F#と内部でどのように扱われるかに非常に密接に一致します。
> typeof<Shape>.GetNestedTypes()
|> Seq.iter (fun t ->
let p = t.GetProperties()
let s =
p
|> Array.map (fun p -> sprintf "%s: %s" p.Name p.PropertyType.Name)
|> String.concat "; "
printfn "Nested type %s: %i Properties %s" t.Name p.Length s
);;
Nested type Tags: 0 Properties
Nested type Circle: 4 Properties r: Double; Tag: Int32; IsCircle: Boolean; IsSquare: Boolean
Nested type Square: 4 Properties Item: Double; Tag: Int32; IsCircle: Boolean; IsSquare: Boolean
:あなたは反射におけるDUの種類を見れば、あなたは労働組合の例と同じ名前を持つ2つのネストされたタイプが表示されます
実際のデータは、サブクラスのプロパティに存在します。 Circle
については、名前付きフィールドを使用した場合は、プロパティーr
が表示されます。 Square
については、Item
プロパティ(または複数の引数がある場合はItem1
,Item2
)のデータがあります。残りの部分はコンパイラによって生成されます。サブクラスを素早く区別するために使用される数値Tag
と、サブクラスチェック用の2つのboolプロパティ。
スーパークラス自体は唯一のコンパイラで生成された特性を持っている:あなたの例のような単一のケースを判別組合については
> typeof<Shape>.GetProperties()
|> Seq.iter (fun p -> printfn "Property %s" p.Name);;
Property Tag
Property IsCircle
Property IsSquare
を、あなたはmatch-with
表現を使用する必要はありません。`
let (Point (x, _)) = p
printf "%i" x // 3
'聞かせP2 =ポイント(PX、PY)のようなものを達成するための任意の短い構文はありません。
それとも
x
を取得し、y
を無視する:あなたはこれを行うことができます? –一般的なケースでは、複数のユニオンケースがあります。 'p'は' Point'の場合を表すオブジェクトですが、他のいくつかのユニオンの場合もあります。あなたがOOPの言葉でそれを考えたければ: 'p'はスーパークラスのインスタンスですが、あなたは派生クラスのフィールドにアクセスしようとしています。 'match'はキャストと等価で、フィールドにアクセス可能にします。 –
@no_mindset、単一のケースしか持たず、より短い構文に興味があるなら、ユニオンではなくレコードを使用します。 –