{"id":948,"date":"2010-02-08T17:58:12","date_gmt":"2010-02-08T17:58:12","guid":{"rendered":"http:\/\/www.navision-blog.de\/2010\/02\/08\/new-syntactic-sugar-for-fake-f-make-getting-rid-of-magic-strings\/"},"modified":"2010-02-08T18:00:06","modified_gmt":"2010-02-08T18:00:06","slug":"new-syntactic-sugar-for-fake-f-make-getting-rid-of-magic-strings","status":"publish","type":"post","link":"http:\/\/www.navision-blog.de\/blog\/2010\/02\/08\/new-syntactic-sugar-for-fake-f-make-getting-rid-of-magic-strings\/","title":{"rendered":"New syntactic sugar for &ldquo;FAKE &ndash; F# Make&rdquo; &ndash; Getting rid of magic strings"},"content":{"rendered":"<p>The new version 0.27 of \u201cFAKE \u2013 F# Make\u201d comes with new syntactic sugar for build targets and build dependencies. Don\u2019t be afraid the old version is still supported &#8211; all scripts should still work with the new version.<\/p>\n<h5>The problem<\/h5>\n<p>Consider the following target definition:<\/p>\n<div style=\"font-family: courier new; background: white; color: black; font-size: 10pt\">\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> buildDir = <span style=\"color: maroon\">&quot;.\/build\/&quot;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">Target <span style=\"color: maroon\">&quot;Clean&quot;<\/span> (<span style=\"color: blue\">fun<\/span> _ <span style=\"color: blue\">-&gt;<\/span><\/p>\n<p style=\"margin: 0px\">&#160; CleanDir buildDir<\/p>\n<p style=\"margin: 0px\">)<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">Target <span style=\"color: maroon\">&quot;Default&quot;<\/span> (<span style=\"color: blue\">fun<\/span> _ <span style=\"color: blue\">-&gt;<\/span><\/p>\n<p style=\"margin: 0px\">&#160; trace <span style=\"color: maroon\">&quot;Hello World from FAKE&quot;<\/span><\/p>\n<p style=\"margin: 0px\">)<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\"><span style=\"color: maroon\">&quot;Default&quot;<\/span> &lt;== [<span style=\"color: maroon\">&quot;Clean&quot;<\/span>]<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">run <span style=\"color: maroon\">&quot;Default&quot;<\/span><\/p>\n<\/p><\/div>\n<p>As you can see we are having a lot of \u201cmagic strings\u201d for the target names and the dependency definitions. This was always a small shortcoming in FAKE, since this doesn\u2019t allow refactoring and may result in runtime errors. <\/p>\n<p>One of my goals for \u201cFAKE \u2013 F# Make\u201d is to remove these strings in future versions. Unfortunately this is not that easy, because it causes a lot of internal issues. In particular logging to the build server is much harder if you don\u2019t have a target name.<\/p>\n<h5><\/h5>\n<h5>The first step<\/h5>\n<p>As posted in a <a href=\"http:\/\/bitbucket.org\/forki\/fake\/issue\/5\/mono-support-is-not-working\">bitbucket<\/a> comment by <a href=\"http:\/\/bitbucket.org\/cipher\/\">cipher<\/a> we could use the \u201c<a href=\"http:\/\/weblogs.asp.net\/podwysocki\/archive\/2010\/02\/05\/using-and-abusing-the-f-dynamic-lookup-operator.aspx\">dynamic lookup operator<\/a>\u201d to remove some of the magic strings without breaking any internal code.<\/p>\n<p>As a result we can rewrite the above sample as:<\/p>\n<div style=\"font-family: courier new; background: white; color: black; font-size: 10pt\">\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> buildDir = <span style=\"color: maroon\">&quot;.\/build\/&quot;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">Target? Clean &lt;-<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">fun<\/span> _ <span style=\"color: blue\">-&gt;<\/span> CleanDir buildDir<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">Target? Default &lt;-<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">fun<\/span> _ <span style=\"color: blue\">-&gt;<\/span> trace <span style=\"color: maroon\">&quot;Hello World from FAKE&quot;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">For? Default &lt;- Dependency? Clean<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">Run? Default<\/p>\n<\/p><\/div>\n<p>All magic strings suddenly disappeared. I think this syntax looks really nice, but unfortunately the strings are not really gone, since the token <strong>Default<\/strong> is only checked at runtime.<\/p>\n<h5>The idea for future versions<\/h5>\n<p>Since the new syntax is really just syntactic sugar I\u2019m always interested in a better solution. Currently I\u2019m working on a syntax using monads. The result could look like this:<\/p>\n<div style=\"font-family: courier new; background: white; color: black; font-size: 10pt\">\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> buildDir = <span style=\"color: maroon\">&quot;.\/build\/&quot;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> Clean = target { CleanDir buildDir }<\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> Default = <\/p>\n<p style=\"margin: 0px\">&#160; target { <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; trace <span style=\"color: maroon\">&quot;Hello World from FAKE&quot;<\/span> <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; trace <span style=\"color: maroon\">&quot;Another line&quot;<\/span><\/p>\n<p style=\"margin: 0px\">&#160; }<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">Default &lt;== [Clean]<\/p>\n<p style=\"margin: 0px\"><span style=\"color: green\"><\/span><\/p>\n<\/p><\/div>\n<div style=\"font-family: courier new; background: white; color: black; font-size: 10pt\">\n<p style=\"margin: 0px\">Run Default<\/p>\n<\/p><\/div>\n<p>This way the magic string are really gone, but my current problem is retrieving the target name from the let-binding name. Please leave a comment if you have an idea to solve this issue.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The new version 0.27 of \u201cFAKE \u2013 F# Make\u201d comes with new syntactic sugar for build targets and build dependencies. Don\u2019t be afraid the old version is still supported &#8211; all scripts should still work with the new version. The problem Consider the following target definition: let buildDir = &quot;.\/build\/&quot; &#160; Target &quot;Clean&quot; (fun _ [&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,546],"tags":[664,545,544],"_links":{"self":[{"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/posts\/948"}],"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=948"}],"version-history":[{"count":1,"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/posts\/948\/revisions"}],"predecessor-version":[{"id":949,"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/posts\/948\/revisions\/949"}],"wp:attachment":[{"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/media?parent=948"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/categories?post=948"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/tags?post=948"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}