{"id":456,"date":"2013-10-27T19:52:12","date_gmt":"2013-10-28T00:52:12","guid":{"rendered":"http:\/\/tiemensfamily.com\/TimOnCS\/?p=456"},"modified":"2013-10-27T19:52:12","modified_gmt":"2013-10-28T00:52:12","slug":"groovybadnessspreadmap","status":"publish","type":"post","link":"https:\/\/tiemensfamily.com\/timoncs\/2013\/10\/27\/groovybadnessspreadmap\/","title":{"rendered":"Groovy Badness: Turn a List into a Map"},"content":{"rendered":"<p>I&#8217;ve always enjoyed finding bugs in languages.  I still fondly recall finding a bug in Perl concerning the &#8220;<code>while () { .. }<\/code>&#8221; construct and file names that evaluate to &#8216;false&#8217;, like a file named &#8220;0&#8221;, for example.<\/p>\n<p>More recently, I discovered a Groovy bug in <code>groovy.lang.SpreadMap<\/code> class (and therefore in the List.toSpreadMap() implementation).  I&#8217;ve reported it (<a href=\"http:\/\/jira.codehaus.org\/browse\/GROOVY-6403\" title=\"SpreadMap is horribly broken\">GROOVY-6403<\/a>) and submitted a patch with a unit test.<\/p>\n<p>Some observations:<\/p>\n<ul>\n<li>This implementation was horribly broken.  Two seconds of <a href=\"http:\/\/grepcode.com\/file\/repo1.maven.org\/maven2\/org.codehaus.groovy\/groovy\/1.8.1\/groovy\/lang\/SpreadMap.java?av=f\" title=\"Source Code of SpreadMap.java\">review<\/a> is enough for competent Java developers to see why.\n<li> This code has been around a long time.  This <a href=\"http:\/\/mrhaki.blogspot.com\/2010\/01\/groovy-goodness-turn-list-into-map.html\">Groovy Goodness<\/a> post is dated January, 2010.  It shows the two methods (.size() and .get()) that were implemented correctly.  I&#8217;ll wonder forever if all the other broken methods (.containsKey(), .keySet(), .isEmpty(), etc.) were missed or purposefully omitted.\n<li> This code could have been easily detected as flawed with a 5-line unit test.\n<\/ul>\n<p><\/p>\n<p>The original example, with some additional (failing) asserts:<\/p>\n<pre class=\"brush:groovy\">\n#!\/usr\/bin\/env groovy\ndef list = ['key', 'value', 'name', 'tim'] as Object[]\ndef map = list.toSpreadMap()\n\nassert 2 == map.size()                \/\/ ok\nassert 'value' == map.key             \/\/ ok\nassert true == map.containsKey('key') \/\/ FAIL\nassert false == map.isEmpty()         \/\/ FAIL\nassert 2 == map.keySet().size()       \/\/ FAIL\n<\/pre>\n<p><strong>Back to the Perl bug <\/strong><\/p>\n<p>For these code snippets, place files named &#8220;0&#8221;, &#8220;1&#8221; and &#8220;2&#8221; in the current directory.  Perl 5 was used for this testing.<\/p>\n<p>The one will print &#8220;File is 0&#8221;, &#8220;File is 1&#8221; and &#8220;File is 2&#8221;, but also prints &#8220;How did we get here if 0 is not true?&#8221; [In earlier versions of Perl, this would not print anything if the first file found was &#8220;0&#8221;.  They&#8217;ve changed that.  But, see the next example.]<\/p>\n<pre class=\"brush:perl\">\n#!\/usr\/bin\/env perl\nwhile ($file = ) {\n   print \"File is $file\\n\";\n   if (! $file) {\n      print \"Huh?  How did we get here if $file is not true?\\n\";\n   }\n}\n<\/pre>\n<p>This one just won&#8217;t print anything, since &#8220;0&#8221; is the first file it sees, and that evaluates to &#8216;false&#8217;.  The extra variable assignment causes the hack fix to fail:<\/p>\n<pre>\n#!\/usr\/bin\/env perl\nmy $inside;\nmy $file;\nwhile ($file = ($inside = )) {\n   print \"File is $file\\n\";\n}\n<\/pre>\n<p>\nP.S. In case it is not obvious, do not use either of these constructs.  In summary:<\/p>\n<ul>\n<li>For the Perl bug, use opendir() and readdir().\n<li>For the Groovy bug, look at what the constructor of <a href=\"http:\/\/grepcode.com\/file\/repo1.maven.org\/maven2\/org.codehaus.groovy\/groovy\/1.8.1\/groovy\/lang\/SpreadMap.java?av=f\">SpreadMap.java<\/a> does, and write your code that way.  Or, use Groovy 2.2.0-rc-3+ or 2.1.10+\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;ve always enjoyed finding bugs in languages. I still fondly recall finding a bug in Perl concerning the &#8220;while () { .. }&#8221; construct and file names that evaluate to &#8216;false&#8217;, like a file named &#8220;0&#8221;, for example. More recently, &hellip; <a href=\"https:\/\/tiemensfamily.com\/timoncs\/2013\/10\/27\/groovybadnessspreadmap\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[5],"tags":[],"_links":{"self":[{"href":"https:\/\/tiemensfamily.com\/timoncs\/wp-json\/wp\/v2\/posts\/456"}],"collection":[{"href":"https:\/\/tiemensfamily.com\/timoncs\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tiemensfamily.com\/timoncs\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tiemensfamily.com\/timoncs\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/tiemensfamily.com\/timoncs\/wp-json\/wp\/v2\/comments?post=456"}],"version-history":[{"count":0,"href":"https:\/\/tiemensfamily.com\/timoncs\/wp-json\/wp\/v2\/posts\/456\/revisions"}],"wp:attachment":[{"href":"https:\/\/tiemensfamily.com\/timoncs\/wp-json\/wp\/v2\/media?parent=456"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tiemensfamily.com\/timoncs\/wp-json\/wp\/v2\/categories?post=456"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tiemensfamily.com\/timoncs\/wp-json\/wp\/v2\/tags?post=456"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}