Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
    bleis-tift
    @bleis-tift
    F#ではenumはすべての値を=で指定する必要があります。
    enumの網羅性ですが、enumは本体が数値なので、指定したケース以外の値も数値をキャストしたりビット演算することで作り出せます。そのため、0に対応するケースがあったとしても結局網羅性は担保されません
    つまり、コンパイラは他の値の考慮が足りないとして警告を出します。
    次に、F#のタプルですが、Item1Item2によるアクセスはできません
    bleis-tift
    @bleis-tift
    System.Tuple<...>で表されてはいるのですが、別物と考えておいた方が色々といいかもしれません。
    次は細かいところですが、F#のリストは読み取り専用の順方向リンクリストのようなものではなく、読み取り専用の順方向リンクリストそのものです。
    type 'a list =
      | []
      | (::) of 'a * 'a list
    こんな定義のイメージです
    次に「演算子」という言葉の使い方ですが、:?[| ... |]も演算子ではありません。
    bleis-tift
    @bleis-tift
    演算子であれば( <op> )のようにして関数化可能ですが、どちらも不可能です
    :?はパターン、[| ... |]は配列式を構成する文法です
    Kouji Matsui
    @kekyo
    うほぉ... 詰め甘 enumが判別共用体になっているというのは、あのエラーメッセージから信じ込んでいたんですが、判別共用体が0とみなされる場合があるという事?
    bleis-tift
    @bleis-tift
    判別共用体が0とみなされるとは?
    Kouji Matsui
    @kekyo
    // "警告 FS0025: この式のパターン マッチが不完全です
    // たとえば、値 'enum<Modes> (0)' はパターンに含まれないケースを示す可能性があります。"
    bleis-tift
    @bleis-tift
    それは判別共用体ではなく、enumですね。enumの場合、0のケースがあろうがなかろうが、定義したケースによってすべてを網羅するのは不可能です。ワイルドカードパターンか変数パターンを使う必要があります。
    Kouji Matsui
    @kekyo
    =で値を指定するとenumになり、指定しないと判別共用体となるということで、確かにそうだ...
    到達しないケースの検出、は書いてる途中で気がついてました。改訂するときに盛り込んでみます
    bleis-tift
    @bleis-tift

    次に、:?パターンですが、これも組み合わせる機会はあって、例えばtype t = Hoge of objのような型があったときに、

    let f = function
    | Hoge(:? string) -> "str"
    | _ -> "other"

    のように、何かのパターンとネストして使うことがあります。

    次に複数の値を持ったケースを持つ判別共用体の定義方法ですが、

    // タプルで定義
    type Node =
      | Element of (string * (Node seq))
      | Text of string
    // タプルを使わずに定義
    type Node =
      | Element of string * Node seq
      | Text of string

    の2種類があって、後者の方がより効率的な型を生成します。

    タプルを使うと、生成される型のフィールドには当然タプルが現れますが、タプルを使わない場合はそれぞれ独立したフィールド(上の場合だと2つのフィールド)が直接生成される型のフィールドとして定義されます。
    効率以外にもコード上に現れてくる違いとして、タプルを使わずに定義した場合はmatch式でタプルとして受け取れない、というものがあります。
    bleis-tift
    @bleis-tift
    タプルを使って生成はできるのに対称性が取れてない感じがしますが、おそらくタプルを使って生成できるのは複数引数の関数とタプルの相互変換のほうの理屈からできるようになっていると思われます。
    Kouji Matsui
    @kekyo
    :? の使われる機会があまりないというのは言い過ぎですね。もうちょっと練ってみます。
    bleis-tift
    @bleis-tift
    機能的にはタプルで定義したほうが便利なんですが、実際にはタプルを使わずに定義することの方が多いです。
    Kouji Matsui
    @kekyo
    なるほど タプルで定義するかどうかの部分、混乱を生まずに利点をうまく説明出来るだろうか...
    bleis-tift
    @bleis-tift
    難しいと思いますねw
    Kouji Matsui
    @kekyo

    この辺、検証してて確かに「あれ、これだとダメだな」とか迷ってた記憶がある

    うっ... markdownだった
    bleis-tift
    @bleis-tift
    正直、タプルで定義しない場合でもタプルで受け取れた方がいいと思うんですが、昔その提案をして蹴られたことがあります
    Kouji Matsui
    @kekyo
    理由は何て?
    bleis-tift
    @bleis-tift
    Githubではなく、fsbug(メール)だかなんだかでやり取りしていたころなので、ちょっと思い出せないですね・・・
    Kouji Matsui
    @kekyo
    使い分けれたほうが良い(効率とか?)
    bleis-tift
    @bleis-tift
    User Voiceに挙げてみてもいいかも?
    次に、バナナクリップについてですが、これを「演算子」とするのはF#の演算子と紛らわしいため、できれば避けたい用語です。
    「この括弧はバナナクリップと呼ばれます」くらいにしておいた方が好みです。
    omanuke
    @omanuke
    タプルで定義しない方はフィールド名?つけられるので大抵そっち使ってます
    Kouji Matsui
    @kekyo
    配列と一緒で文法、かな
    bleis-tift
    @bleis-tift
    type t = Hoge of xxx:int * Yyy:string // 大文字始まりにするか小文字始まりにするかで悩む
    大文字派
    Kouji Matsui
    @kekyo
    あー!それや。フィールド名のようなものが定義できたような気がしてたけど、再現できず、気のせいかと...
    bleis-tift
    @bleis-tift
    あぁ、タプルだとタプル自体にしか付けれませんからね
    type t = Hoge of Xxx:(int * string)
    omanuke
    @omanuke
    小文字派(´・ω・`)
    Kouji Matsui
    @kekyo
    あの説明だと、タプル使う事に抵抗ないと書いたけど、やっぱりちょっと抵抗ある気も(自分で書いてて)アレだった
    bleis-tift
    @bleis-tift
    次に細かいところですが、IsPlusEvenよりもIsPositiveEvenの方がいいかな、と思いました
    Kouji Matsui
    @kekyo
    (*´Д`)
    bleis-tift
    @bleis-tift
    あと、OptionをNullable相当とするのは抵抗があります。
    System.Nullableは値型しか持てませんし、System.Nullable + 参照型としても、型の扱いにかなり違いがあるので。
    例えば参照型ではnullであろうがなかろうがその型のメンバーにアクセスできるのに対し、Optionでは中に含む型のメンバーにはアクセスできない
    Kouji Matsui
    @kekyo
    どの辺りですか? C#erに説明するには(確かに頭の中では別物なんですが)値のあるなしを保持できると言う意味で引き合いに出しました