iRihttp://www.jerf.org/iri/Tagline pending.en-usSun, 27 Jul 2014 23:16:21 -0000 And the cat&#39;s in the cradle and the silver spoon, Little boy blue and the ... http://www.jerf.org/iri/post/2934 <p><i>And the cat's in the cradle and the silver spoon,<br /> Little boy blue and the man in the moon.<br /> "When you coming home, dad?" "I'm home right now,<br /> having some fun and how,<br /> You know we're having fun and how!"</i></p> jerf@jerf.org (jerf)Sun, 27 Jul 2014 23:16:21 -0000http://www.jerf.org/iri/post/2934 Go: More UNIX than UNIX http://www.jerf.org/iri/post/2931 <p>Go comes in part from Rob Pike and Ken Thompson, both influential in early UNIX. Both Rob Pike and Ken Thompson also were influential in working on <a href='http://en.wikipedia.org/wiki/Plan_9_from_Bell_Labs'>Plan 9</a>, a followup to UNIX.</p> <p>UNIX's ideal is that "everything is a file". In Go terminology, this is a declaration that everything should be accessible via a uniform <tt>interface</tt>, which the OS specially privileges. One of Plan 9's core reasons for existing is that UNIX didn't take this anywhere near as far as it could be taken, and it goes much further in making everything accessible as a file in a directory structure.</p> <p>I'm skeptical of both of these approaches. Everything <i>isn't</i> a "file".</p> <p>There's numerous "files" that require <a href='http://en.wikipedia.org/wiki/Ioctl'>ioctls</a> to correctly manipulate, which are arbitrary extensions outside of the file interface. On the flip side, there are all kinds of "files" that can't be seeked, such as sockets, or files that can't be closed, like UDP streams. Pretty much every element of the file interface is one that doesn't apply to some "file", somewhere.</p> <p>The <a href='http://en.wikipedia.org/wiki/Procrustes'>Procrustean approach</a> to software engineering tends to have the same results as Procrustes himself did, gravely or even fatally wounding the code in question.</p> <p><a href="http://www.jerf.org/iri/post/2931">Read the rest...</a></p> jerf@jerf.org (jerf)Tue, 29 Apr 2014 14:20:39 -0000http://www.jerf.org/iri/post/2931ProgrammingGolang Suture - Supervisor Trees for Go http://www.jerf.org/iri/post/2930 <p>Supervisor trees are one of the core ingredients in Erlang's reliability and <a href='http://blogs.teamb.com/craigstuntz/2008/05/19/37819/'>let it crash philosophy</a>. A well-structured Erlang program is broken into multiple independent pieces that communicate via messages, and when a piece crashes, the supervisor of that piece automatically restarts it.</p> <p>This may not sound very impressive if you've never used it. But I have witnessed systems that I have written experience dozens of crashes per minute, but function correctly for 99% of the users. Even as I have been writing <a href='https://github.com/thejerf/suture'>suture</a>, I have on occasion been astonished to flip my screen over to the console of Go program I've written with suture, and been surprised to discover that it's actually been merrily crashing away during my manual testing, but soldiering on so well I didn't even know.</p> <p>(This is, of course, immediately followed by improving my logging so I <i>do</i> know when it happens in the future. Being crash-resistant is good, but one should not "spend" this valuable resource frivolously!)</p> <p>I've been porting a system out of Erlang into Go for various other reasons, and I've missed having supervisor trees around. I decided to create them in Go. But this is one of those cases where we do not need a transliteration of the Erlang code into Go. For one thing, that's simply impossible as the two are mutually incompatible in some fundamental ways. We want an idiomatic <i>translation</i> of the functionality, which retains as much as possible of the original while perhaps introducing whatever new local capabilities into it make sense.</p> <p>To correctly do that, step one is to deeply examine not only the <i>what</i> of Erlang supervision trees, but the <i>why</i>, and then figure out how to translate.</p> <p><a href="http://www.jerf.org/iri/post/2930">Read the rest...</a></p> jerf@jerf.org (jerf)Tue, 22 Apr 2014 20:31:15 -0000http://www.jerf.org/iri/post/2930ProgrammingGolang The Environment Object Pattern in Go http://www.jerf.org/iri/post/2929 <p>One of the things I've been really enjoying about Go is how easy testing is. The pervasive use of interfaces and composition-instead-of-inheritance synergize nicely for testing. But as I've expressed this online on reddit and Hacker News a couple of times, I've found that this does not seem to be a universally-shared opinion. Some have even commented on how hard it is to test in Go.</p> <p>Since we are all obviously using the same language, the difference must lie in coding behavior. I've internalized a lot of testing methodology over the years, and I find some of the things work even better in Go that most other imperative languages. Let me share one of my core tricks today, which I will call the Environment Object pattern, and why Go makes it incrementally easier to use than other similar (imperative) environments.</p> <p><a href="http://www.jerf.org/iri/post/2929">Read the rest...</a></p> jerf@jerf.org (jerf)Fri, 24 Jan 2014 01:31:40 -0000http://www.jerf.org/iri/post/2929ProgrammingGolang So you want to write a Monad tutorial in Not-Haskell... http://www.jerf.org/iri/post/2928 <p>There are a number of errors made in putative Monad tutorials in languages other than Haskell. Any implementation of monadic computations should be able to implement the equivalent of the following in Haskell:</p> <pre>minimal :: Bool -&gt; [(Int, String)] minimal b = do x &lt;- if b then [1, 2] else [3, 4] if x `mod` 2 == 0 then do y &lt;- ["a", "b"] return (x, y) else do y &lt;- ["y", "z"] return (x, y)</pre> <p>This should yield the local equivalent of:</p> <pre>Prelude&gt; minimal True [(1,"y"),(1,"z"),(2,"a"),(2,"b")] Prelude&gt; minimal False [(3,"y"),(3,"z"),(4,"a"),(4,"b")]</pre> <p>At the risk of being offensive, you, ahhh... really ought to understand <i>why</i> that's the result too, without too much effort... or you really shouldn't be writing a Monad tutorial. <i>Ahem.</i></p> <p>In particular:</p> <ul><li>Many putative monadic computation solutions only work with a "container" that contains zero or one elements, and therefore do not work on lists. <tt>&gt;&gt;=</tt> is allowed to call its second argument (<tt>a -&gt; m b</tt>) an <i>arbitrary</i> number of times. It may be once, it may be dozens, it may be none. If you can't do that, you don't have a monadic computation.</li> <li>A monadic computation has the ability to examine the intermediate results of the computation, and make decisions, as shown by the if statement. If you can't do that, you don't have a monadic computation.</li> <li>In statically-typed languages, the type of the inner value is not fixed at the beginning. It's <tt>a -&gt; m b</tt>, not <tt>a -&gt; m a</tt>, which is quite different. Note how <tt>x</tt> and <tt>y</tt> are of different types.</li> <li>The monadic computation builds up a namespace as it goes along; note we determine <tt>x</tt>, then somewhat later use it in the <tt>return</tt>, regardless of which branch we go down, and in both cases, we do not use it right away. Many putative implementations end up with a pipeline, where each stage can use the previous stage's values, but can not refer back to values before that.</li></ul> <p>A common misconception is that you can implement this in Javascript or similar languages using "method chaining". I do not believe this is possible; for monadic computations to work in Javascript at all, you <i>must</i> be nesting functions within calls to bind within functions within calls to bind... basically, it's impossibly inconvenient to use monadic computations in Javascript, and a number of other languages. A mere implementation of method chaining is not "monadic", and libraries that use method chaining are not "monadic" (unless they really do implement the rest of what it takes to be a monad, but I've so far never seen one).</p> <p>If you <i>can</i> translate the above code correctly, and obtain the correct result, I don't guarantee that you have a proper monadic computation, but if you've got a bind or a join function with the right type signatures, and you can do the above, you're probably at least on the right track. This is the approximately minimal example that a putative implementation of a monadic computation ought to be able to do.</p> jerf@jerf.org (jerf)Fri, 17 Jan 2014 19:47:56 -0000http://www.jerf.org/iri/post/2928ProgrammingHaskell