{"id":834,"date":"2009-07-01T16:02:25","date_gmt":"2009-07-01T14:02:25","guid":{"rendered":"http:\/\/www.navision-blog.de\/2009\/07\/01\/extensibility-of-functions-with-lambdas-in-f-and-c\/"},"modified":"2009-07-01T16:19:59","modified_gmt":"2009-07-01T14:19:59","slug":"extensibility-of-functions-with-lambdas-in-f-and-c","status":"publish","type":"post","link":"http:\/\/www.navision-blog.de\/blog\/2009\/07\/01\/extensibility-of-functions-with-lambdas-in-f-and-c\/","title":{"rendered":"Extensibility of functions with lambdas (in F# and C#)"},"content":{"rendered":"<p>One of the nice properties of functional programming languages is the easy extensibility of custom functions. Let\u2019s consider a simple F# function (from <a href=\"http:\/\/code.google.com\/p\/fake\/\">\u201cFAKE \u2013 F# Make\u201d<\/a>) for a recursive directory copy:<\/p>\n<pre class=\"code\"><span style=\"color: blue\">open <\/span>System\n<span style=\"color: blue\">open <\/span>System.IO\n<span style=\"color: green\">\n\/\/\/ Copies a directory recursive\n\/\/\/ Thanks to Robert Pickering <a title=\"http:\/\/strangelights.com\/blog\/\" href=\"http:\/\/strangelights.com\/blog\/\">http:\/\/strangelights.com\/blog\/<\/a><\/span><span style=\"color: green\">\n\/\/\/  param target: target directory : string\n\/\/\/  param source: source directory : string\n<\/span><span style=\"color: blue\">let <\/span>CopyDir target source =\n  Directory.GetFiles(source, <span style=\"color: maroon\">&quot;*.*&quot;<\/span>, SearchOption.AllDirectories)\n    |&gt; Seq.iter (<span style=\"color: blue\">fun <\/span>file <span style=\"color: blue\">-&gt; \n      let <\/span>newFile = target + file.Remove(0, source.Length)\n      printf <span style=\"color: maroon\">&quot;%s =&gt; %s&quot; <\/span>file newFile\n      Directory.CreateDirectory(Path.GetDirectoryName(newFile)) |&gt; ignore\n      File.Copy(file, newFile, <span style=\"color: blue\">true<\/span>))<\/pre>\n<p>If we want to allow users to set custom file filters, we can add a third parameter:<\/p>\n<pre class=\"code\"><span style=\"color: green\">\/\/\/ Copies a directory recursive\n<strong>\/\/\/ and allows to filter the files<\/strong>\n<span style=\"color: green\">\/\/\/ Thanks to Robert Pickering <a title=\"http:\/\/strangelights.com\/blog\/\" href=\"http:\/\/strangelights.com\/blog\/\">http:\/\/strangelights.com\/blog\/<\/span><\/span><span style=\"color: green\"><\/span><\/a>\n<span style=\"color: green\">\/\/\/  param target: target directory : string\n\/\/\/  param source: source directory : string\n<strong>\/\/\/  param filterFile: FilterFunction: string -&gt; bool<\/strong>\n<\/span><span style=\"color: blue\">let <\/span>CopyDirFiltered target source <strong>filterFile<\/strong> =\n  Directory.GetFiles(source, <span style=\"color: maroon\">&quot;*.*&quot;<\/span>, SearchOption.AllDirectories)\n    <strong>|&gt; Seq.filter filterFile<\/strong>\n    |&gt; Seq.iter (<span style=\"color: blue\">fun <\/span>file <span style=\"color: blue\">-&gt; \n      let <\/span>newFile = target + file.Remove(0, source.Length)\n      printfn <span style=\"color: maroon\">&quot;%s =&gt; %s&quot; <\/span>file newFile\n      Directory.CreateDirectory(Path.GetDirectoryName(newFile)) |&gt; ignore\n      File.Copy(file, newFile, <span style=\"color: blue\">true<\/span>))<\/pre>\n<p>Now we can define some filter functions:<\/p>\n<pre class=\"code\"><span style=\"color: green\">\/\/\/ Exclude SVN files (path with .svn)\n\/\/\/ excludeSVNFiles<strong>: string -&gt; bool<\/strong> \n<\/span><span style=\"color: blue\">let <\/span>excludeSVNFiles (path:string) = not &lt;| path.Contains <span style=\"color: maroon\">&quot;.svn&quot;\n\n<\/span><span style=\"color: green\">\/\/\/ Includes all files\n\/\/\/ allFiles<strong>: string -&gt; bool<\/strong> <\/span>\n<\/span><span style=\"color: blue\">let <\/span>allFiles (path:string) = <span style=\"color: blue\">true<\/span><\/pre>\n<p>Now it is possible to use CopyDirFiltered in the following ways:<\/p>\n<pre class=\"code\"><span style=\"color: green\">\/\/\/ Copies all files &lt;=&gt; same as CopyDir\n<\/span>CopyDirFiltered <span style=\"color: maroon\">&quot;C:\\\\target&quot; &quot;C:\\\\source&quot; <\/span>allFiles\n\n<span style=\"color: green\">\/\/\/ Copies all files except SVN files\n<\/span>CopyDirFiltered <span style=\"color: maroon\">&quot;C:\\\\target&quot; &quot;C:\\\\source&quot; <\/span>excludeSVNFiles\n\n<span style=\"color: green\">\/\/\/ Copies all files only if random number &lt;&gt; 2\n<\/span><span style=\"color: blue\">let <\/span>r = <span style=\"color: blue\">new <\/span>Random()\nCopyDirFiltered <span style=\"color: maroon\">&quot;C:\\\\target&quot; &quot;C:\\\\source&quot; <\/span>(<span style=\"color: blue\">fun <\/span>path <span style=\"color: blue\">-&gt; <\/span>r.Next(5) &lt;&gt; 2)<\/pre>\n<h5>Extensibility of functions in C#<\/h5>\n<p>Of course we can do the same thing in C# 3.0:<\/p>\n<pre class=\"code\"><span style=\"color: gray\">\/\/\/ &lt;summary&gt;\n\/\/\/ <\/span><span style=\"color: green\">Copies a directory recursive\n<\/span><span style=\"color: gray\">\/\/\/ <\/span><span style=\"color: green\">and allows to filter the files\n<\/span><span style=\"color: gray\">\/\/\/ &lt;\/summary&gt;\n\/\/\/ &lt;param name=&quot;target&quot;&gt;<\/span><span style=\"color: green\">The target.<\/span><span style=\"color: gray\">&lt;\/param&gt;\n\/\/\/ &lt;param name=&quot;source&quot;&gt;<\/span><span style=\"color: green\">The source.<\/span><span style=\"color: gray\">&lt;\/param&gt;\n\/\/\/ &lt;param name=&quot;fileFilter&quot;&gt;<\/span><span style=\"color: green\">The file filter.<\/span><span style=\"color: gray\">&lt;\/param&gt;\n<\/span><span style=\"color: blue\">public static void <\/span>CopyDirFiltered(<span style=\"color: blue\">string <\/span>target, <span style=\"color: blue\">string <\/span>source,\n                                   <span style=\"color: #2b91af\">Func<\/span>&lt;<span style=\"color: blue\">string<\/span>, <span style=\"color: blue\">bool<\/span>&gt; fileFilter)\n{\n    <span style=\"color: blue\">string<\/span>[] allFiles = <span style=\"color: #2b91af\">Directory<\/span>.GetFiles(\n        source, <span style=\"color: #a31515\">&quot;*.*&quot;<\/span>, <span style=\"color: #2b91af\">SearchOption<\/span>.AllDirectories);\n    <span style=\"color: blue\">foreach <\/span>(<span style=\"color: blue\">string <\/span>file <span style=\"color: blue\">in from <\/span>f <span style=\"color: blue\">in <\/span>allFiles\n                            <span style=\"color: blue\">where <\/span>fileFilter(f)\n                            <span style=\"color: blue\">select <\/span>f)\n    {\n        <span style=\"color: blue\">string <\/span>newFile = target + file.Remove(0, source.Length);\n        <span style=\"color: #2b91af\">Console<\/span>.WriteLine(<span style=\"color: #a31515\">&quot;{0} =&gt; {1}&quot;<\/span>, file, newFile);\n        <span style=\"color: #2b91af\">Directory<\/span>.CreateDirectory(<span style=\"color: #2b91af\">Path<\/span>.GetDirectoryName(newFile));\n        <span style=\"color: #2b91af\">File<\/span>.Copy(file, newFile, <span style=\"color: blue\">true<\/span>);\n    }\n}<\/pre>\n<p>Now it is easy to use the C# function with lambdas:<\/p>\n<blockquote>\n<p>\u201cA lambda expression is an anonymous function that can contain expressions and statements, and can be used to create delegates or expression tree types.\u201d<\/p>\n<p align=\"right\">[<a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/bb397687.aspx\">MSDN<\/a>]<\/p>\n<\/blockquote>\n<pre class=\"code\"><span style=\"color: #2b91af\">Func<\/span>&lt;<span style=\"color: blue\">string<\/span>, <span style=\"color: blue\">bool<\/span>&gt; filterSVN = x =&gt; !x.Contains(<span style=\"color: #a31515\">&quot;.svn&quot;<\/span>);\n<span style=\"color: #2b91af\">Func<\/span>&lt;<span style=\"color: blue\">string<\/span>, <span style=\"color: blue\">bool<\/span>&gt; allFiles = x =&gt; <span style=\"color: blue\">true<\/span>;\n\n<span style=\"color: gray\">\/\/\/ <\/span><span style=\"color: green\">Copies all files <\/span><span style=\"color: gray\">&lt;=&gt; <\/span><span style=\"color: green\">same as CopyDir\n<\/span>CopyDirFiltered(<span style=\"color: #a31515\">&quot;C:\\\\target&quot;<\/span>, <span style=\"color: #a31515\">&quot;C:\\\\source&quot;<\/span>, allFiles);\n\n<span style=\"color: gray\">\/\/\/ <\/span><span style=\"color: green\">Copies all files except SVN files\n<\/span>CopyDirFiltered(<span style=\"color: #a31515\">&quot;C:\\\\target&quot;<\/span>, <span style=\"color: #a31515\">&quot;C:\\\\source&quot;<\/span>, filterSVN);\n\n<span style=\"color: gray\">\/\/\/ <\/span><span style=\"color: green\">Copies all files only if random number <\/span><span style=\"color: gray\">&lt;&gt; <\/span><span style=\"color: green\">2\n<\/span><span style=\"color: blue\">var <\/span>r = <span style=\"color: blue\">new <\/span><span style=\"color: #2b91af\">Random<\/span>();\nCopyDirFiltered(<span style=\"color: #a31515\">&quot;C:\\\\target&quot;<\/span>, <span style=\"color: #a31515\">&quot;C:\\\\source&quot;<\/span>, path =&gt; r.Next(5) != 2);<\/pre>\n<p>Keeping this simple technique in mind allows to create very flexible functions.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>One of the nice properties of functional programming languages is the easy extensibility of custom functions. Let\u2019s consider a simple F# function (from \u201cFAKE \u2013 F# Make\u201d) for a recursive directory copy: open System open System.IO \/\/\/ Copies a directory recursive \/\/\/ Thanks to Robert Pickering http:\/\/strangelights.com\/blog\/ \/\/\/ param target: target directory : string \/\/\/ [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[23,448],"tags":[81,664,544,555],"_links":{"self":[{"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/posts\/834"}],"collection":[{"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/comments?post=834"}],"version-history":[{"count":9,"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/posts\/834\/revisions"}],"predecessor-version":[{"id":843,"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/posts\/834\/revisions\/843"}],"wp:attachment":[{"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/media?parent=834"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/categories?post=834"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/tags?post=834"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}