CINXE.COM

Neal Gafter's blog: May 2007

<!DOCTYPE html> <html xmlns='http://www.w3.org/1999/xhtml' xmlns:b='http://www.google.com/2005/gml/b' xmlns:data='http://www.google.com/2005/gml/data' xmlns:expr='http://www.google.com/2005/gml/expr'> <head> <link href='https://www.blogger.com/static/v1/widgets/55013136-widget_css_bundle.css' rel='stylesheet' type='text/css'/> <meta content='text/html; charset=UTF-8' http-equiv='Content-Type'/> <meta content='blogger' name='generator'/> <link href='https://gafter.blogspot.com/favicon.ico' rel='icon' type='image/x-icon'/> <link href='http://gafter.blogspot.com/2007/05/' rel='canonical'/> <link rel="alternate" type="application/atom+xml" title="Neal Gafter&#39;s blog - Atom" href="https://gafter.blogspot.com/feeds/posts/default" /> <link rel="alternate" type="application/rss+xml" title="Neal Gafter&#39;s blog - RSS" href="https://gafter.blogspot.com/feeds/posts/default?alt=rss" /> <link rel="service.post" type="application/atom+xml" title="Neal Gafter&#39;s blog - Atom" href="https://www.blogger.com/feeds/7803021/posts/default" /> <!--Can't find substitution for tag [blog.ieCssRetrofitLinks]--> <meta content='http://gafter.blogspot.com/2007/05/' property='og:url'/> <meta content='Neal Gafter&#39;s blog' property='og:title'/> <meta content='Thoughts about Programming Languages, Science and Philosophy.' property='og:description'/> <title>Neal Gafter's blog: May 2007</title> <style id='page-skin-1' type='text/css'><!-- /* ----------------------------------------------- Blogger Template Style Name: Stretch Denim Designer: Darren Delaye URL: www.DarrenDelaye.com Date: 11 Jul 2006 ----------------------------------------------- */ body { background: #619bb8; margin: 0; padding: 0px; font: x-small Verdana, Arial; text-align: center; color: #000000; font-size/* */:/**/small; font-size: /**/small; } a:link { color: #215670; } a:visited { color: #215670; } a img { border-width: 0; } #outer-wrapper { font: normal normal 100% Verdana, Arial, Sans-serif;; } /* Header ----------------------------------------------- */ #header-wrapper { margin:0; padding: 0; background-color: #619bb8; text-align: left; } #header { margin: 0 2%; background-color: #215670; color: #efefef; padding: 0; font: normal normal 210% Verdana, Arial, Sans-serif;; position: relative; } h1.title { padding-top: 38px; margin: 0 1% .1em; line-height: 1.2em; font-size: 100%; } h1.title a, h1.title a:visited { color: #efefef; text-decoration: none; } #header .description { display: block; margin: 0 1%; padding: 0 0 40px; line-height: 1.4em; font-size: 50%; } /* Content ----------------------------------------------- */ .clear { clear: both; } #content-wrapper { margin: 0 2%; padding: 0 0 15px; text-align: left; background-color: #efefef; border: 1px solid #cccccc; border-top: 0; } #main-wrapper { margin-left: 1%; width: 64%; float: left; background-color: #efefef; display: inline; /* fix for doubling margin in IE */ word-wrap: break-word; /* fix for long text breaking sidebar float in IE */ overflow: hidden; /* fix for long non-text content breaking IE sidebar float */ } #sidebar-wrapper { margin-right: 1%; width: 29%; float: right; background-color: #efefef; display: inline; /* fix for doubling margin in IE */ word-wrap: break-word; /* fix for long text breaking sidebar float in IE */ overflow: hidden; /* fix for long non-text content breaking IE sidebar float */ } /* Headings ----------------------------------------------- */ h2, h3 { margin: 0; } /* Posts ----------------------------------------------- */ .date-header { margin: 1.5em 0 0; font-weight: normal; color: #666666; font-size: 100%; } .post { margin: 0 0 1.5em; padding-bottom: 1.5em; } .post-title { margin: 0; padding: 0; font-size: 125%; font-weight: bold; line-height: 1.1em; } .post-title a, .post-title a:visited, .post-title strong { text-decoration: none; color: #000000; font-weight: bold; } .post div { margin: 0 0 .75em; line-height: 1.3em; } .post-footer { margin: -.25em 0 0; color: #000000; font-size: 87%; } .post-footer .span { margin-right: .3em; } .post img, table.tr-caption-container { padding: 4px; border: 1px solid #cccccc; } .tr-caption-container img { border: none; padding: 0; } .post blockquote { margin: 1em 20px; } .post blockquote p { margin: .75em 0; } /* Comments ----------------------------------------------- */ #comments h4 { margin: 1em 0; color: #666666; } #comments h4 strong { font-size: 110%; } #comments-block { margin: 1em 0 1.5em; line-height: 1.3em; } #comments-block dt { margin: .5em 0; } #comments-block dd { margin: .25em 0 0; } #comments-block dd.comment-footer { margin: -.25em 0 2em; line-height: 1.4em; font-size: 78%; } #comments-block dd p { margin: 0 0 .75em; } .deleted-comment { font-style:italic; color:gray; } .feed-links { clear: both; line-height: 2.5em; } #blog-pager-newer-link { float: left; } #blog-pager-older-link { float: right; } #blog-pager { text-align: center; } /* Sidebar Content ----------------------------------------------- */ .sidebar h2 { margin: 1.6em 0 .5em; padding: 4px 5px; background-color: #619bb8; font-size: 100%; color: #333333; } .sidebar ul { margin: 0; padding: 0; list-style: none; } .sidebar li { margin: 0; padding-top: 0; padding-right: 0; padding-bottom: .5em; padding-left: 15px; text-indent: -15px; line-height: 1.5em; } .sidebar { color: #000000; line-height:1.3em; } .sidebar .widget { margin-bottom: 1em; } .sidebar .widget-content { margin: 0 5px; } /* Profile ----------------------------------------------- */ .profile-img { float: left; margin-top: 0; margin-right: 5px; margin-bottom: 5px; margin-left: 0; padding: 4px; border: 1px solid #cccccc; } .profile-data { margin:0; text-transform:uppercase; letter-spacing:.1em; font-weight: bold; line-height: 1.6em; font-size: 78%; } .profile-datablock { margin:.5em 0 .5em; } .profile-textblock { margin: 0.5em 0; line-height: 1.6em; } /* Footer ----------------------------------------------- */ #footer { clear: both; text-align: center; color: #000000; } #footer .widget { margin:.5em; padding-top: 20px; font-size: 85%; line-height: 1.5em; text-align: left; } /** Page structure tweaks for layout editor wireframe */ body#layout #header { width: 750px; } --></style> <link href='https://www.blogger.com/dyn-css/authorization.css?targetBlogID=7803021&amp;zx=320dc9d6-3705-4c62-b5c8-53b2c61cc0a1' media='none' onload='if(media!=&#39;all&#39;)media=&#39;all&#39;' rel='stylesheet'/><noscript><link href='https://www.blogger.com/dyn-css/authorization.css?targetBlogID=7803021&amp;zx=320dc9d6-3705-4c62-b5c8-53b2c61cc0a1' rel='stylesheet'/></noscript> <meta name='google-adsense-platform-account' content='ca-host-pub-1556223355139109'/> <meta name='google-adsense-platform-domain' content='blogspot.com'/> </head> <body> <div class='navbar section' id='navbar'><div class='widget Navbar' data-version='1' id='Navbar1'><script type="text/javascript"> function setAttributeOnload(object, attribute, val) { if(window.addEventListener) { window.addEventListener('load', function(){ object[attribute] = val; }, false); } else { window.attachEvent('onload', function(){ object[attribute] = val; }); } } </script> <div id="navbar-iframe-container"></div> <script type="text/javascript" src="https://apis.google.com/js/platform.js"></script> <script type="text/javascript"> gapi.load("gapi.iframes:gapi.iframes.style.bubble", function() { if (gapi.iframes && gapi.iframes.getContext) { gapi.iframes.getContext().openChild({ url: 'https://www.blogger.com/navbar.g?targetBlogID\x3d7803021\x26blogName\x3dNeal+Gafter\x27s+blog\x26publishMode\x3dPUBLISH_MODE_BLOGSPOT\x26navbarType\x3dBLUE\x26layoutType\x3dLAYOUTS\x26searchRoot\x3dhttps://gafter.blogspot.com/search\x26blogLocale\x3den\x26v\x3d2\x26homepageUrl\x3dhttps://gafter.blogspot.com/\x26vt\x3d9028559674743070826', where: document.getElementById("navbar-iframe-container"), id: "navbar-iframe", messageHandlersFilter: gapi.iframes.CROSS_ORIGIN_IFRAMES_FILTER, messageHandlers: { 'blogger-ping': function() {} } }); } }); </script><script type="text/javascript"> (function() { var script = document.createElement('script'); script.type = 'text/javascript'; script.src = '//pagead2.googlesyndication.com/pagead/js/google_top_exp.js'; var head = document.getElementsByTagName('head')[0]; if (head) { head.appendChild(script); }})(); </script> </div></div> <div id='outer-wrapper'><div id='wrap2'> <!-- skip links for text browsers --> <span id='skiplinks' style='display:none;'> <a href='#main'>skip to main </a> | <a href='#sidebar'>skip to sidebar</a> </span> <div id='header-wrapper'> <div class='header section' id='header'><div class='widget Header' data-version='1' id='Header1'> <div id='header-inner'> <div class='titlewrapper'> <h1 class='title'> <a href='https://gafter.blogspot.com/'> Neal Gafter's blog </a> </h1> </div> <div class='descriptionwrapper'> <p class='description'><span>Thoughts about Programming Languages, Science and Philosophy.</span></p> </div> </div> </div></div> </div> <div id='content-wrapper'> <div id='main-wrapper'> <div class='main section' id='main'><div class='widget Blog' data-version='1' id='Blog1'> <div class='blog-posts hfeed'> <div class="date-outer"> <h2 class='date-header'><span>Saturday, May 26, 2007</span></h2> <div class="date-posts"> <div class='post-outer'> <div class='post'> <a name='5610187677814530305'></a> <h3 class='post-title'> <a href='https://gafter.blogspot.com/2007/05/removing-language-features.html'>Removing Language Features?</a> </h3> <div class='post-header-line-1'></div> <div class='post-body'> <p><p>As a language grows by the addition of features, it necessarily gets more complex. After all, you can't remove existing language features because existing programs use those features, but each additional feature adds complexity. Right?</p> <p>Fellow Googler Matt Shulman asked me a question about the <a href="http://www.javac.info/">Closures for Java</a> specification. He observed that much of the complexity arises because of support for checked exceptions in the spec. Things like <code>throws</code> type parameters, disjunctive types, and throws clauses on function interfaces would be unnecessary without checked exceptions. Matt asked me if we had considered if things would be simpler without all that. At first I misunderstood his question to be referring to just the Closures specification, so I answered that&nbsp;the facility wouldn't fit into the language as well without support for checked exceptions.</p> <p>Matt clarified that he was asking not just about removing support for checked exceptions from the Closures spec, but from the entire programming language.</p> <p>There has been an <a href="http://www.artima.com/intv/solid.html">ongoing</a> <a href="http://www.artima.com/intv/handcuffs.html">debate</a> on the utility of checked exceptions. Many people are critical of Java's checked exceptions, characterizing them as a failed experiment in software engineering. In practice, checked exceptions can result in <a href="http://java.sun.com/javase/6/docs/api/java/lang/reflect/InvocationTargetException.html">API complexity</a>, and programs appear to be cluttered with exception handling code just to satisfy the compiler. Some people believe checked exceptions are a good language feature but are <a href="http://dev2dev.bea.com/pub/a/2006/11/effective-exceptions.html">misused, even in the JDK</a>. With the "experts" being such poor role models, how can we expect ordinary Java programmers to do better?</p> <p>We did a <a href="//www.google.com/search?q=java+checked+exceptions">Google search</a> to see how many people have written in support of checked exceptions and how many people don't like them. The discussion seems to be lopsided against checked exceptions, but on the other hand that may be due to the fact that checked exceptions are the status quo.</p> <p>This isn't a question I had thought much about. I believe the language could be simplified by treating all exception types as unchecked without breaking existing programs. This could also result in a simplification of future language extensions and APIs. But would the language and platform be better off without checked exceptions?</p></p> <div style='clear: both;'></div> </div> <div class='post-footer'> <p class='post-footer-line post-footer-line-1'><span class='post-comment-link'> <a class='comment-link' href='https://www.blogger.com/comment/fullpage/post/7803021/5610187677814530305' onclick=''>85 comments</a> </span> <span class='post-icons'> </span> <span class='post-backlinks post-comment-link'> </span> </p> <p class='post-footer-line post-footer-line-2'></p> <p class='post-footer-line post-footer-line-3'></p> </div> </div> </div> </div></div> <div class="date-outer"> <h2 class='date-header'><span>Sunday, May 20, 2007</span></h2> <div class="date-posts"> <div class='post-outer'> <div class='post'> <a name='3200938110645509413'></a> <h3 class='post-title'> <a href='https://gafter.blogspot.com/2007/05/limitation-of-super-type-tokens.html'>A Limitation of Super Type Tokens</a> </h3> <div class='post-header-line-1'></div> <div class='post-body'> <p><p>Watching Josh Bloch's presentation at JavaOne about new topics in the second edition of <a href="http://www.amazon.com/gp/redirect.html?ie=UTF8&amp;location=http%3A%2F%2Fwww.amazon.com%2FEffective-Java-Programming-Language-Guide%2Fdp%2F0201310058&amp;tag=wwwgaftercom-20&amp;linkCode=ur2&amp;camp=1789&amp;creative=9325"><span style="font-style: italic;">Effective Java</span></a> makes me want to go out and get my own copy. Unfortunately, he's not scheduled to have the new edition in print until later this year.</p> <p>There was a coincidental adjacency between two slides in Josh's talk that made me think a bit more about the idea of <a href="http://gafter.blogspot.com/2006/12/super-type-tokens.html"><span style="font-style: italic;">Super Type Tokens</span></a>. The last slide of his discussion of generics gave a complete implementation of the mind-expanding <span style="font-style: italic;">Typesafe Heterogenous Containers</span> (THC) pattern using Super Type Tokens:</p> <blockquote> <pre>import&nbsp;java.lang.reflect.*;<br /><br />public&nbsp;abstract&nbsp;class&nbsp;TypeRef&lt;T&gt;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;final&nbsp;Type&nbsp;type;<br />&nbsp;&nbsp;&nbsp;&nbsp;protected&nbsp;TypeRef()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ParameterizedType&nbsp;superclass&nbsp;=&nbsp;(ParameterizedType)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;getClass().getGenericSuperclass();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;type&nbsp;=&nbsp;superclass.getActualTypeArguments()[0];<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;@Override&nbsp;public&nbsp;boolean&nbsp;equals&nbsp;(Object&nbsp;o)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;o&nbsp;instanceof&nbsp;TypeRef&nbsp;&amp;&amp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((TypeRef)o).type.equals(type);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;@Override&nbsp;public&nbsp;int&nbsp;hashCode()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;type.hashCode();<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /><br />public&nbsp;class&nbsp;Favorites2&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;Map&lt;TypeRef&lt;?&gt;,&nbsp;Object&gt;&nbsp;favorites&nbsp;=<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new&nbsp;HashMap&lt;&nbsp;TypeRef&lt;?&gt;&nbsp;,&nbsp;Object&gt;();<br />&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;&lt;T&gt;&nbsp;void&nbsp;setFavorite(TypeRef&lt;T&gt;&nbsp;type,&nbsp;T&nbsp;thing)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;favorites.put(type,&nbsp;thing);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: rgb(153, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;@SuppressWarning("unchecked")</span><br />&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;&lt;T&gt;&nbsp;T&nbsp;getFavorite(TypeRef&lt;T&gt;&nbsp;type)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;<span style="color: rgb(153, 0, 0);">(T)</span>&nbsp;favorites.get(type);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Favorites2&nbsp;f&nbsp;=&nbsp;new&nbsp;Favorites2();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List&lt;String&gt;&nbsp;stooges&nbsp;=&nbsp;Arrays.asList(<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Larry",&nbsp;"Moe",&nbsp;"Curly");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;f.setFavorite(new&nbsp;TypeRef&lt;List&lt;String&gt;&gt;(){},&nbsp;stooges);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List&lt;String&gt;&nbsp;ls&nbsp;=&nbsp;f.getFavorite(<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new&nbsp;TypeRef&lt;List&lt;String&gt;&gt;(){});<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /></pre> </blockquote> <p>But on the very next slide, the very first bullet of the summary of his presentation reminds us</p> <ul> <li>Don't ignore compiler warnings.</li> </ul> <p>This was referring to Josh's advice earlier in the presentation not to ignore or suppress unchecked compiler warnings without trying to understand them. Ideally, you should only suppress these warnings when you have good reason to believe that the code is type-safe, even though you might not be able to convince the compiler of that fact.</p> <p>The method <code>Favorites2.getFavorite</code>, above, is annotated to suppress a warning from the compiler. Without that annotation, the compiler complains about the cast to the type T, a type parameter. Is this code demonstrably type safe? Is it possible to cause this cast to fail using code that is otherwise completely type safe? Unfortunately, the cast is not safe:</p> <blockquote> <pre>class Oops { static Favorites2 f = new Favorites2(); static &lt;T&gt; List&lt;T&gt; favoriteList() { TypeRef&lt;List&lt;T&gt;&gt; ref = new TypeRef&lt;List&lt;T&gt;&gt;(){}; List&lt;T&gt; result = f.getFavorite(ref); if (result == null) { result = new ArrayList&lt;T&gt;(); f.setFavorite(ref, result); } return result; } public static void main(String[] args) { List&lt;String&gt; ls = favoriteList(); List&lt;Integer&gt; li = favoriteList(); li.add(1); for (String s : ls) System.out.println(s); } }</pre> </blockquote> <p>This program compiles without warning, but it exposes the loopole in the type system created by the cast to T in&nbsp;<code>Favorites2.getFavorite</code>. The compiler's warning does, after all, tell us about a weakness in the type safety of the program.</p> <p>The issue is a subtle one: <code>TypeRef</code> treats two types as the same when the underlying <code>java.lang.reflect.Type</code> objects are equal. A given <code>java.lang.reflect.Type</code> object represents a particular <span style="font-style: italic;">static</span> type appearing in the source, but if it is a type variable it can represent a different <span style="font-style: italic;">dynamic</span> type <span style="font-style: italic; text-decoration: underline;"><span style="font-style: italic;"></span></span>from one point in the program's execution to another. The program <code>Oops</code> exploits that mismatch.</p> <p>The Super Type Token pattern can be redeemed by disallowing the use of type variables anywhere in the Type object it stores. That can be enforced at runtime (but not at compile time) in the constructor.</p> <p>Perhaps a better solution would be to <a href="http://gafter.blogspot.com/2006/11/reified-generics-for-java.html">reify generics</a> (i.e., "<a href="http://www.artima.com/forums/flat.jsp?forum=121&amp;thread=192309">erase erasure</a>") in the language, making all this nonsense unnecessary.</p></p> <div style='clear: both;'></div> </div> <div class='post-footer'> <p class='post-footer-line post-footer-line-1'><span class='post-comment-link'> <a class='comment-link' href='https://www.blogger.com/comment/fullpage/post/7803021/3200938110645509413' onclick=''>7 comments</a> </span> <span class='post-icons'> </span> <span class='post-backlinks post-comment-link'> </span> </p> <p class='post-footer-line post-footer-line-2'></p> <p class='post-footer-line post-footer-line-3'></p> </div> </div> </div> </div></div> </div> <div class='blog-pager' id='blog-pager'> <span id='blog-pager-newer-link'> <a class='blog-pager-newer-link' href='https://gafter.blogspot.com/search?updated-max=2007-10-28T17:05:00-07:00&amp;max-results=2&amp;reverse-paginate=true' id='Blog1_blog-pager-newer-link' title='Newer Posts'>Newer Posts</a> </span> <span id='blog-pager-older-link'> <a class='blog-pager-older-link' href='https://gafter.blogspot.com/search?updated-max=2007-05-20T19:01:00-07:00&amp;max-results=2' id='Blog1_blog-pager-older-link' title='Older Posts'>Older Posts</a> </span> <a class='home-link' href='https://gafter.blogspot.com/'>Home</a> </div> <div class='clear'></div> <div class='blog-feeds'> <div class='feed-links'> Subscribe to: <a class='feed-link' href='https://gafter.blogspot.com/feeds/posts/default' target='_blank' type='application/atom+xml'>Posts (Atom)</a> </div> </div> </div></div> </div> <div id='sidebar-wrapper'> <div class='sidebar section' id='sidebar'><div class='widget BlogArchive' data-version='1' id='BlogArchive1'> <h2>Blog Archive</h2> <div class='widget-content'> <div id='ArchiveList'> <div id='BlogArchive1_ArchiveList'> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2024/'> 2024 </a> <span class='post-count' dir='ltr'>(1)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2024/09/'> September </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2023/'> 2023 </a> <span class='post-count' dir='ltr'>(1)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2023/08/'> August </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2020/'> 2020 </a> <span class='post-count' dir='ltr'>(1)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2020/12/'> December </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2019/'> 2019 </a> <span class='post-count' dir='ltr'>(2)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2019/11/'> November </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2019/08/'> August </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2017/'> 2017 </a> <span class='post-count' dir='ltr'>(1)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2017/06/'> June </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2016/'> 2016 </a> <span class='post-count' dir='ltr'>(7)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2016/02/'> February </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2016/01/'> January </a> <span class='post-count' dir='ltr'>(6)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2015/'> 2015 </a> <span class='post-count' dir='ltr'>(1)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2015/12/'> December </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2014/'> 2014 </a> <span class='post-count' dir='ltr'>(1)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2014/11/'> November </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2010/'> 2010 </a> <span class='post-count' dir='ltr'>(2)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2010/08/'> August </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2010/02/'> February </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2009/'> 2009 </a> <span class='post-count' dir='ltr'>(2)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2009/03/'> March </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2009/02/'> February </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2008/'> 2008 </a> <span class='post-count' dir='ltr'>(4)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2008/08/'> August </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2008/03/'> March </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2008/02/'> February </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2008/01/'> January </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate expanded'> <a class='toggle' href='javascript:void(0)'> <span class='zippy toggle-open'> &#9660;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2007/'> 2007 </a> <span class='post-count' dir='ltr'>(18)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2007/12/'> December </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2007/11/'> November </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2007/10/'> October </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2007/07/'> July </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate expanded'> <a class='toggle' href='javascript:void(0)'> <span class='zippy toggle-open'> &#9660;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2007/05/'> May </a> <span class='post-count' dir='ltr'>(2)</span> <ul class='posts'> <li><a href='https://gafter.blogspot.com/2007/05/removing-language-features.html'>Removing Language Features?</a></li> <li><a href='https://gafter.blogspot.com/2007/05/limitation-of-super-type-tokens.html'>A Limitation of Super Type Tokens</a></li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2007/04/'> April </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2007/03/'> March </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2007/02/'> February </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2007/01/'> January </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2006/'> 2006 </a> <span class='post-count' dir='ltr'>(20)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2006/12/'> December </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2006/11/'> November </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2006/10/'> October </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2006/09/'> September </a> <span class='post-count' dir='ltr'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2006/08/'> August </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2005/'> 2005 </a> <span class='post-count' dir='ltr'>(2)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2005/02/'> February </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2004/'> 2004 </a> <span class='post-count' dir='ltr'>(1)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> &#9658;&#160; </span> </a> <a class='post-count-link' href='https://gafter.blogspot.com/2004/09/'> September </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> </li> </ul> </div> </div> <div class='clear'></div> </div> </div><div class='widget Profile' data-version='1' id='Profile1'> <h2>About Me</h2> <div class='widget-content'> <dl class='profile-datablock'> <dt class='profile-data'> <a class='profile-name-link g-profile' href='https://www.blogger.com/profile/08579466817032124881' rel='author' style='background-image: url(//www.blogger.com/img/logo-16.png);'> Neal Gafter </a> </dt> <dd class='profile-textblock'>Neal Gafter is a Computer Programming Language Designer and Implementer, Amateur Scientist and Philosopher. He works on the Rel compiler at Relational.AI. He previously worked for Microsoft on C#, for Google on Calendar, and for Sun Microsystems on Java. Neal was granted an OpenJDK Community Innovators' Challenge award for his design and implementation of lambda expressions for Java. He is coauthor of <em>Java Puzzlers: Traps, Pitfalls, and Corner Cases</em> (Addison Wesley, 2005). He was a member of the C++ Standards Committee and led the development of C and C++ compilers at Sun Microsystems, Microtec Research, and Texas Instruments. He holds a Ph.D. in computer science from the University of Rochester.</dd> </dl> <a class='profile-link' href='https://www.blogger.com/profile/08579466817032124881' rel='author'>View my complete profile</a> <div class='clear'></div> </div> </div></div> </div> <!-- spacer for skins that want sidebar and main to be the same height--> <div class='clear'>&#160;</div> </div> <!-- end content-wrapper --> <div id='footer-wrapper'> <div class='footer no-items section' id='footer'></div> </div> </div></div> <!-- end outer-wrapper --> <script src="//www.google-analytics.com/urchin.js" type="text/javascript"> </script> <script type='text/javascript'> _uacct = "UA-605497-1"; urchinTracker(); </script> <script type="text/javascript" src="https://www.blogger.com/static/v1/widgets/984859869-widgets.js"></script> <script type='text/javascript'> window['__wavt'] = 'AOuZoY6EfCkolp2fpYsmW6z13cshhjQhsg:1732806990549';_WidgetManager._Init('//www.blogger.com/rearrange?blogID\x3d7803021','//gafter.blogspot.com/2007/05/','7803021'); _WidgetManager._SetDataContext([{'name': 'blog', 'data': {'blogId': '7803021', 'title': 'Neal Gafter\x27s blog', 'url': 'https://gafter.blogspot.com/2007/05/', 'canonicalUrl': 'http://gafter.blogspot.com/2007/05/', 'homepageUrl': 'https://gafter.blogspot.com/', 'searchUrl': 'https://gafter.blogspot.com/search', 'canonicalHomepageUrl': 'http://gafter.blogspot.com/', 'blogspotFaviconUrl': 'https://gafter.blogspot.com/favicon.ico', 'bloggerUrl': 'https://www.blogger.com', 'hasCustomDomain': false, 'httpsEnabled': true, 'enabledCommentProfileImages': true, 'gPlusViewType': 'FILTERED_POSTMOD', 'adultContent': false, 'analyticsAccountNumber': '', 'encoding': 'UTF-8', 'locale': 'en', 'localeUnderscoreDelimited': 'en', 'languageDirection': 'ltr', 'isPrivate': false, 'isMobile': false, 'isMobileRequest': false, 'mobileClass': '', 'isPrivateBlog': false, 'isDynamicViewsAvailable': false, 'feedLinks': '\x3clink rel\x3d\x22alternate\x22 type\x3d\x22application/atom+xml\x22 title\x3d\x22Neal Gafter\x26#39;s blog - Atom\x22 href\x3d\x22https://gafter.blogspot.com/feeds/posts/default\x22 /\x3e\n\x3clink rel\x3d\x22alternate\x22 type\x3d\x22application/rss+xml\x22 title\x3d\x22Neal Gafter\x26#39;s blog - RSS\x22 href\x3d\x22https://gafter.blogspot.com/feeds/posts/default?alt\x3drss\x22 /\x3e\n\x3clink rel\x3d\x22service.post\x22 type\x3d\x22application/atom+xml\x22 title\x3d\x22Neal Gafter\x26#39;s blog - Atom\x22 href\x3d\x22https://www.blogger.com/feeds/7803021/posts/default\x22 /\x3e\n', 'meTag': '', 'adsenseHostId': 'ca-host-pub-1556223355139109', 'adsenseHasAds': false, 'adsenseAutoAds': false, 'boqCommentIframeForm': true, 'loginRedirectParam': '', 'view': '', 'dynamicViewsCommentsSrc': '//www.blogblog.com/dynamicviews/4224c15c4e7c9321/js/comments.js', 'dynamicViewsScriptSrc': '//www.blogblog.com/dynamicviews/2fafd358a4bcb2b4', 'plusOneApiSrc': 'https://apis.google.com/js/platform.js', 'disableGComments': true, 'interstitialAccepted': false, 'sharing': {'platforms': [{'name': 'Get link', 'key': 'link', 'shareMessage': 'Get link', 'target': ''}, {'name': 'Facebook', 'key': 'facebook', 'shareMessage': 'Share to Facebook', 'target': 'facebook'}, {'name': 'BlogThis!', 'key': 'blogThis', 'shareMessage': 'BlogThis!', 'target': 'blog'}, {'name': 'X', 'key': 'twitter', 'shareMessage': 'Share to X', 'target': 'twitter'}, {'name': 'Pinterest', 'key': 'pinterest', 'shareMessage': 'Share to Pinterest', 'target': 'pinterest'}, {'name': 'Email', 'key': 'email', 'shareMessage': 'Email', 'target': 'email'}], 'disableGooglePlus': true, 'googlePlusShareButtonWidth': 0, 'googlePlusBootstrap': '\x3cscript type\x3d\x22text/javascript\x22\x3ewindow.___gcfg \x3d {\x27lang\x27: \x27en\x27};\x3c/script\x3e'}, 'hasCustomJumpLinkMessage': false, 'jumpLinkMessage': 'Read more', 'pageType': 'archive', 'pageName': 'May 2007', 'pageTitle': 'Neal Gafter\x27s blog: May 2007'}}, {'name': 'features', 'data': {}}, {'name': 'messages', 'data': {'edit': 'Edit', 'linkCopiedToClipboard': 'Link copied to clipboard!', 'ok': 'Ok', 'postLink': 'Post Link'}}, {'name': 'template', 'data': {'name': 'custom', 'localizedName': 'Custom', 'isResponsive': false, 'isAlternateRendering': false, 'isCustom': true}}, {'name': 'view', 'data': {'classic': {'name': 'classic', 'url': '?view\x3dclassic'}, 'flipcard': {'name': 'flipcard', 'url': '?view\x3dflipcard'}, 'magazine': {'name': 'magazine', 'url': '?view\x3dmagazine'}, 'mosaic': {'name': 'mosaic', 'url': '?view\x3dmosaic'}, 'sidebar': {'name': 'sidebar', 'url': '?view\x3dsidebar'}, 'snapshot': {'name': 'snapshot', 'url': '?view\x3dsnapshot'}, 'timeslide': {'name': 'timeslide', 'url': '?view\x3dtimeslide'}, 'isMobile': false, 'title': 'Neal Gafter\x27s blog', 'description': 'Thoughts about Programming Languages, Science and Philosophy.', 'url': 'https://gafter.blogspot.com/2007/05/', 'type': 'feed', 'isSingleItem': false, 'isMultipleItems': true, 'isError': false, 'isPage': false, 'isPost': false, 'isHomepage': false, 'isArchive': true, 'isLabelSearch': false, 'archive': {'year': 2007, 'month': 5, 'rangeMessage': 'Showing posts from May, 2007'}}}]); _WidgetManager._RegisterWidget('_NavbarView', new _WidgetInfo('Navbar1', 'navbar', document.getElementById('Navbar1'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_HeaderView', new _WidgetInfo('Header1', 'header', document.getElementById('Header1'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_BlogView', new _WidgetInfo('Blog1', 'main', document.getElementById('Blog1'), {'cmtInteractionsEnabled': false, 'lightboxEnabled': true, 'lightboxModuleUrl': 'https://www.blogger.com/static/v1/jsbin/2646514562-lbx.js', 'lightboxCssUrl': 'https://www.blogger.com/static/v1/v-css/1964470060-lightbox_bundle.css'}, 'displayModeFull')); _WidgetManager._RegisterWidget('_BlogArchiveView', new _WidgetInfo('BlogArchive1', 'sidebar', document.getElementById('BlogArchive1'), {'languageDirection': 'ltr', 'loadingMessage': 'Loading\x26hellip;'}, 'displayModeFull')); _WidgetManager._RegisterWidget('_ProfileView', new _WidgetInfo('Profile1', 'sidebar', document.getElementById('Profile1'), {}, 'displayModeFull')); </script> </body> </html>

Pages: 1 2 3 4 5 6 7 8 9 10