F#では、引数は一個で返す値も一個という大原則が有るらしい。6行目や7行目は複数の引数を持っているように見えます。6行目は7行目のシンタクスシュガーらしい。8行目から10行目で、引数が一個を実現しているようです。今のとこは覚えておくことにして、大原則だけは、理解しておいたほうが良いんでしょう。
まだまだ理解不足です。(笑)
実行後の画面。
マイクロソフトの説明
前のセクションで示した例の多くは、F# の関数宣言で暗黙的な "カリー化" を利用することで、より簡潔に記述できます。 カリー化とは、複数のパラメーターを持つ関数を、それぞれが単一のパラメーターを持つ一連の埋め込み関数に変換するプロセスです。 F# では、複数のパラメーターを持つ関数は本質的にカリー化されます。 たとえば、前のセクションの compose
は、次に示すように、3 つのパラメーターを使用する簡潔なスタイルで記述できます。
前にapply関数を定義する意味がわからなかったのですが、今回はcompose関数を定義する意味が分かりません。多分ですが、25行のように書けば、10行目から18行目まで色々書いてますが、集約されるんではと思います。しかもcomposeの定義も要らない。
マイクロソフトの説明。
関数呼び出しの結果値として関数を返すことができるのは、高階関数のもう 1 つの特徴です。 次の例では、1 つの引数 checkFor
を受け取り、結果値として新しい関数を返す item
という関数を定義します。 返された関数は、引数 lst
としてリストを受け取り、その item
内で lst
を検索します。 item
が存在する場合、関数は true
を返します。 item
がない場合、関数は false
を返します。 次のコードでは、前のセクションと同様に、用意されているリスト関数 List.exists を使用してリストを検索します。
何か良く分からないです。試しに英語版をDeepLで訳してみましたのが下です。下の方が分かりやすいでしょう。
関数呼び出しの値として関数を返すことができるのが、高階関数の第二の特徴である。次の例では、checkForはitemという引数をとり、その値として新しい関数を返す関数と定義されている。返される関数は、引数としてリストlstを取り、lstの中にitemがあるかどうかを探す。もしitemが存在すれば、この関数はtrueを返す。itemが存在しない場合、この関数はfalseを返す。前のセクションと同様に、次のコードでは、提供されたリスト関数List.existsを使ってリストを検索しています。
13行目が肝だと思います。関数を定義しているようで、例えば、関数fは、let f x = x * xかまたは、let f = fun x -> x * xが関数を定義しているので、微妙に違いがあります。checkForは、ローカル関数functionToReturnがあって、ラムダ式で一致した要素があるかを調べて、boole値を返す。
17行目を追加しました。
let evenとlet evenSyuseiにリストの名前であるintslistを使ってみました。どうやら、一般的に使うxとかaと、同様に処理されてるようです。つまり関数の定義では、仮の引数は、定義の中だけで有効と言えるようです。
5行目のラムダ式で関数の定義が間違っています。コメントになっています。18行目と違いを意識しておかないとまずいかも。Lambda式だけで関数を定義する場合と引数がある場合、引数なので、仮の名称が来ます。13行目、Lambda式を”()”で括ってます。
5行目evenを訂正します。5行目と6行目は同じ機能の関数です。11行目と12行目は、Lambda式を関数で置き換えてみます。18行目から20行目は、関数を定義しているんですね。xは引数。21行目と22行目は関数ではないですよね。xに相当するものがないですから。多分。
7月上旬は色々有りました。マイナポイント第二弾、健康保険の自己負担率の変更、参議院選挙、安倍元総理の殺害など。こんな中でもウクライナではロシアが侵略を続けてますし、政情不安は世界に広がりつつあります。心配なことばかりです。
先ずは、intのListを用意します。intslistとします。nijyouとevenの関数を用意します。ans1は思った通り。ans2の無名関数は、例題の通り。
結果は出ましたが、true,falseで出ているトコは、数字で出したいのですが…。
ans2を出しているところをevenで置き換えると、結果は思いもよらぬ、方向へ行ってしまいました。何故なんですかね。evenと(fun x -> x % 2 = 0)は意味が同じと思いますが。(even)としても、思った通りにならない。
even intslistを()で括ってみましたが、どうもいかん。関数型プログラミング難しい(笑)例題ばかりやっていると、こういうことには直面しません。
更に不可解は続いて、let ans3 xのトコでも、ぶち当たりました。これは関数を定義したようです。let ans3 intslistとやったら駄目なんですね。どれも理由がわからない。例えばVBだったら関数を呼ぶ場合の引数と、関数での引数は原則、違うので同じでも問題ないと思います。
まだまだ理解が進まない、ゴチャゴチャしてます。(笑と涙)それにしても、猛暑です、暑い。
昨日悩みに悩んでやめてました。今朝やってみたら、なんてこと無くて動いてました。Module1のkasanを使います。
Module1はファイル名Module1.fsの事ではないようです。module Module1のことのようです。importやrequireは無しでいいみたいです。その代わりファイル名とモジュール名を同じにしたほうが混乱しないように思います。但し、プロジェクトには両方のファイルを入れておきます。
入力を使ってみました。stdin.ReadLine() |> stringで文字列として、受け取るようです。
[<EntryPoint>]を書く形式では、通常使う分にはmodule入らないと思いますが、使ってみました。begin、endを使ってみました。endはインデントされることに注意ですかね。上のkasanでは引数はxとyの2個。下のModule1.kasanではx、y、zの3個です。
moduleの疑問が消えたわけでは、無いですが、いくらかは、理解したかなあ?(font)
QiitaにVSCodeでF#のデバッグする方法が載ってました。
デバッグコンソールに実行の様子が出てます。ターミナルからでも実行できます。ブレークポイントも置けました。
上の図でprogramのとこ、net6.0で良いようですが、サイトでは違ってました。”<>”入らない。launch.jsonはマニュアルで追加しました。ファイルを追加したら中の内容は、サイトの通り。
setting.jsonはイジってません。
task.jsonもサイトの通りで出来ました。結構手順をふまないと出来ないようですので、VS2022でやったほうが断然楽だと思います。Linuxとはホルダーとう違いが有ると思います。
Google翻訳で訳しましたが、分かりづらいとこもあるようです。
最後のevenNumberSquareだけ、ほんの少しだけ、付く加えました。もとの参考したコードでは”%d”で出力してましたが、どうやらListでは通用しないようです。削除したら、エラーは出ませんが、4項目以降は省略です。
”%A"指定で出力すると省略されません。しめしめ。(笑)
cametan_42さんのアドバイスではmatchがキーポイントということです。mapとかが関数型プログラミングでは必須の知識なんですね。Rubyでもcollectとか有ったのですが、多分F#のmapと同じだったと思いますが、使わなくてもなんとかなりましたが、関数型プログラミングでは、そうではなく必須のようです。違うかもしれませんけど(苦)
高階関数の前の説明。だと思いますが、WriteLineが関数だと、関数が関数を呼んでるように見えますが、自分で作ったものでないので、文と見ると?単に関数が拘束された変数を呼んでるだけ、に見えます、またまたが、変数の拘束と関数の定義が、全く同じに見えます。
applyIt1などで関数を呼ぶ方法が、分からない。直接書いたほうが良いように思えてしまいます。疑問、なぜ?
追加)
まずは通常使っていた方法。VSCodeでエラーなるので、VSに戻ってやってみた画面です。下の下の画面で0が無いためでした。
上の画面が、普通に使っていたVisual Studioでの画面。ThreeAdditionでxにfloatを付けたら、どの引数も通りました。
floatを取ったら、エラーです。関数の引数から、ThreeAdditionの引数の型を推測はしてくれないようです。
もう一方の書き方は、上のようにopen System []を書く形式だと、moduleは要らないようです。こっちの方がプログラムみたいで良いですが。同じようなことが、Pythonでもありました。
参考にしたサイトはこちら。やはりマイクロソフトのサイトでは分からずです?。
まだ途中ですが、多少分かってきました。上の参考にしたサイトでもちょっとだけ違ってました。open Systemや[]が無くて、printfn文だけでしたが、実行は右下のペイン、ターミナル(POWERSHELL)で行いますし、しかもdotnet run。コンパイルされているものの実行とは違うようです。
ここで大きな疑問、前からありましたが、マイクロソフトのサイトでもありました、REPLを基本とした開発。REPL自体は少しはわかりますが、例えば1+2;;をやってみたところで、どうエディタへ反映させて、プログラミングを作り上げるのでしょうか?
最近の言語では全てそうなっているようです。Scala,Kotlin,Python最後のF#。自分は最初の一行から、統合環境を使うので、これが理解できないんですよ。(笑)
追記)最後に重要なことを落としてました。mainの最後の0です。これが無いとprintfnに赤の波線が引かれて、いかにもprintfn文が間違っているように思いますが、違います。mainも関数、intを返す必要があるんですね。気付かなかった。(涙)これでUbuntuのVSCodeでも出来るかもしれません。がREPLでの開発ができるかは、また別の問題ですかね。
追記2)Ubuntuでやってみあたのですが…。
実行した結果がどこにも見当たりません。エラーにはなりません。最初はprintfnの文だけ表示されました。open Systemや[<EntryPoint>]、0は追加しました。ネタ元サイトを更に読まないといけないようです。(哀)
funListは、関数が要素になってます。どう使うのでしょうか?11行目のBMIculculatorは数字をコメントにしましたが、htが小数点付きだったら、floatにしてからsquareしないとだめですね。squareはこのままでいいんでしょうか?もともとは整数で使ってましたが、floatに変更なって、それでも良きに計らってくれますかね?
32行目のラムダ式は()内が関数と見ると、2つ引数を持った関数です。その上のfstとsndは、やはり外のカッコ内が、関数名と引数になってる、ということですかね?ただtupleになっているということなんですか?