Fに飛び蟌みたす。 C開発者向けハンドブック

この投皿では、コヌドをCからFに「翻蚳」する方法に぀いおは説明したせん。異なるパラダむムにより、これらの各蚀語がそのタスクの範囲で最適になりたす。 ただし、コヌドをあるパラダむムから別のパラダむムに倉換するこずを考えなければ、関数型プログラミングのすべおの利点をより速く理解するこずができたす。 奜奇心、盛で奜奇心and盛で、たったく新しいこずを孊ぶ準備ができたした。 さあ始めたしょう



F -developersのロシア語コミュニティの翻蚳シリヌズのすべおの資料は、タグ#fsharplangruで芋぀けるこずができたす。

前の蚘事「 なぜFを䜿甚する必芁があるか」で、Fを今すぐ詊す䟡倀がある理由を説明したした。 次に、アプリケヌションの成功に必芁な基本を分析したす。 この投皿は、C、Java、たたはその他のオブゞェクト指向蚀語に粟通しおいる人を察象ずしおいたす。 すでにFで蚘述しおいる堎合、これらの抂念はおなじみのはずです。


違いにたっすぐに


関数型プログラミングの抂念を勉匷する前に、小さな䟋を芋お、FがCずどのように異なるかを刀断したしょう。 これは、2぀の機胜ず結果を衚瀺する基本的な䟋です。


let square x = x * x let sumOfSquares n = [1..n] //      1  n |> List.map square //      |> List.sum //  ! printfn "   5    %d" (sumOfSquares 5) 

型の明瀺的な指瀺はなく、セミコロンや䞭括匧はありたせん。 括匧は1か所で䜿甚されたす。入力倀ずしお数倀5を䜿甚しおsumOfSquares関数を呌び出し、結果を画面に衚瀺したす。 パむプラむン挔算子|> パむプラむン挔算子は、Unixのパむプラむンパむプ、パむプず同じ方法で䜿甚されたす。 squareは、 List.map関数にパラメヌタヌずしお盎接枡される関数ですFの関数は倀、ファヌストクラス関数ずしお扱われたす。


実際にはさらに倚くの違いがありたすが、最初に基本的なこずに察凊する必芁がありたす。それらはFを理解するための鍵だからです。


CおよびF䞻芁抂念の䞀臎


次の衚は、CずFの重芁な抂念のいく぀かの察応を瀺しおいたす。 これは意図的に短く䞍完党な説明ですが、Fの孊習の始めに芚えおおくず簡単です。


Cおよびオブゞェクト指向プログラミングFず関数型プログラミング
倉数䞍倉の倀
説明曞衚珟
メ゜ッドを持぀オブゞェクト皮類ず機胜

いく぀かの甚語のクむックチヌトシヌト



C列に瀺されおいるものはすべおFでも可胜であるそしお非垞に簡単に実装できるこずは泚目に倀したす。 F列には、はるかに耇雑ではありたすが、Cでできるこずもありたす。 巊の列の芁玠はFで「䞍良」ではなく、その逆も同様です。 メ゜ッドを備えたオブゞェクトはFでの䜿甚に最適であり、状況に応じお最適な゜リュヌションであるこずがよくありたす。


倉数ではなく䞍倉の倀


関数型プログラミングで最も珍しい抂念の1぀は䞍倉性䞍倉性です。 圌は、関数型プログラミング愛奜家のコミュニティで十分な泚目を济びおいないこずがよくありたす。 ただし、デフォルトで倀が倉曎されおいない蚀語を䜿甚したこずがない堎合、これは倚くの堎合、これ以䞊の孊習を行うための最初で最も重芁な障害ずなりたす。 䞍倉性は、ほずんどすべおの関数型蚀語の基本抂念です。


 let x = 1 

前の匏では、倀1が名前x関連付けられおいたす。 その存圚を通じお、名前xは倀1を参照し、倉曎できたせん。 たずえば、次のコヌドはxの倀を再割り圓おできたせん。


 let x = 1 x = x + 1 //     ! 

代わりに、2行目は、 x x + 1等しいかどうかを決定する比范です。 <-挔算子ずmutable修食子を䜿甚しおmutate xを倉曎倉曎する方法がありたす詳现に぀いおは、 可倉倉数を参照しおください。 Fを別の必須プログラミング蚀語ず芋なさない堎合、その最匷点を䜿甚できたす。


䞍倉性は基本的に、問題を解決するための通垞のアプロヌチを倉えたす。 たずえば、 forルヌプおよびその他の呜什型プログラミングの基本操䜜は、Fではあたり䜿甚されたせん。


より具䜓的な䟋を考えおみたしょう。入力リストの数倀を2乗したいずしたす。 Fで行う方法は次のずおりです。


 //  ,     let square x = x * x let getSquares items = items |> List.map square let lst = [ 1; 2; 3; 4; 5 ] //    F# printfn "  %A  %A" lst (getSquares lst) 

この䟋ではforルヌプがないこずに泚意しforください。 抂念レベルでは、これは呜什型コヌドずは倧きく異なりたす。 リスト内の各アむテムを二乗したせん。 入力リストにsquare関数を適甚し、二乗倀を取埗したす。 これは非垞に埮劙な違いですが、実際には倧幅に異なるコヌドに぀ながる可胜性がありたす。 たず、 getSquares関数は実際に完党に新しいリストを䜜成したす。


䞍倉性は、リスト内のデヌタを管理する単なる別の方法よりもはるかに広い抂念です。 参照の透過性の抂念はFにずっお自然であり、システム蚭蚈ずこれらのシステムの䞀郚がどのように組み合わされるかに倧きな圱響を䞎えたす。 システムの機胜特性は、予期しない堎合に倀が倉曎されない堎合により予枬可胜になりたす。


さらに、倀が䞍倉の堎合、同時プログラミングが容易になりたす。 可倉状態のためにCで発生するいく぀かの耇雑な問題は、Fではたったく発生したせん。 Fは、すべおのマルチスレッドず非同期の問題を魔法のように解決するこずはできたせんが、倚くのこずが簡単になりたす。


呜什ではなく匏


前述のように、Fは匏を䜿甚したす。 これは、ステヌトメントがほずんどすべおに䜿甚されるCずは察照的です。 䞡者の違いは䞀芋取るに足らないように思えるかもしれたせんが、留意すべきこずが1぀ありたす。衚珟は意味を生み出したす。 手順-いいえ。


 // 'getMessage' --  ,  `name` -   . let getMessage name = if name = "Phillip" then // 'if' -  . "Hello, Phillip!" //     .    else "Hello, other person!" //      . let phillipMessage = getMessage "Phillip" // getMessage,  ,  .      'phillipMessage'. let alfMessage = getMessage "Alf" //      'alfMessage'! 

前の䟋では、FをCのような呜什型蚀語ず区別するいく぀かのポむントを芋るこずができたす。



このアプロヌチはCずは非垞に異なりたすが、ほずんどの堎合、Fでコヌドを蚘述するずきに自然に思えたす。


少し深く掘り䞋げるず、Fで呜什さえ匏を䜿甚しお蚘述されたす。 このような匏は、タむプunit倀を返したす。 unit Cのvoidに少し䌌おいvoid 


 let names = [ "Alf"; "Vasily"; "Shreyans"; "Jin Sun"; "Moulaye" ] //  `for`.   'do' ,          `unit`. //    ,     . for name in names do printfn "My name is %s" name // printfn  unit. 

前のforルヌプの䟋では、すべおがタむプunitです。 unit匏は、戻り倀を持たない匏です。


F配列、リスト、およびシヌケンス


前のコヌド䟋ではF配列ずリストを䜿甚しおいたした。 このセクションでは、いく぀かの詳现に぀いお説明したす。


Fはいく぀かのタむプのコレクションを提䟛し、最も䞀般的なものは配列、リスト、およびシヌケンスです。



Fの配列、リスト、およびシヌケンスには、匏の特別な構文もありたす。 これは、プログラムでデヌタを生成する必芁があるさたざたなタスクに非垞に䟿利です。


 //     100   let first100Squares = [ for x in 1..100 -> x * x ] //   ,  ! let first100SquaresArray = [| for x in 1..100 -> x * x |] // ,       // //    Seq.take! let odds = let rec loop x = //     seq { yield x yield! loop (x + 2) } loop 1 printfn " 3  : %A" (Seq.take 3 odds) // : " 3  : seq [1; 3; 5] 

F関数ずLINQメ゜ッドの察応


LINQメ゜ッドに粟通しおいる堎合、次の衚はFの同様の関数を理解するのに圹立ちたす。


LINQF関数
Wherefilter
Selectmap
GroupBygroupBy
SelectManycollect
Aggregatefoldたたはreduce
Sumsum

たた、 Seq 、 ListおよびArrayモゞュヌルにも同じ関数セットが存圚するこずに気付くかもしれたせん。 Seqモゞュヌル関数は、シヌケンス、リスト、たたは配列に䜿甚できたす。 配列ずリストの関数は、それぞれFの配列ずリストにのみ䜿甚できたす。 たた、Fのシヌケンスは遅延型であり、リストず配列ぱネルギッシュです。 リストたたは配列でSeqモゞュヌル関数を䜿甚するず、遅延蚈算が必芁になり、戻り倀の型はシヌケンスになりたす。


前のセクションには倚くの情報が含たれおいたすが、Fでプログラムを䜜成するず、盎感的になりたす。


機胜コンベダ


前のコヌド䟋で|>挔算子が䜿甚されおいるこずに気づいたかもしれたせん。 UNIXのパむプラむンに非垞に䌌おいたす。巊に䜕かを取り、右に䜕かの入力に枡したす。 この挔算子「パむプ」たたは「パむプラむン」ず呌ばれるは、 機胜的なパむプラむンを䜜成するために䜿甚されたす。 以䞋に䟋を瀺したす。


 let square x = x * x let isOdd x = x % 2 <> 0 let getOddSquares items = items |> Seq.filter isOdd |> Seq.map square 

この䟋では、 itemsは最初にSeq.filter関数の入力に枡されたす。 次に、 Seq.filter sequenceの戻り倀がSeq.map関数の入力に枡されたす。 Seq.mapの実行結果は、 getOddSquares関数の出力です。


コンベダヌのオペレヌタヌは非垞に䜿いやすいので、それを䜿甚しない人はほずんどいたせん。 おそらくこれはFの最もお気に入りの機胜の1぀です


Fタむプ


Fは.NETプラットフォヌムの蚀語であるため、Cず同じプリミティブ型 string 、 intを持っおいたす。 .NETオブゞェクトを䜿甚し、オブゞェクト指向プログラミングの4぀の䞻芁な柱をサポヌトしたす。 Fはタプル 、およびCにはない2぀の䞻芁なタむプ、レコヌドず識別された共甚䜓を提䟛したす。


レコヌドは、最も文字通りの意味で、比范操䜜を自動的に実装する順序付けられた名前付き倀のグルヌプです。 比范がどのように発生するかを考える必芁はありたせん。リンクの等䟡性を通じお、たたは2぀のオブゞェクト間の等䟡性のカスタム定矩を通じお。 レコヌドは倀であり、倀を比范できたす。 カテゎリ理論の蚀語を話すタむプワヌクです。 それらには倚くの甚途がありたすが、最も明癜なものの1぀は、POCOたたはPOJOずしお䜿甚できるこずです。


 open System //      -. //       type Person = { Name: string Age: int Birth: DateTime } //    `Person`   . //      ,      let p1 = { Name="Charles"; Age=27; Birth=DateTime(1990, 1, 1) } //         let p2 = { Name="Moulaye" Age=22 Birth=DateTime(1995, 1, 1) } //     .     Equals()  GetHasCode(). printfn " ? %b" (p1 = p2) //   `false`,     . 

Fのもう1぀の基本的なタむプは、英語文孊ではunions、PO 、たたはDUずラベル付けされおいたす。 ROは、倚くの名前付きバリアントを衚すタむプです。 カテゎリヌ理論の蚀語では、これは和型ず呌ばれたす。 たた、再垰的に定矩するこずもできるため、階局デヌタの蚘述が倧幅に簡玠化されたす。


 //     . // // ,   -  '  . type BST<'T> = | Empty | Node of 'T * BST<'T> * BST<'T> //       BST<'T> //  BST     ! let rec flip bst = match bst with | Empty -> bst | Node(item, left, right) -> Node(item, flip right, flip left) //   BST let tree = Node(10, Node(3, Empty, Node(6, Empty, Empty)), Node(55, Node(16, Empty, Empty), Empty)) //  ! printfn "%A" (flip tree) 

タダム タグ付けされたア゜シ゚ヌションずFの力を掻甚しお、バむナリ怜玢ツリヌを展開する任意のむンタビュヌを実行できたす。


Nodeバリアントの定矩に奇劙な構文を芋たこずは確かです。 これは実際にはタプル眲名です。 これは、定矩するBSTが空たたはタプル(, , )いずれかであるこずを意味したす。 これは眲名に関するセクションでより詳现に説明されたす 。


すべおをたずめるF60秒で構文


次のコヌド䟋は、F構文のこの優れたレビュヌを曞いたFコミュニティのヒヌロヌであるScott Vlashinの蚱可を埗お提䟛されおいたす。 箄1分で読むこずができたす。 この䟋はわずかに線集されおいたす。


 //      ,  .    . //      . (*       (    ). *) // ======== "" (   ) ========== //   "let"   ()  let myInt = 5 let myFloat = 3.14 let myString = "" //   -     // ========  ============ let twoToFive = [ 2; 3; 4; 5 ] //      , //       . let oneToFive = 1 :: twoToFive //  ::       // : [1; 2; 3; 4; 5] let zeroToFive = [0;1] @ twoToFive //  @    // :       ,    ! // ========  ======== //   "let"    . let square x = x * x //   -   . square 3 //    .   . let add xy = x + y //   add (x,y)!   //   . add 2 3 //  . //    ,   . //     . let evens list = let isEven x = x % 2 = 0 //  "isEven"   ("")  List.filter isEven list // List.filter -    //   :  //  ,    evens oneToFive //   //    ,   . //   ,   "map"   , //    "sum"  . //   "List.map"       "List.sum" let sumOfSquaresTo100 = List.sum (List.map square [ 1 .. 100 ]) //           "|>" //      sumOfSquares,     let sumOfSquaresTo100piped = [ 1 .. 100 ] |> List.map square |> List.sum // "square"   //    - ( ) //     "fun" let sumOfSquaresTo100withFun = [ 1 .. 100 ] |> List.map (fun x -> x * x) |> List.sum //  F#    -   "return"   //          // ========    ======== // Match..with.. -  case/switch  " ". let x = "a" match x with | "a" -> printfn "x -  a" | "b" -> printfn "x -  b" | _ -> printfn "x -  - " //   " " // Some(..)  None    Nullable<T> let validValue = Some(99) let invalidValue = None //    match..with   "Some"  "None" //         "Some". let optionPatternMatch input = match input with | Some i -> printfn "  %d" i | None -> printfn "  " optionPatternMatch validValue optionPatternMatch invalidValue // =========    ========= //  -  ,     . //   . let twoTuple = (1, 2) let threeTuple = ("a", 2, true) //    .     . type Person = { First: string; Last: string } let person1 = { First="John"; Last="Doe" } //         //    . let person2 = { First="Jane" Last="Doe" } //   .  -  . type Temp = | DegreesC of float | DegreesF of float let temp = DegreesF 98.6 //      . // ,  -,    //    : type Employee = | Worker of Person | Manager of Employee list let jdoe = { First="John"; Last="Doe" } let worker = Worker jdoe // =========    ========= //  printf/printfn    Console.Write/WriteLine  C#. printfn "     int %i, float %f, bool %b" 1 2.0 true printfn " %s,  -  %A" "hello" [ 1; 2; 3; 4 ] //        printfn "twoTuple=%A,\nPerson=%A,\nTemp=%A,\nEmployee=%A" twoTuple person1 temp worker 

さらに、.NETおよびサポヌトされおいる蚀語の公匏ドキュメントには、 「FTour」ずいう資料がありたす。


次にするこず


この投皿で説明するものはすべお、Fの衚面的な機胜にすぎたせん。 この蚘事を読んだ埌、Fず関数型プログラミングに没頭できるこずを願っおいたす。 Fをさらに調査するための挔習ずしお蚘述できる䟋をいく぀か瀺したす。



Fを䜿甚できるタスクは他にもたくさんありたす。 前のリストは決しお完党なものではありたせん。 Fはさたざたなアプリケヌションで䜿甚されたす単玔なビルドスクリプトから数十億の収益を䞊げるオンラむンストアのバック゚ンドたで。 Fを䜿甚できるプロゞェクトに制限はありたせん。


远加のリ゜ヌス


Fには、CたたはJavaの経隓がある人向けの資料など、倚くのチュヌトリアルがありたす。 次のリンクは、Fの詳现を説明するのに圹立ちたす。



Fの孊習を開始する他のいく぀かの方法に぀いおも説明したす。


最埌に、Fコミュニティは非垞に初心者に優しいです。 Slackには、FSoftware Foundationがサポヌトする非垞に掻発なチャットがあり、 自由に参加できる初心者ルヌムがありたす。 行うこずをお勧めしたす


ロシア語を話すコミュニティFのサむトを蚪れるこずを忘れないでください 蚀語の孊習に぀いお質問がある堎合は、チャットルヌムでお気軜にご盞談ください。



翻蚳著者に぀いお


この蚘事は、 ロシア語を話すF開発者のコ​​ミュニティの努力によっお翻蚳されたした。
@schvepsss .



Source: https://habr.com/ru/post/J335560/


All Articles