{"id":237,"date":"2006-12-08T10:13:37","date_gmt":"2006-12-08T10:13:37","guid":{"rendered":"http:\/\/scientopia.org\/blogs\/goodmath\/2006\/12\/08\/pathological-stack-hell-underload\/"},"modified":"2006-12-08T10:13:37","modified_gmt":"2006-12-08T10:13:37","slug":"pathological-stack-hell-underload","status":"publish","type":"post","link":"http:\/\/www.goodmath.org\/blog\/2006\/12\/08\/pathological-stack-hell-underload\/","title":{"rendered":"Pathological Stack Hell: Underload"},"content":{"rendered":"<p>Our pathological language this week is [Underload][underload]. Underload is, in some ways, similar to Muriel, only it&#8217;s a much more sensible language. In fact, there are actually serious<br \/>\npractical languages called *concatenative languages* based on the same idea as Underload: [Joy][joy] and [Factor][factor] are two examples.<br \/>\n[underload]: http:\/\/esoteric.voxelperfect.net\/wiki\/Underload<br \/>\n[muriel]: http:\/\/scienceblogs.com\/goodmath\/2006\/11\/friday_pathological_programmin_5.php<br \/>\n[joy]: http:\/\/www.latrobe.edu.au\/philosophy\/phimvt\/joy.html<br \/>\n[factor]: http:\/\/www.factorcode.org\/<br \/>\nUnderload is a remarkably simple language. It&#8217;s stack based, like Forth, so all of the data is stored on the stack. Its only means of control is constructing a program on the stack and executing it; and the only data that it can manipulate is lists of characters.<br \/>\nThe commands in Underload are:<br \/>\n* `~` &#8211;  swap the top two elements on the stack.<br \/>\n* `:` &#8211; duplicate the top element on the stack.<br \/>\n* `!` &#8211; discard the top element on the stack.<br \/>\n* `*` &#8211; concatenate the two elements on top of the stack into a single list.<br \/>\n* `a`  &#8211; take the element on top of the stack, and wrap it in &#8220;()&#8221;s.<br \/>\n* `(&#8230;)` &#8211; push the contents of the parens on the stack as a single stack element.<br \/>\n* `S` &#8211; print the element on top of the stack.<br \/>\n* `^` &#8211; take the element on top of the stack, and append it to the currently executing program<br \/>\nstring.<br \/>\nAs usual, we&#8217;ll start with a &#8220;Hello world&#8221; program.<br \/>\n(Hello world!)S<br \/>\nSimple, right?<br \/>\nSuppose we wanted to add two numbers. The easiest way to handle numbers in Underload is unary format. So suppose want to add 3 + 5. First, we need to put 3 and 5 on the stack. We can represent three as a list `xxx` and 5 as a list `xxxxx`. To push those onto the stack, we need<br \/>\nto wrap them in parens; and t add them, we want to just concatenate the two lists. So the program to add 3 + 5 and print the result is:<br \/>\n(xxx)(xxxxx)*S<br \/>\nAs you&#8217;d probably expect, an Underload quine is extremely simple:<br \/>\n(:aSS):aSS<br \/>\nI&#8217;ll walk through that just to make it clear. First, the list `&#8221;:aSS&#8221;` is pushed onto the stack, so writing the stack as a list of comma separated elements,  the stack is &#8220;`[:aSS]`&#8221;. Then we execute &#8220;:&#8221;, which duplicates the top of the stack, leaving &#8220;`[:aSS,:aSS]`&#8221;. Then we execute &#8220;a&#8221;, which wraps the element on top of the stack in parens, giving us &#8220;`[(:aSS),:aSS]`&#8221;. Now there are two &#8220;S&#8221; commands, which output the two top stack elements; so the out is `(:aSS):aSS`.<br \/>\nA program to generate the fibonacci series is also pretty simple:<br \/>\n(()(*))(~:^:S*a~^a~!~*~:(\/)S^):^<br \/>\nIt looks like a nighmare, but it&#8217;s really not bad. It starts with &#8220;()&#8221; (0) and &#8220;(*)&#8221; (1) on the stack. And the rest of the program basically copies the larger number, adds the smaller and larger (giving the next element of the sequence), leaving two fibonacci numbers of the stack. It duplicates the larger, prints it, and then goes on to the next iteration. The body of the program is `(~:^:S*a~^a~!~*~:(\/)S^)`, which at the very beginning `(~:^)` duplicates itself.<br \/>\nThere&#8217;s an online interpreter for [Underload][interp] which does single-stepping. I recommend popping over there, and watching the fibonacci series program execute. It&#8217;s much more interesting to watch it in action than it would be to read my detailed description of it!<br \/>\nNow, is this Turing complete? It&#8217;s a little hard to see. But the author of Underload took care of that question, by showing how to compile [Unlambda][unlambda] into Underload.<br \/>\n* Unlambda &#8220;`s`&#8221; translates to Underload &#8220;`((:)~*(~)*a(~*(~^)*))`&#8221;<br \/>\n* Unlambda &#8220;`k`&#8221; translates to Underload &#8220;`(a(!)~*)`&#8221;<br \/>\n* Unlambda &#8220;`i`&#8221; translates to Underload &#8220;`()`&#8221;.<br \/>\n* Unlambda &#8220;&#8220;&#8220;&#8221; translates to Underload &#8220;~^&#8221;.<br \/>\n* Unlambda &#8220;`.x`&#8221; translates to Underload &#8220;`((x)S)`&#8221;.<br \/>\n[interp]: http:\/\/esoteric.voxelperfect.net\/files\/underload\/underload.html<br \/>\n[unlambda]: http:\/\/scienceblogs.com\/goodmath\/2006\/08\/friday_pathological_programmin_3.php<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Our pathological language this week is [Underload][underload]. Underload is, in some ways, similar to Muriel, only it&#8217;s a much more sensible language. In fact, there are actually serious practical languages called *concatenative languages* based on the same idea as Underload: [Joy][joy] and [Factor][factor] are two examples. [underload]: http:\/\/esoteric.voxelperfect.net\/wiki\/Underload [muriel]: http:\/\/scienceblogs.com\/goodmath\/2006\/11\/friday_pathological_programmin_5.php [joy]: http:\/\/www.latrobe.edu.au\/philosophy\/phimvt\/joy.html [factor]: http:\/\/www.factorcode.org\/ Underload [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[92],"tags":[],"class_list":["post-237","post","type-post","status-publish","format-standard","hentry","category-pathological-programming"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p4lzZS-3P","jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"_links":{"self":[{"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/posts\/237","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/comments?post=237"}],"version-history":[{"count":0,"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/posts\/237\/revisions"}],"wp:attachment":[{"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/media?parent=237"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/categories?post=237"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/tags?post=237"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}