ã©ã¤ãã©ãªãä½ã£ã¦ã¿ã¦æããF#ã®è¯ãã¨ãããæ©ã¿ã©ãã
ããã¯F# Advent Calendar 2012ã®5æ¥ç®ã®è¨äºã§ãã
æ¨æ¥ã®è¨äºã¯ãkos59125ããã®F# ã®ããã®ä¹±æ°çæãã¬ã¼ã ã¯ã¼ã¯ã§ãããç§ã«ã¨ã£ã¦ã¯ããã¾ããªãã¿ã®ãªãä¸çã®è©±ã§å¤§å¤åºæ¿çã§ããstateã¢ããã¯ãã¤è¦ã¦ãéæ³ã®ããã§ããèªåãããããã³ã³ãã¥ãã¼ã·ã§ã³å¼ã使ãããªããããã«ãªãããã
ãã¦ãä»æ¥ã®è¨äºã¯ãã¨è¨ãã¾ãã¨ãã¼ãã¼ã£ã¨ããã¿ã¤ãã«ã§æ縮ã§ãããå®ä½é¨ãåºã«æ¸ãã¦ã¿ããã¨æãã¾ãã
ã¯ããã«
ã¡ããã©2å¹´åãEntity Frameworkããã¼ã¹ã«C#ã§ã¹ãã¼ãã¬ã¹ãªO/Rãããã¼ãä½ã£ã¦ãããã§ãããF#ã触ã£ã¦ãããã¡ã«F#ã§æ¸ããã»ããå¹ççã«ä½ãããã ã¨ç´æãã¦ãä¸ããä½ãç´ãããã¨ãããã¾ãï¼ã¤ãã§ã«Entity Frameworkããã¼ã¹ã«ããã®ãããã¾ããï¼ãããã¦ã§ããã®ãSomaã¨ããã©ã¤ãã©ãªã§ããä»äºã§ã使ã£ã¦ãã¦èªåã«ã¨ã£ã¦ã¯ã¨ã¦ãå®ç¨çãSomaã¯ãF#ã§ä½ãã¾ããããC#ãVB.NETããã使ããããAPIãåãã¦ãã¾ããå®éãä»äºã§ã¯C#ããå¼ã³åºãã¦ä½¿ã£ã¦ãã¾ãã対å¿RDBMSã¨ãã¦ã¯ãSQL Serverã ãã§ãªãOracleããµãã¼ããã¦ããã¨ãããå®ç¨çã¨è¨ããã¨ããã§ãã.NETã®ç°å¢ã§ä¸çªä½¿ããã¦ãããã¼ã¿ãã¼ã¹ãSQL Serverã§ããã®æ¬¡ãOracleã ã¨æãã®ã§ï¼ãã¶ãï¼ã
F#ã§ä½ãç´ãããã¨ã¯ãçµæçã«ã¯æ£è§£ã§ãããããã¶ããææ©ãã³ã³ãã¯ãã«ä½ããã¨æã£ã¦ãã¾ãã
ã¨ãSomaã®ã¢ãã¼ã«ã¯ããã¾ã§ã«ãã¦ãä»åã¯ãSomaã®æ©è½çãªå´é¢ã§ã¯ãªãã¦ãSomaãä½ãéç¨ã§å®æããF#ã®è¯ãã¨ãããæ©ã¿ã©ãããç´¹ä»ãã¾ããè¯ãã¨ããã¯ã¡ãã£ã¨ç´°ãã話ãªã®ã§ããC#ã¡ã¤ã³ãªæ¹ã«ä¼ããã¨ããããã§ãããæ©ã¿ã©ããã«ã¤ãã¦ã¯F#好ããªæ¹ã«æè¦ãèãã¦ã¿ããã§ãã
F#ã®è¯ãã¨ãã
F#ã®å©ç¹ã¯ãåæ¨è«ã¨ãå¤å¥å ±ç¨ä½ã¨ããã¿ã¼ã³ãããã³ã°ã¨ãããããããã¾ãããèªåãæãæ°ã«å ¥ã£ã¦ããã®ã¯ãã¹ã³ã¼ããçãã§ãããã¨ããç¹é·ã§ããã¡ãã£ã¨å°å³ããããã¾ãããããã®è¯ãã¯å¤ããªãã
ã¹ã³ã¼ããçãã§ããã¨ãä¸åº¦ã«èæ ®ããªããã°ãããªãäºæãæ¸ãããã®ã§ãé ã®ä¸ã«ãããã¸ãã¯ãã³ã¼ãã«è½ã¨ãããããªãã¾ããããã¯æ¬å½ã«ãããã®ã§ããæ¬è³ªçãªãã¨ã«ã ãéä¸ã§ãã¦æ¥½ããã³ã¼ããæ¸ãã¾ãããã
ã¹ã³ã¼ããçãããå ·ä½çãªæ¹æ³ã«ã¯
- å¤ãä¸æ¹ã«å®ç¾©ãã
- é¢æ°ããã¹ãããã
- å¤ãã·ã£ãã¦ã£ã³ã°ãã
ã¨è¨ã£ããã®ãããã¾ãã
å¤ãä¸æ¹ã«å®ç¾©ãã
F#ã§ã¯ããã¡ã¤ã«ã®ä¸¦ã³ãã¢ã¸ã¥ã¼ã«ãå¤ï¼é¢æ°å«ãï¼ã®å®ç¾©é åºã«æå³ããã£ã¦ãä¸æ¹åç §ããã§ããªãããã«å¶éããã¦ãã¾ããæåã¯ããã®å¶éã«ã¨ã¾ã©ãã¾ããããæ £ãã¦ã¿ãã°ä¾¿å©ã ã¨æ°ã¥ãã¾ãããå ¬éãã¦ããªãå¤ãå¤æ´ããéã®å½±é¿ç¯å²ã¯ããã®ä¸æ¹ã«çµãããããã§ãã
(* F# *) (* barãåç §ã§ããã®ã¯foo, hoge, main *) let bar x = x * 2 (* fooãåç §ã§ããã®ã¯hoge, main *) let foo x = bar x (* hogeãåç §ã§ããã®ã¯main *) let hoge x = foo x [<EntryPoint>] let main argv = printfn "%d" <| hoge 10 0
é¢æ°ããã¹ãããã
é¢æ°ããã¹ããããã¨ãå å´ã®é¢æ°ãã¯ãå¤å´ã®é¢æ°ãã®å é¨ã§ããåç §ã§ãã¾ãããããç¹å®ã®é¢æ°å ã ãã§ä½¿ãããé¢æ°ã¯å å´ã«å®ç¾©ããã®ãèªç¶ã§ããé¢æ°ã®ãã¹ãã¯ãC#ã§ãã¡ã½ããã®ä¸ã«ã©ã ãå¼ãæ¸ããããã¦å¯è½ã§ãããã©ã ãå¼ã«ã¯yield returnãã§ããªãã¨ããå¶éããã£ã¦ã次ã®ãããªãã¨ã¯ã§ãã¾ããã
// C# class Program { static void Main(string[] args) { Func<IDataReader, IEnumerable<object>> getValues = (reader) => { while (reader.Read()) { // ã©ã ãå¼ã®ä¸ã§ã¯yield returnã§ããªã yield return reader.GetValue(0); } }; ... } }
ä¸æ¹ãF#ã¯åé¡ãªãå å´ã®é¢æ°ã§yieldã§ãã¾ãããããããC#ã®Funcåã«ç¸å½ããå®ç¾©ãæ¸ãå¿ è¦ããªãã®ã§ç°¡æ½ã§ããã
(* F# *) [<EntryPoint>] let main argv = let getValues (reader:IDataReader) = seq { while reader.Read() do yield reader.GetValue(0) } ...
å¤ãã·ã£ãã¦ã£ã³ã°ãã
ã·ã£ãã¦ã£ã³ã°ã¯ã¨ã¦ã好ããªæ©è½ã§ããããã¦ãè¯ããä¼ãã¥ããæ©è½ã®çé ã§ãï¼ä½åã人ã«èª¬æãã¾ãããã©ãããã¾ããããªã...ï¼ã
(* F# *) let read path = (* æ£è¦ååã®pathããã°åºåããé¢æ° *) let logger () = printfn "%s" path (* ã·ã£ãã¦ã£ã³ã°ããã以éã¯æ£è¦ååã®pathãåç §ããå¿ è¦ãªã *) let path = normalize path ... readFile path logger
ã·ã£ãã¦ã£ã³ã°ã¯ããã以éã§åç §ããããªãå¤ãå®å ¨ã«é ãã¾ãããã¨ãã°ãä¸ã®ä¾ã«ããã¦loggeré¢æ°ã¯æ£è¦ååã®pathãåç §ãã¾ãããã·ã£ãã¦ã£ã³ã°å¾ã®å¦çã§ã¯normalizeãããæ°ããpathãåç §ãã¾ãï¼ã¤ã¾ããã·ã£ãã¦ã£ã³ã°åå¾ã§å¤ãå ±æããªãï¼ãã·ã£ãã¦ã£ã³ã°ã¯ã¹ã³ã¼ããçãã§ããä¸ã«ç®¡çãã¹ãååãå¢ãããªãã®ã§ãããã°ã©ãã®æèã«ããããã®ã§ãã
C#ã§ä¼¼ããããªãã¨ï¼åä»£å ¥ï¼ãããã¨ãF#ã¨éã£ãæåã«ãªãã¾ããé¢æ°ãåä»£å ¥å¾ã®å¤ãåç §ããã®ã§ï¼ã¤ã¾ããå¤ãå ±æããï¼ã
以ä¸ãF#ã®è¯ãã¨ããã§ããã
F#ã®æ©ã¿ã©ãã
æ©ã¿ã©ããã¯ãã©ã¤ãã©ãªè¨è¨ã«é¢ãããã®ã3ã¤ã«çµã£ã¦è©±ãã¾ãã
- ã©ã®è¨èªãæ³å®ãã¦APIãä½ãã¹ããï¼
- ã·ã°ããã£ãã¡ã¤ã«(.fsi)ã使ãã¹ããï¼
- æ¡å¼µãã¤ã³ãã®ããã©ã«ãå®è£ ãF#ã§æ¸ãã¹ããï¼
ã©ã®è¨èªãæ³å®ãã¦APIãä½ãã¹ããï¼
èãã¨ãã¦ã¯3ã¤ããã¨æãã¾ããç°¡åãªé ã«ä¸¦ã¹ãã¨
- F#å°ç¨ã®APIã«ãã
- å¤ãã®.NETè¨èªãæ³å®ãã¦æ¨æºçãª.NETã®è¦ç´ã«åã£ãAPIã«ãã
- ä¸ã®2ã¤ã®ä¸¡æ¹ã«å¯¾å¿ãã
F#å°ç¨ã®APIã¯ãç°¡åã§ãããF#ã§ã©ã¤ãã©ãªãä½ã£ã¦ãã以ä¸ãèæ ®ç¹ã¯å°ãªãã¨æãã¾ãã
æ¨æºçãª.NETã®è¦ç´ã«åã£ãAPIã«ããã«ã¯ã次ã®ã¬ã¤ãã©ã¤ã³ãããã®ã§ããããåç §ããã®ãããã§ããé常ã¯ãã®æ¹æ³ãã¨ãã¨æãã¾ããæ¥æ¬èªè¨³ãããã¾ãã
Somaã¯ä¸é¨ã®APIã§3çªç®ã®æ¹æ³ã¨ãã¾ãããF#ãã使ããããAPIã¨C#ï¼ãVB/NETï¼ãã使ããããAPIã¯å¥ã ã¨æãããã§ãããã¤ã³ãã¯3ã¤ã
- C#ã§ã¯å¿åã¯ã©ã¹ãå©ç¨ãããããF#ã§ã¯Dictinaryã¾ãã¯Tupleã使ããã
- C#ã§ã¯mutableãªåã使ãããããF#ã§ã¯immutableãªåï¼F#ã®ã¬ã³ã¼ãåï¼ã使ããã
- C#ã§ã¯nullã使ãããããF#ã§ã¯Optionåã使ããã
ãã ãããF#å°ç¨ã®APIãã¨ãæ¨æºçãª.NETã®è¦ç´ã«åã£ãAPIãã®ä¸¡æ¹ã«å¯¾å¿ããã®ã¯æ¬å½ã«å¤§å¤ã§ãããªããªãã2åã«ãªããããã³ã¼ãããããã¦...ãããã¥ã¡ã³ããã
ã·ã°ããã£ãã¡ã¤ã«(.fsi)ã使ãã¹ããï¼
ã·ã°ããã£ãã¡ã¤ã«(.fsi)ã®å©ç¨ã¯ã¬ã¤ãã©ã¤ã³ã§æ¨å¥¨ããã¦ããã®ã§ãããã¾ããã«ã¡ã³ããã³ã¹ããã®ã¯ã¡ãã£ã¨ããã©ãã§ããfsiã¨fsã§åããã¨ãéè¤ãã¦æ¸ãã¦ããæ°åã«ãªã£ã¦ãã¾ãã
Somaã§ã¯ã·ã°ããã£ãã¡ã¤ã«ãæ¸ãã¾ããããã·ã°ããã£ãã¡ã¤ã«ã®ä»£ããã«ã¢ã¯ã»ã¹ä¿®é£¾å(public, internal, private)ã使ãæ¹æ³ãç°¡åã§ããã¨æãã¾ããã¾ã¡ãããªããèªåã次ã«F#ã§ã©ã¤ãã©ãªä½ãã¨ãã¯ã¢ã¯ã»ã¹ä¿®é£¾åã使ãæ¹æ³ãé¸ã³ã¾ãã
ããã©ã«ããpublicãªã®ã§ãé ãããã¨ããã ãinternalãprivateãã¤ãã¦ããã°ããããããªããã¨ããã®ãä»ã®èªåã®èãã§ãã
(* F# *) module Greeting = let hello name = "hello " + name let internal goodBye name = "good-bye " + name
æ¡å¼µãã¤ã³ãã®ããã©ã«ãå®è£ ãF#ã§æ¸ãã¹ããï¼
Somaã§ã¯ãããã¤ãæ¡å¼µãã¤ã³ãï¼RDBMSã«ä¾åãããããªæ©è½ã®ã«ã¹ã¿ãã¤ãºãªã©ï¼ãè¨ãã¾ããããC#ï¼ãVB.NETï¼ã§ãæ¡å¼µã§ããããã«ãããã¯ãã¡ããã¤ã³ã¿ãã§ã¼ã¹ã«ãã¦ãã¾ãããã ããã¤ã³ã¿ãã§ã¼ã¹ãå®è£
ããæ½è±¡ã¯ã©ã¹ãããã©ã«ãã®ã¯ã©ã¹ãããã¤ãF#ã§æ¸ããã¨ãããçµæ§é¢åã§ããã
çç±ã¯2ã¤ããã¾ãã
- F#ã®ã¯ã©ã¹ã®æ§æãC#ã«æ¯ã¹ã¦ããªãåé·ï¼virtualãªã¡ã½ããã®å®ç¾©ãã¤ã³ã¿ãã§ã¼ã¹ã®æ示çå®è£ ãªã©ï¼
- Visual StudioãReSharperã¨ãã£ããã¼ã«ã«ããã³ã¼ãçæã®æ©æµãå¾ãããªã
ã¯ã©ã¹ãæ¸ããããªã¨ããã¯ãå¥ã¢ã»ã³ããªã«ãã¦C#ã§æ¸ãã¦ãããã£ããªãã¨ä»ã¯æãã¾ããInternalsVisibleToAttributeã使ãã°ãå¥ã¢ã»ã³ããªã®internalãªAPIãå¼ã¹ã¾ããããã®ã»ãããã¶ã楽ã§ãã
以ä¸ãF#ã®æ©ã¿ã©ããã§ããã
ã¾ã¨ã
çµé¨çã«å®æããF#ã®è¯ãã¨ããã¨æ©ã¿ã©ãããæ¸ãã¾ãããè¯ãã¨ããã¯ãã¹ã³ã¼ããçããã¦æ¬è³ªçãªãã¨ã«éä¸ã§ãããã¨ãæ©ã¿ã©ããã¯ãè¤æ°ããã°ã©ãã³ã°è¨èªããã®å©ç¨ãæ³å®ããAPIã«ã¾ã¤ãããã¨ã§ããã
F# Advent Calendarãåå ãã¦ããã£ãã§ããã¢ã¤ã¢ã¤ãã¦ããèããè¨èªåã§ãã¦F#ã«ããã«èå³ãæã¤ããæ©ä¼ã«ãªãã¾ããã
ãã¦ãææ¥ã¯ãpocketberserkerããã§ããã楽ãã¿ã«ï¼