5

これは F# のよく知られた制限だと思いますが、適切な回避策が見つかりませんでした…</p>

コードは次のとおりです (できるだけ単純にしようとしたので、おそらく意味がないように見えます)。

[<ReflectedDefinition>]
type Human (makeAName: unit -> string) as self =
    let mutable cats : Cat array = [| |]
    do
        // get a cat
        cats <- Array.append cats [| new Cat (self, makeAName ()) |]
    member this.Cats = cats
and
 [<ReflectedDefinition>]
 Cat (owner : Human, name : string) = class end

コンパイラは次のように述べています。

エラー FS0452: 引用符にインライン アセンブリ コードまたは配列のパターン マッチングを含めることはできません

実際、as selfすべてを破壊するのは と 配列プロパティ ゲッターの組み合わせです。

ここでのポイントは次のとおりです。

  • WebSharper にコレクションを JavaSript 配列に変換してもらいたいので、本当に配列を使いたいと思っています。
  • コンストラクターには自己識別子が本当に必要です。
  • 私は本当にクラスが必要です (つまり、機能的なスタイルは機能しません)。
  • メソッドごとの自己識別子 ( member this.Foo) は正常に機能します。

私が考えることができる 1 つの回避策は、コンストラクターを非公開にし、静的メソッドを使用してオブジェクトを構築することです。このように私は必要ありませんas self。しかし、それはばかげています。

より良いオプションはありますか?


アップデート:

さらに簡単な例を次に示します。

[<ReflectedDefinition>]
type User (uid: int) as self =
    let ROOT_UID = 0
    member this.isRoot = (uid = ROOT_UID)

クラス定数を定義することas selfさえできません。それは実際には別の質問ですが、ここで質問します: この特定のケースでクラス定数を定義するにはどうすればよいですか?


4

1 に答える 1

8

ばかげているとはまったく思いません。実際には、WebSharper を使用しないコードであっても、わかりやすくするために静的コンストラクター メソッドを好みます。IntelliFactory コードベース全体で、使用することはあったとしてもめったにありませんself

F# コンパイラと引用符の 2 つの厄介な制限にぶつかっています。ご指摘のとおり、静的メソッドはself問題を解決できます。

[<ReflectedDefinition>]
type Human private (cats: ref<Cat []>) =
    member this.Cats = !cats

    static member Create(makeAName: unit -> string) =
        let cats = ref [| |]
        let h = Human(cats)
        let cat = Cat(h, makeAName())
        cats := [| cat |]
        h

and [<ReflectedDefinition>] Cat (owner: Human, name: string) =
    class
    end

refこれを実現する方法は他にもたくさんあります。たとえば、間接化を取り除くことができます。

第 2 に、単純な静的メソッドであっても、配列操作を含むコードを使用FS0452することがよくあります。ReflectedDefinitionこれは通常、直接配列アクセス ( Array.iterArray.map) の代わりにライブラリ関数を使用することで解決できます。

2 番目の例では、これが本当に必要です。

[<ReflectedDefinition>]
module Users =

    [<Literal>]     
    let ROOT_UID = 0

    type User(uid: int) =
        member this.isRoot = (uid = ROOT_UID)

[<Literal>]アノテーションを使用すると、定数のパターン マッチが可能になります。これは、定数が複数ある場合に便利です。

あなたのポイントのために:

  1. 私は本当に配列を使いたいです - それは問題ないはずです
  2. 私は本当に自己識別子が必要です-コンストラクターがそうではないのと同じように、それは決して必要ではありません
  3. 私は本当にクラスが必要です(つまり、機能的なスタイルは機能しません)-間違いなくそうではありません
  4. メソッドごとの自己識別子 (メンバー this.Foo) は正常に機能します - はい、便利です
于 2013-03-28T11:58:34.530 に答える