CINXE.COM
Ken Shirriff's blog: 2008
<!DOCTYPE html> <html class='v2' dir='ltr' 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/3566091532-css_bundle_v2.css' rel='stylesheet' type='text/css'/> <meta content='width=1100' name='viewport'/> <meta content='text/html; charset=UTF-8' http-equiv='Content-Type'/> <meta content='blogger' name='generator'/> <link href='http://www.righto.com/favicon.ico' rel='icon' type='image/x-icon'/> <link href='http://www.righto.com/2008/' rel='canonical'/> <link rel="alternate" type="application/atom+xml" title="Ken Shirriff's blog - Atom" href="http://www.righto.com/feeds/posts/default" /> <link rel="alternate" type="application/rss+xml" title="Ken Shirriff's blog - RSS" href="http://www.righto.com/feeds/posts/default?alt=rss" /> <link rel="service.post" type="application/atom+xml" title="Ken Shirriff's blog - Atom" href="https://www.blogger.com/feeds/6264947694886887540/posts/default" /> <!--Can't find substitution for tag [blog.ieCssRetrofitLinks]--> <meta content='http://www.righto.com/2008/' property='og:url'/> <meta content='Ken Shirriff's blog' property='og:title'/> <meta content='Computer history, restoring vintage computers, IC reverse engineering, and whatever' property='og:description'/> <title>Ken Shirriff's blog: 2008</title> <style type='text/css'>@font-face{font-family:'Play';font-style:normal;font-weight:400;font-display:swap;src:url(//fonts.gstatic.com/s/play/v19/6aez4K2oVqwIvtU2Gw.eot);}</style> <style id='page-skin-1' type='text/css'><!-- /* ----------------------------------------------- Blogger Template Style Name: Simple Designer: Blogger URL: www.blogger.com ----------------------------------------------- */ /* Variable definitions ==================== <Variable name="keycolor" description="Main Color" type="color" default="#66bbdd"/> <Group description="Page Text" selector="body"> <Variable name="body.font" description="Font" type="font" default="normal normal 12px Arial, Tahoma, Helvetica, FreeSans, sans-serif"/> <Variable name="body.text.color" description="Text Color" type="color" default="#222222"/> </Group> <Group description="Backgrounds" selector=".body-fauxcolumns-outer"> <Variable name="body.background.color" description="Outer Background" type="color" default="#66bbdd"/> <Variable name="content.background.color" description="Main Background" type="color" default="#ffffff"/> <Variable name="header.background.color" description="Header Background" type="color" default="transparent"/> </Group> <Group description="Links" selector=".main-outer"> <Variable name="link.color" description="Link Color" type="color" default="#2288bb"/> <Variable name="link.visited.color" description="Visited Color" type="color" default="#888888"/> <Variable name="link.hover.color" description="Hover Color" type="color" default="#33aaff"/> </Group> <Group description="Blog Title" selector=".header h1"> <Variable name="header.font" description="Font" type="font" default="normal normal 60px Arial, Tahoma, Helvetica, FreeSans, sans-serif"/> <Variable name="header.text.color" description="Title Color" type="color" default="#3399bb" /> </Group> <Group description="Blog Description" selector=".header .description"> <Variable name="description.text.color" description="Description Color" type="color" default="#777777" /> </Group> <Group description="Tabs Text" selector=".tabs-inner .widget li a"> <Variable name="tabs.font" description="Font" type="font" default="normal normal 14px Arial, Tahoma, Helvetica, FreeSans, sans-serif"/> <Variable name="tabs.text.color" description="Text Color" type="color" default="#999999"/> <Variable name="tabs.selected.text.color" description="Selected Color" type="color" default="#000000"/> </Group> <Group description="Tabs Background" selector=".tabs-outer .PageList"> <Variable name="tabs.background.color" description="Background Color" type="color" default="#f5f5f5"/> <Variable name="tabs.selected.background.color" description="Selected Color" type="color" default="#eeeeee"/> </Group> <Group description="Post Title" selector="h3.post-title, .comments h4"> <Variable name="post.title.font" description="Font" type="font" default="normal normal 22px Arial, Tahoma, Helvetica, FreeSans, sans-serif"/> </Group> <Group description="Date Header" selector=".date-header"> <Variable name="date.header.color" description="Text Color" type="color" default="#222222"/> <Variable name="date.header.background.color" description="Background Color" type="color" default="transparent"/> <Variable name="date.header.font" description="Text Font" type="font" default="normal bold 11px Arial, Tahoma, Helvetica, FreeSans, sans-serif"/> <Variable name="date.header.padding" description="Date Header Padding" type="string" default="inherit"/> <Variable name="date.header.letterspacing" description="Date Header Letter Spacing" type="string" default="inherit"/> <Variable name="date.header.margin" description="Date Header Margin" type="string" default="inherit"/> </Group> <Group description="Post Footer" selector=".post-footer"> <Variable name="post.footer.text.color" description="Text Color" type="color" default="#666666"/> <Variable name="post.footer.background.color" description="Background Color" type="color" default="#f9f9f9"/> <Variable name="post.footer.border.color" description="Shadow Color" type="color" default="#eeeeee"/> </Group> <Group description="Gadgets" selector="h2"> <Variable name="widget.title.font" description="Title Font" type="font" default="normal bold 11px Arial, Tahoma, Helvetica, FreeSans, sans-serif"/> <Variable name="widget.title.text.color" description="Title Color" type="color" default="#000000"/> <Variable name="widget.alternate.text.color" description="Alternate Color" type="color" default="#999999"/> </Group> <Group description="Images" selector=".main-inner"> <Variable name="image.background.color" description="Background Color" type="color" default="#ffffff"/> <Variable name="image.border.color" description="Border Color" type="color" default="#eeeeee"/> <Variable name="image.text.color" description="Caption Text Color" type="color" default="#222222"/> </Group> <Group description="Accents" selector=".content-inner"> <Variable name="body.rule.color" description="Separator Line Color" type="color" default="#eeeeee"/> <Variable name="tabs.border.color" description="Tabs Border Color" type="color" default="#eeeeee"/> </Group> <Variable name="body.background" description="Body Background" type="background" color="#f6fbf6" default="$(color) none repeat scroll top left"/> <Variable name="body.background.override" description="Body Background Override" type="string" default=""/> <Variable name="body.background.gradient.cap" description="Body Gradient Cap" type="url" default="url(https://resources.blogblog.com/blogblog/data/1kt/simple/gradients_light.png)"/> <Variable name="body.background.gradient.tile" description="Body Gradient Tile" type="url" default="url(https://resources.blogblog.com/blogblog/data/1kt/simple/body_gradient_tile_light.png)"/> <Variable name="content.background.color.selector" description="Content Background Color Selector" type="string" default=".content-inner"/> <Variable name="content.padding" description="Content Padding" type="length" default="10px" min="0" max="100px"/> <Variable name="content.padding.horizontal" description="Content Horizontal Padding" type="length" default="10px" min="0" max="100px"/> <Variable name="content.shadow.spread" description="Content Shadow Spread" type="length" default="40px" min="0" max="100px"/> <Variable name="content.shadow.spread.webkit" description="Content Shadow Spread (WebKit)" type="length" default="5px" min="0" max="100px"/> <Variable name="content.shadow.spread.ie" description="Content Shadow Spread (IE)" type="length" default="10px" min="0" max="100px"/> <Variable name="main.border.width" description="Main Border Width" type="length" default="0" min="0" max="10px"/> <Variable name="header.background.gradient" description="Header Gradient" type="url" default="none"/> <Variable name="header.shadow.offset.left" description="Header Shadow Offset Left" type="length" default="-1px" min="-50px" max="50px"/> <Variable name="header.shadow.offset.top" description="Header Shadow Offset Top" type="length" default="-1px" min="-50px" max="50px"/> <Variable name="header.shadow.spread" description="Header Shadow Spread" type="length" default="1px" min="0" max="100px"/> <Variable name="header.padding" description="Header Padding" type="length" default="30px" min="0" max="100px"/> <Variable name="header.border.size" description="Header Border Size" type="length" default="1px" min="0" max="10px"/> <Variable name="header.bottom.border.size" description="Header Bottom Border Size" type="length" default="0" min="0" max="10px"/> <Variable name="header.border.horizontalsize" description="Header Horizontal Border Size" type="length" default="0" min="0" max="10px"/> <Variable name="description.text.size" description="Description Text Size" type="string" default="140%"/> <Variable name="tabs.margin.top" description="Tabs Margin Top" type="length" default="0" min="0" max="100px"/> <Variable name="tabs.margin.side" description="Tabs Side Margin" type="length" default="30px" min="0" max="100px"/> <Variable name="tabs.background.gradient" description="Tabs Background Gradient" type="url" default="url(https://resources.blogblog.com/blogblog/data/1kt/simple/gradients_light.png)"/> <Variable name="tabs.border.width" description="Tabs Border Width" type="length" default="1px" min="0" max="10px"/> <Variable name="tabs.bevel.border.width" description="Tabs Bevel Border Width" type="length" default="1px" min="0" max="10px"/> <Variable name="post.margin.bottom" description="Post Bottom Margin" type="length" default="25px" min="0" max="100px"/> <Variable name="image.border.small.size" description="Image Border Small Size" type="length" default="2px" min="0" max="10px"/> <Variable name="image.border.large.size" description="Image Border Large Size" type="length" default="5px" min="0" max="10px"/> <Variable name="page.width.selector" description="Page Width Selector" type="string" default=".region-inner"/> <Variable name="page.width" description="Page Width" type="string" default="auto"/> <Variable name="main.section.margin" description="Main Section Margin" type="length" default="15px" min="0" max="100px"/> <Variable name="main.padding" description="Main Padding" type="length" default="15px" min="0" max="100px"/> <Variable name="main.padding.top" description="Main Padding Top" type="length" default="30px" min="0" max="100px"/> <Variable name="main.padding.bottom" description="Main Padding Bottom" type="length" default="30px" min="0" max="100px"/> <Variable name="paging.background" color="#ffffff" description="Background of blog paging area" type="background" default="transparent none no-repeat scroll top center"/> <Variable name="footer.bevel" description="Bevel border length of footer" type="length" default="0" min="0" max="10px"/> <Variable name="mobile.background.overlay" description="Mobile Background Overlay" type="string" default="transparent none repeat scroll top left"/> <Variable name="mobile.background.size" description="Mobile Background Size" type="string" default="auto"/> <Variable name="mobile.button.color" description="Mobile Button Color" type="color" default="#ffffff" /> <Variable name="startSide" description="Side where text starts in blog language" type="automatic" default="left"/> <Variable name="endSide" description="Side where text ends in blog language" type="automatic" default="right"/> */ /* Content ----------------------------------------------- */ body { font: normal normal 14px Arial, Tahoma, Helvetica, FreeSans, sans-serif; color: #222222; background: #f6fbf6 none repeat scroll top left; padding: 0 40px 40px 40px; } html body .region-inner { min-width: 0; max-width: 100%; width: auto; } h2 { font-size: 22px; } a:link { text-decoration:none; color: #121fb3; } a:visited { text-decoration:none; color: #121fb3; } a:hover { text-decoration:underline; color: #1a00ff; } .body-fauxcolumn-outer .fauxcolumn-inner { background: transparent url(//www.blogblog.com/1kt/simple/body_gradient_tile_light.png) repeat scroll top left; _background-image: none; } .body-fauxcolumn-outer .cap-top { position: absolute; z-index: 1; height: 400px; width: 100%; } .body-fauxcolumn-outer .cap-top .cap-left { width: 100%; background: transparent url(//www.blogblog.com/1kt/simple/gradients_light.png) repeat-x scroll top left; _background-image: none; } .content-outer { -moz-box-shadow: 0 0 40px rgba(0, 0, 0, .15); -webkit-box-shadow: 0 0 5px rgba(0, 0, 0, .15); -goog-ms-box-shadow: 0 0 10px #333333; box-shadow: 0 0 40px rgba(0, 0, 0, .15); margin-bottom: 1px; } .content-inner { padding: 10px 10px; } .content-inner { background-color: #ffffff; } /* Header ----------------------------------------------- */ .header-outer { background: #f6fbf7 url(//www.blogblog.com/1kt/simple/gradients_light.png) repeat-x scroll 0 -400px; _background-image: none; } .Header h1 { font: normal normal 42px Play; color: #666666; text-shadow: 1px 2px 3px rgba(0, 0, 0, .2); } .Header h1 a { color: #666666; } .Header .description { font-size: 140%; color: #666666; } .header-inner .Header .titlewrapper { padding: 22px 30px; } .header-inner .Header .descriptionwrapper { padding: 0 30px; } /* Tabs ----------------------------------------------- */ .tabs-inner .section:first-child { border-top: 0 solid #eeeeee; } .tabs-inner .section:first-child ul { margin-top: -0; border-top: 0 solid #eeeeee; border-left: 0 solid #eeeeee; border-right: 0 solid #eeeeee; } .tabs-inner .widget ul { background: #f5f5f5 url(//www.blogblog.com/1kt/simple/gradients_light.png) repeat-x scroll 0 -800px; _background-image: none; border-bottom: 1px solid #eeeeee; margin-top: 0; margin-left: -30px; margin-right: -30px; } .tabs-inner .widget li a { display: inline-block; padding: .6em 1em; font: normal normal 14px Arial, Tahoma, Helvetica, FreeSans, sans-serif; color: #999999; border-left: 1px solid #ffffff; border-right: 1px solid #eeeeee; } .tabs-inner .widget li:first-child a { border-left: none; } .tabs-inner .widget li.selected a, .tabs-inner .widget li a:hover { color: #000000; background-color: #eeeeee; text-decoration: none; } /* Columns ----------------------------------------------- */ .main-outer { border-top: 0 solid #eeeeee; } .fauxcolumn-left-outer .fauxcolumn-inner { border-right: 1px solid #eeeeee; } .fauxcolumn-right-outer .fauxcolumn-inner { border-left: 1px solid #eeeeee; } /* Headings ----------------------------------------------- */ div.widget > h2, div.widget h2.title { margin: 0 0 1em 0; font: normal bold 11px Arial, Tahoma, Helvetica, FreeSans, sans-serif; color: #000000; } /* Widgets ----------------------------------------------- */ .widget .zippy { color: #999999; text-shadow: 2px 2px 1px rgba(0, 0, 0, .1); } .widget .popular-posts ul { list-style: none; } /* Posts ----------------------------------------------- */ h2.date-header { font: normal bold 11px Arial, Tahoma, Helvetica, FreeSans, sans-serif; } .date-header span { background-color: transparent; color: transparent; padding: inherit; letter-spacing: inherit; margin: inherit; } .main-inner { padding-top: 30px; padding-bottom: 30px; } .main-inner .column-center-inner { padding: 0 15px; } .main-inner .column-center-inner .section { margin: 0 15px; } .post { margin: 0 0 25px 0; } h3.post-title, .comments h4 { font: normal normal 22px Arial, Tahoma, Helvetica, FreeSans, sans-serif; margin: .75em 0 0; } .post-body { font-size: 110%; line-height: 1.4; position: relative; } .post-body img, .post-body .tr-caption-container, .Profile img, .Image img, .BlogList .item-thumbnail img { padding: 2px; background: #ffffff; border: 1px solid #ffffff; -moz-box-shadow: 1px 1px 5px rgba(0, 0, 0, .1); -webkit-box-shadow: 1px 1px 5px rgba(0, 0, 0, .1); box-shadow: 1px 1px 5px rgba(0, 0, 0, .1); } .post-body img, .post-body .tr-caption-container { padding: 5px; } .post-body .tr-caption-container { color: #222222; } .post-body .tr-caption-container img { padding: 0; background: transparent; border: none; -moz-box-shadow: 0 0 0 rgba(0, 0, 0, .1); -webkit-box-shadow: 0 0 0 rgba(0, 0, 0, .1); box-shadow: 0 0 0 rgba(0, 0, 0, .1); } .post-header { margin: 0 0 1.5em; line-height: 1.6; font-size: 90%; } .post-footer { margin: 20px -2px 0; padding: 5px 10px; color: #666666; background-color: #f9f9f9; border-bottom: 1px solid #eeeeee; line-height: 1.6; font-size: 90%; } #comments .comment-author { padding-top: 1.5em; border-top: 1px solid #eeeeee; background-position: 0 1.5em; } #comments .comment-author:first-child { padding-top: 0; border-top: none; } .avatar-image-container { margin: .2em 0 0; } #comments .avatar-image-container img { border: 1px solid #ffffff; } /* Comments ----------------------------------------------- */ .comments .comments-content .icon.blog-author { background-repeat: no-repeat; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEgAACxIB0t1+/AAAAAd0SU1FB9sLFwMeCjjhcOMAAAD+SURBVDjLtZSvTgNBEIe/WRRnm3U8RC1neQdsm1zSBIU9VVF1FkUguQQsD9ITmD7ECZIJSE4OZo9stoVjC/zc7ky+zH9hXwVwDpTAWWLrgS3QAe8AZgaAJI5zYAmc8r0G4AHYHQKVwII8PZrZFsBFkeRCABYiMh9BRUhnSkPTNCtVXYXURi1FpBDgArj8QU1eVXUzfnjv7yP7kwu1mYrkWlU33vs1QNu2qU8pwN0UpKoqokjWwCztrMuBhEhmh8bD5UDqur75asbcX0BGUB9/HAMB+r32hznJgXy2v0sGLBcyAJ1EK3LFcbo1s91JeLwAbwGYu7TP/3ZGfnXYPgAVNngtqatUNgAAAABJRU5ErkJggg==); } .comments .comments-content .loadmore a { border-top: 1px solid #999999; border-bottom: 1px solid #999999; } .comments .comment-thread.inline-thread { background-color: #f9f9f9; } .comments .continue { border-top: 2px solid #999999; } /* Accents ---------------------------------------------- */ .section-columns td.columns-cell { border-left: 1px solid #eeeeee; } .blog-pager { background: transparent none no-repeat scroll top center; } .blog-pager-older-link, .home-link, .blog-pager-newer-link { background-color: #ffffff; padding: 5px; } .footer-outer { border-top: 0 dashed #bbbbbb; } /* Mobile ----------------------------------------------- */ body.mobile { background-size: auto; } .mobile .body-fauxcolumn-outer { background: transparent none repeat scroll top left; } .mobile .body-fauxcolumn-outer .cap-top { background-size: 100% auto; } .mobile .content-outer { -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, .15); box-shadow: 0 0 3px rgba(0, 0, 0, .15); } .mobile .tabs-inner .widget ul { margin-left: 0; margin-right: 0; } .mobile .post { margin: 0; } .mobile .main-inner .column-center-inner .section { margin: 0; } .mobile .date-header span { padding: 0.1em 10px; margin: 0 -10px; } .mobile h3.post-title { margin: 0; } .mobile .blog-pager { background: transparent none no-repeat scroll top center; } .mobile .footer-outer { border-top: none; } .mobile .main-inner, .mobile .footer-inner { background-color: #ffffff; } .mobile-index-contents { color: #222222; } .mobile-link-button { background-color: #121fb3; } .mobile-link-button a:link, .mobile-link-button a:visited { color: #ffffff; } .mobile .tabs-inner .section:first-child { border-top: none; } .mobile .tabs-inner .PageList .widget-content { background-color: #eeeeee; color: #000000; border-top: 1px solid #eeeeee; border-bottom: 1px solid #eeeeee; } .mobile .tabs-inner .PageList .widget-content .pagelist-arrow { border-left: 1px solid #eeeeee; } .content-outer { max-width: 1400px !important; } /* fix header */ #header-inner { width: 100% !important; background-position: right !important; } .titlewrapper { padding: 11px 30px 0 !important; } .descriptionwrapper { margin-bottom: 0 !important; } .description { font-size: 120% !important; } /* suppress things */ .date-header { display: none; } #Attribution1 { display: none; } .post-author, .post-timestamp, .reaction-buttons { display: none; } /* h2: sidebar titles */ /* h3: post title */ .post-title , .entry-title { font-size: 180% !important; margin-top: 0 !important; } .entry-title a:link, .entry-title a:visited, .entry-title a:active{ color: #a03; } #main h2 { color:#333; margin-bottom:.4em; margin-top: 13px; font-size:140%; } #main h3 { color:#333; margin-bottom:.4em; margin-top: 13px; font-size:110%; } #main h4 { color:#333; margin-bottom:.5em; } #sidebar-right-1 a:link, #sidebar-right-1 a:visited, #sidebar-right-1 a:active { color: #666; } #sidebar-right-1 h2 { font-size: 100%; color: #666; } /* disable image box */ element.style { } table.chargers img { height: 18px; } table.chargers img { height: 18px; } .post-body img, .post-body .tr-caption-container { padding: 5px; } .post-body img, .post-body .tr-caption-container, .Profile img, .Image img, .BlogList .item-thumbnail img { padding: 0; background: #ffffff; border: none; -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; } /* Special items */ a:link img.hilite, a:visited img.hilite { color: #fff; } a:hover img.hilite, a:hover img.hilite2 { color: #f66; } a:active img.hilite { color: #33c; } .hilite {cursor:zoom-in} pre {color:#000000;border:1px solid #000000;} pre.repl { background-color:#e0e0f0; font-size:120%;} pre.arc { background-color:#e0e0f0; font-size:120%;} pre.code { background-color:#e0f0e0; font-size:120%; white-space:pre-wrap;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word;text-wrap:unrestricted;} code { font-size: 100%;} blockquote { font-size: 110%; background: transparent url("//static.righto.com/images/blockquote.gif") no-repeat 0 0; margin: 20px 0px; padding: 0px 40px;} div.cite {font-size: .8em;.; font-style: italic; color: #888; margin-bottom: 9px;} a.ref { color: gray;vertical-align: super; text-decoration: none; font-size:60%;margin-left: 2px;} a img.hilite { border: 1px solid; color: #888; z-index: 2; } a img.hilite2, a:active img.hilite2 { border: 1px solid; color: #f6fbf6; } table.chargers { border-width: 1px; border-spacing: 2px; border-style: outset; border-color: gray; border-collapse: collapse; background-color: white; } table.chargers th.maker { padding-right: 5px; text-align: right; } table.chargers th { border-width: 1px; padding: 3px; border-style: inset; border-color: gray; background-color: white; text-align: center; } table.chargers img { height: 18px; } table.chargers td { text-align: center; border-width: 1px; padding: 2px 8px; border-style: inset; border-color: gray; background-color: white; } --></style> <style id='template-skin-1' type='text/css'><!-- body { min-width: 750px; } .content-outer, .content-fauxcolumn-outer, .region-inner { min-width: 750px; max-width: 750px; _width: 750px; } .main-inner .columns { padding-left: 0px; padding-right: 240px; } .main-inner .fauxcolumn-center-outer { left: 0px; right: 240px; /* IE6 does not respect left and right together */ _width: expression(this.parentNode.offsetWidth - parseInt("0px") - parseInt("240px") + 'px'); } .main-inner .fauxcolumn-left-outer { width: 0px; } .main-inner .fauxcolumn-right-outer { width: 240px; } .main-inner .column-left-outer { width: 0px; right: 100%; margin-left: -0px; } .main-inner .column-right-outer { width: 240px; margin-right: -240px; } #layout { min-width: 0; } #layout .content-outer { min-width: 0; width: 800px; } #layout .region-inner { min-width: 0; width: auto; } --></style> <meta content='width=device-width, initial-scale=1.0, maximum-scale=12.0, minimum-scale=.25, user-scalable=yes' name='viewport'/> <meta content='mw8ww70r3jW0GzXY6j1d' name='follow_it-verification-code'/> <link href='https://www.blogger.com/dyn-css/authorization.css?targetBlogID=6264947694886887540&zx=a927c2ec-ff76-4713-a4d7-bad5d5d1c05d' media='none' onload='if(media!='all')media='all'' rel='stylesheet'/><noscript><link href='https://www.blogger.com/dyn-css/authorization.css?targetBlogID=6264947694886887540&zx=a927c2ec-ff76-4713-a4d7-bad5d5d1c05d' 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 class='loading'> <div class='navbar no-items section' id='navbar'> </div> <div class='body-fauxcolumns'> <div class='fauxcolumn-outer body-fauxcolumn-outer'> <div class='cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left'> <div class='fauxborder-right'></div> <div class='fauxcolumn-inner'> </div> </div> <div class='cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> </div> <div class='content'> <div class='content-fauxcolumns'> <div class='fauxcolumn-outer content-fauxcolumn-outer'> <div class='cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left'> <div class='fauxborder-right'></div> <div class='fauxcolumn-inner'> </div> </div> <div class='cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> </div> <div class='content-outer'> <div class='content-cap-top cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left content-fauxborder-left'> <div class='fauxborder-right content-fauxborder-right'></div> <div class='content-inner'> <header> <div class='header-outer'> <div class='header-cap-top cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left header-fauxborder-left'> <div class='fauxborder-right header-fauxborder-right'></div> <div class='region-inner header-inner'> <div class='header section' id='header'><div class='widget Header' data-version='1' id='Header1'> <div id='header-inner' style='background-image: url("https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-4KXwYe0lQ4HFzhAye9vvRlij2ZYvMbfPCnqEE__1o85Fjo3XgefxJQhWRdwR3EzNWNMWT3yMaj2QZaT9GazqQx3C6oWa3-hBNlRHG7f-Oib-lv1Wq_C2_A0rt8xZgs87iNqzRVKK7H0A/s800/background.jpg"); background-position: left; width: 550px; min-height: 105px; _height: 105px; background-repeat: no-repeat; '> <div class='titlewrapper' style='background: transparent'> <h1 class='title' style='background: transparent; border-width: 0px'> <a href='http://www.righto.com/'> Ken Shirriff's blog </a> </h1> </div> <div class='descriptionwrapper'> <p class='description'><span>Computer history, restoring vintage computers, IC reverse engineering, and whatever</span></p> </div> </div> </div></div> </div> </div> <div class='header-cap-bottom cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> </header> <div class='tabs-outer'> <div class='tabs-cap-top cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left tabs-fauxborder-left'> <div class='fauxborder-right tabs-fauxborder-right'></div> <div class='region-inner tabs-inner'> <div class='tabs no-items section' id='crosscol'></div> <div class='tabs no-items section' id='crosscol-overflow'></div> </div> </div> <div class='tabs-cap-bottom cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> <div class='main-outer'> <div class='main-cap-top cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left main-fauxborder-left'> <div class='fauxborder-right main-fauxborder-right'></div> <div class='region-inner main-inner'> <div class='columns fauxcolumns'> <div class='fauxcolumn-outer fauxcolumn-center-outer'> <div class='cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left'> <div class='fauxborder-right'></div> <div class='fauxcolumn-inner'> </div> </div> <div class='cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> <div class='fauxcolumn-outer fauxcolumn-left-outer'> <div class='cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left'> <div class='fauxborder-right'></div> <div class='fauxcolumn-inner'> </div> </div> <div class='cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> <div class='fauxcolumn-outer fauxcolumn-right-outer'> <div class='cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left'> <div class='fauxborder-right'></div> <div class='fauxcolumn-inner'> </div> </div> <div class='cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> <!-- corrects IE6 width calculation --> <div class='columns-inner'> <div class='column-center-outer'> <div class='column-center-inner'> <div class='main section' id='main'><div class='widget Blog' data-version='1' id='Blog1'> <div class='blog-posts hfeed'> <div class="date-outer"> <div class="date-posts"> <div class='post-outer'> <div class='post hentry' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='6264947694886887540' itemprop='blogId'/> <meta content='5052709031128120171' itemprop='postId'/> <a name='5052709031128120171'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='http://www.righto.com/2008/07/rise-of-scripting-languages-and-fall-of.html'>The rise of scripting languages and the fall of Java</a> </h3> <div class='post-header'> <div class='post-header-line-1'></div> </div> <div class='post-body entry-content' id='post-body-5052709031128120171' itemprop='description articleBody'> <p><blockquote> Java is very much in full retreat. <br>-- R. Loui </blockquote> Professor Ronald Loui has an interesting article on the rise of scripting languages (<a href="http://www.cse.wustl.edu/~loui/praiseieee.html">In Praise of Scripting: Real Programming Pragmatism</a>) in the July 2008 issue of IEEE Computer. It claims scripting languages such as Perl, Python, and Javascript have dramatically fulfilled their <a href="http://home.pacbell.net/ouster/scripting.html">early promise</a>, provide many benefits, and are poised to take over the lead from Java. However, the academic programming language community is stuck in theory and hasn't recognized the ascendence of scripting languages. <p> I agree that scripting languages are on the rise. Most people would agree that they provide rapid development, higher levels of abstraction, and brevity that helps the programmer. The article also describes how scripting languages can be a performance win, since they can allow experimentation and implementation of efficient algorithms that would be too painful in Java or C++. So even if C++ is faster on the micro-benchmark level, a programmer using a scripting language may end up with faster algorithms overall. I've argued <a href="http://www.righto.com/2008/05/why-arc-is-bad-for-exploratory.html">somewhat controversally</a> that Arc is too slow for my programming problems, so I remain unconvinced that basic performance can be ignored entirely. <p> As for the claim that Java is in full retreat, it strikes me as wishful thinking. (I'd believe "slow decline" though.) It will be interesting to check back on this claim in 5 years. <blockquote> I personally believe that CS1 [freshman computer science] Java is the greatest single mistake in the history of computing curricula. <br>-- R. Loui </blockquote> The article suggests good languages for teaching introductory computer science are gawk, Javscript, PHP, and ASP, but Python is emerging as a consensus for the best freshman programming language. This is the hardest part of the article for me to swallow. The idea of writing real programs in Awk never occurred to me, and I remain skeptical even though the author claims it works well. For those who would suggest Scheme as an introductory programming language, it was displaced as a dominant freshman language by Java a decade ago, and is apparently no longer considered an option. <p> I can't argue with the author's claim that student learning is enhanced by experimenting, writing code, and getting hands-on experience, and that scripting languages make this faster and easier. <blockquote> Python and Ruby have the enviable properties that almost no one dislikes them, and almost everyone respects them. <br>-- R. Loui </blockquote> In <a href="http://www.righto.com/2008/07/why-your-favorite-language-is-unpopular.html">Why your favorite language is unpopular</a> I discussed how the Change Function model can explain the success of programming languages based on maximizing the crisis solved and minimizing the perceived pain of adoption. I can apply this model applies to scripting languages as well: <p> <b>Magnitude of crisis</b> solved by Tcl/Tk: <b>High</b> - How to add a scripting language to a C program. How to add a GUI to a C program without painful X11 and Motif code. <br><b>Total Perceived Pain of Adoption</b>: <b>Low</b> - Link Tcl in with your C program and add a few hooks. Create the GUI with trivial scripts. <p> <b>Magnitude of crisis</b> solved by Perl: <b>High</b> - How to quickly write CGI scripts. How to solve problems too complex for shell scripts. How to process files. How to develop quickly and iteratively. <br><b>Total Perceived Pain of Adoption</b>: <b>Low</b> - Apart from looking like line noise, Perl is easy to get started with, is well integrated with Unix, has the definitive regex implementation, and has libraries for almost everything. <p> My point is that these languages solved specific painful problems and had low pain of adoption. As a result, they were much more successful than beautiful, powerful languages that were less able to directly solve painful problems or were more painful to adopt. <blockquote> The real reason why academics were blindsided by scripting is their lack of practicality. <br>-- R. Loui </blockquote> A major thrust of the article is that academics are too concerned with theoretical issues of syntax and semantics, rather than pragmatic issues of what a language can achive quickly, inexpensively, and practically. Academics are said to be too tied to theoretical concepts such as object-oriented programming and strong typing, and are missing the real-world benefits of scripting languages. <p> (Interestingly, Rob Pike made a similar argument against academics in the context of operating systems software (<a href="http://herpolhode.com/rob/utah2000.pdf">Systems Software Research is Irrelevant</a>), stating that academic research is irrelevant and the real innovation is in industry. Since I have friends doing academic OS research, I should add a disclaimer here that I don't necessarily agree.) <p> One measure of pragmatics raised by the paper is how well does a language work with other Unix tools. I think the importance of this is underappreciated. In particular, I view this as a significant barrier to adoption of Arc. Running Arc as a shell script instead of a REPL is nontrivial (as is the case with many Lisp and Scheme implementations). Running an external program from Arc is clunky, even though it is often necessary to actually get things done (<a href="http://arclanguage.org/item?id=3522">Kens' law</a>), and <a href="http://www.righto.com/doc/io.html#pipe-from">real pipes</a> are missing from Arc entirely. <p> Java's integration with Unix also has painful gaps - where's <code>getpid()</code> for instance? Why is JNI so difficult compared to calling native code from C#? I blame Sun's pure-Java platform independence ideology, and I'm surprised it hasn't hurt Java more. <p>On the other hand, Python and Perl provide a remarkable degree of integration, which I view as a key factor in their success. Likewise, Visual Basic is highly integrated with the Windows environment and highly successful there. <p> In conclusion, Loui's paper raises numerous interesting points about the success of scripting languages. I expect that the reasons for the rise of scripting languages will only get stronger, and languages that don't support the scripting model will have an increasingly harder time gaining adoption. <p> <font size="-1">Note: quotes above are from the preprint and may not match the published article.</font> <div style='clear: both;'></div> </div> <div class='post-footer'> <div 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/6264947694886887540/5052709031128120171' onclick=''> 4 comments: </a> </span> <span class='post-icons'> <span class='item-action'> <a href='https://www.blogger.com/email-post.g?blogID=6264947694886887540&postID=5052709031128120171' title='Email Post'> <img alt='' class='icon-action' height='13' src='http://img1.blogblog.com/img/icon18_email.gif' width='18'/> </a> </span> <span class='item-control blog-admin pid-1138732533'> <a href='https://www.blogger.com/post-edit.g?blogID=6264947694886887540&postID=5052709031128120171&from=pencil' title='Edit Post'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> <span class='post-backlinks post-comment-link'> </span> <div class='post-share-buttons goog-inline-block'> <a class='goog-inline-block share-button sb-email' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=5052709031128120171&target=email' target='_blank' title='Email This'><span class='share-button-link-text'>Email This</span></a><a class='goog-inline-block share-button sb-blog' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=5052709031128120171&target=blog' onclick='window.open(this.href, "_blank", "height=270,width=475"); return false;' target='_blank' title='BlogThis!'><span class='share-button-link-text'>BlogThis!</span></a><a class='goog-inline-block share-button sb-twitter' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=5052709031128120171&target=twitter' target='_blank' title='Share to X'><span class='share-button-link-text'>Share to X</span></a><a class='goog-inline-block share-button sb-facebook' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=5052709031128120171&target=facebook' onclick='window.open(this.href, "_blank", "height=430,width=640"); return false;' target='_blank' title='Share to Facebook'><span class='share-button-link-text'>Share to Facebook</span></a><a class='goog-inline-block share-button sb-pinterest' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=5052709031128120171&target=pinterest' target='_blank' title='Share to Pinterest'><span class='share-button-link-text'>Share to Pinterest</span></a> </div> </div> <div class='post-footer-line post-footer-line-2'><span class='post-labels'> Labels: <a href='http://www.righto.com/search/label/java' rel='tag'>java</a>, <a href='http://www.righto.com/search/label/random' rel='tag'>random</a>, <a href='http://www.righto.com/search/label/snark' rel='tag'>snark</a> </span> </div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> </div></div> <div class="date-outer"> <div class="date-posts"> <div class='post-outer'> <div class='post hentry' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='http://static.righto.com/images/geek.png' itemprop='image_url'/> <meta content='6264947694886887540' itemprop='blogId'/> <meta content='2699423316012690302' itemprop='postId'/> <a name='2699423316012690302'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='http://www.righto.com/2008/07/why-your-favorite-language-is-unpopular.html'>Why your favorite language is unpopular</a> </h3> <div class='post-header'> <div class='post-header-line-1'></div> </div> <div class='post-body entry-content' id='post-body-2699423316012690302' itemprop='description articleBody'> <blockquote> The total world's population of Haskell programmers fits in a 747. And if that goes down, nobody would even notice. <br>-- Erik Meijer </blockquote> <p> I recently saw an interesting talk on functional programming by <a href="https://en.wikipedia.org/wiki/Erik_Meijer_%28computer_scientist%29">Erik Meijer</a> (of <a href="http://www.reddit.com/r/programming/comments/6q591/A_Classic_Functional_Programming_with_Bananas">Bananas, Lenses, Envelopes, and Barbed Wire</a> fame). Among other things, he discussed why many superior technologies such as Haskell don't catch on. <h3>Geek formula for success</h3> He claims the "Geek formula" for success of a technology is that if a technology is 10 times better, it should catch on and become popular. Even if it is slower, Moore's law will soon make it 10 times faster. <p> <img alt="" src="http://static.righto.com/images/geek.png"> <p> So if Haskell is 10 times better than C and Haskell programs are 10 times shorter, everybody should be using Haskell. <h3>Real-life formula for success</h3> However, as Erik points out, "That's not how it is in real life." In real life, success is based on the perceived crisis divided by the perceived pain of adoption. Users want something that will get the job done and solve their crisis, without a lot of pain to switch. <p> <img alt="" src="http://static.righto.com/images/real.png"> <br> This argument applies to many languages that remain unpopular despite their technical merits, such as Lisp, Arc, and Erlang, as well as technologies such as the Semantic Web and LaTex. <iframe src="http://rcm.amazon.com/e/cm?t=rightocom&o=1&p=8&l=as1&asins=B000NA6U2O&fc1=000000&IS2=1<1=_blank&lc1=0000FF&bc1=000000&bg1=FFFFFF&f=ifr" style="width:120px;height:240px; float: right;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0" scrolling="no"></iframe> <h3><i>The Change Function</i></h3> The above argument is based on the book <i>The Change Function: Why Some Technologies Take Off and Others Crash and Burn</i> by Pip Coburn. To summarize the book, new technologies aren't adopted because they are great, new, and disruptive; they are adopted only if the user's crisis solved by the technology is greater than the perceived pain of adoption. As a result, most new technologies fail. <p> The first half of the book is a bit fluffy, but gets more interesting when it discusses specific technologies that failed or succeeded. The book also goes out on a limb and predicts future winners (mobile enterprise Email, satellite radio, business intelligence software) and losers (RFID, entertainment PC, WiMax). <h3>Languages and <i>The Change Function</i></h3> <i>The Change Function</i> argument has a lot of merit for explaining what languages become popular and what languages don't. If Lisp is so great, why are there <a href="http://www.windowsdevcenter.com/pub/a/oreilly/windows/news/gateskeynote_0601.html">8 million Visual Basic programmers worldwide</a> and few Lisp programmers? The answer isn't <a href="http://www.paulgraham.com/avg.html">pointy-haired bosses</a> (since Lisp isn't <a href="http://c2.com/cgi/wiki?ProgrammingLanguagePopularity">popular on SourceForge</a> either). The crisis vs. pain of adoption model provides a powerful explanation: <p> <b>Magnitude of crisis</b> solved by Visual Basic: <b>High</b> (e.g. how to easily write Windows applications) <br><b>Total Perceived Pain of Adoption</b> for Visual Basic: <b>Very Low</b> (hit Alt-F11 in Excel and you're done) <p> <b>Magnitude of crisis</b> solved by Lisp: <b>Low</b> (metaprogramming, powerful macros, and higher-order functions are solutions in search of problems) <br><b>Total Perceived Pain of Adoption</b> for Lisp: <b>High</b> (this shouldn't require explanation) <p> The same model explains the success of, for instance, Java: <br><b>Magnitude of crisis</b> solved by Java: <b>High</b> (originally how to run code in a browser and write portable code, now how to avoid crashes due to memory allocation errors and bad pointers) <br><b>Total Perceived Pain of Adoption</b>: <b>Low</b> (syntax similar to C++, easy to deploy) <p> Applying this model to other languages is left as an exercise for the reader. <p> <iframe src="http://rcm.amazon.com/e/cm?t=rightocom&o=1&p=8&l=as1&asins=193435600X&fc1=000000&IS1=1<1=_blank&lc1=0000FF&bc1=000000&bg1=FFFFFF&f=ifr" style="width:120px;height:240px; float: right;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe> Erik points out that Erlang and Haskell are now being marketed according to the second formula: there is a <a href="http://www.reddit.com/search?q=multicore+crisis&x=0&y=0">multicore crisis</a> and functional languages are <a href="http://www.reddit.com/search?q=haskell+multicore&x=0&y=0">the solution</a>. It will be interesting to see how much additional traction these languages get without addressing the "pain of adoption" part. <h3><i>The Change Function</i> and startups</h3> <i>The Change Function</i> ends with ten sets of questions and a set of techniques for designing technologies that will be adopted; this part of the book has many ideas that would be beneficial for startups. Many of these are fairly obvious, such as "Fail fast and iterate", and have a customer-centered culture instead of a sales-centered culture, while others are more thought-provoking: "What is the user crisis you intend to solve? What are the top five reasons a user with this crisis would not use your product?" The ultimate conclusion of the book is "Figure out what people <i>really</i> want!", which brings to mind the advice to <a href="http://www.paulgraham.com/good.html">make something people want</a>. <div style='clear: both;'></div> </div> <div class='post-footer'> <div 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/6264947694886887540/2699423316012690302' onclick=''> 22 comments: </a> </span> <span class='post-icons'> <span class='item-action'> <a href='https://www.blogger.com/email-post.g?blogID=6264947694886887540&postID=2699423316012690302' title='Email Post'> <img alt='' class='icon-action' height='13' src='http://img1.blogblog.com/img/icon18_email.gif' width='18'/> </a> </span> <span class='item-control blog-admin pid-1138732533'> <a href='https://www.blogger.com/post-edit.g?blogID=6264947694886887540&postID=2699423316012690302&from=pencil' title='Edit Post'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> <span class='post-backlinks post-comment-link'> </span> <div class='post-share-buttons goog-inline-block'> <a class='goog-inline-block share-button sb-email' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=2699423316012690302&target=email' target='_blank' title='Email This'><span class='share-button-link-text'>Email This</span></a><a class='goog-inline-block share-button sb-blog' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=2699423316012690302&target=blog' onclick='window.open(this.href, "_blank", "height=270,width=475"); return false;' target='_blank' title='BlogThis!'><span class='share-button-link-text'>BlogThis!</span></a><a class='goog-inline-block share-button sb-twitter' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=2699423316012690302&target=twitter' target='_blank' title='Share to X'><span class='share-button-link-text'>Share to X</span></a><a class='goog-inline-block share-button sb-facebook' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=2699423316012690302&target=facebook' onclick='window.open(this.href, "_blank", "height=430,width=640"); return false;' target='_blank' title='Share to Facebook'><span class='share-button-link-text'>Share to Facebook</span></a><a class='goog-inline-block share-button sb-pinterest' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=2699423316012690302&target=pinterest' target='_blank' title='Share to Pinterest'><span class='share-button-link-text'>Share to Pinterest</span></a> </div> </div> <div class='post-footer-line post-footer-line-2'><span class='post-labels'> Labels: <a href='http://www.righto.com/search/label/arc' rel='tag'>arc</a>, <a href='http://www.righto.com/search/label/haskell' rel='tag'>haskell</a>, <a href='http://www.righto.com/search/label/random' rel='tag'>random</a>, <a href='http://www.righto.com/search/label/snark' rel='tag'>snark</a> </span> </div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> </div></div> <div class="date-outer"> <div class="date-posts"> <div class='post-outer'> <div class='post hentry' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='6264947694886887540' itemprop='blogId'/> <meta content='2219572455219389220' itemprop='postId'/> <a name='2219572455219389220'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='http://www.righto.com/2008/07/maxwells-equations-of-software-examined.html'>"Maxwell's equations of software" examined</a> </h3> <div class='post-header'> <div class='post-header-line-1'></div> </div> <div class='post-body entry-content' id='post-body-2219572455219389220' itemprop='description articleBody'> A <a href="http://bc.tech.coop/blog/060224.html">recent post</a> quotes Alan Kay's <a href="http://www.doc.ic.ac.uk/~sue/475/AlanKay.html">statement</a> that expressing Lisp in itself is the "<a href="https://en.wikipedia.org/wiki/Maxwell's_equations#General_formulations_of_Maxwell.27s_equations">Maxwell's Equations of Software</a>": <p> <blockquote>Yes, that was the big revelation to me when I was in graduate school—when I finally understood that the half page of code on the bottom of page 13 of the Lisp 1.5 manual was Lisp in itself. These were “Maxwell’s Equations of Software!” </blockquote> <p> This quote appears many places on the web, but the code itself is harder to find. What <i>is</i> this amazing half page of code? <p> The Lisp 1.5 Manual, which was written by John McCarthy et al in 1961, is available at <a href="http://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf">softwarepreservation.org</a>. In it, the "Maxwell's equations" define a universal Lisp function <code>evalquote</code> that can evaluate any given function: <pre> evalquote[fn;x] = apply[fn;x;NIL] </pre> where <pre> apply[fn;x;a] = [atom[fn] -> [eq[fn;CAR] -> caar[x]; eq[fn;CDR] -> cdar[x]; eq[fn;CONS] -> cons[car[x];cadr[x]]; eq[fn;ATOM] -> atom[car[x]]; eq[fn;EQ] -> eq[car[x];cadr[x]]; T -> apply[eval[fn;a];x;a]]; eq[car[fn];LAMBDA] -> eval[caddr[fn];pairlis[cadr[fn];x;a]]; eq[car[fn];LABEL] -> apply[caddr[fn];x;cons[cons[cadr[fn]; caddr[fn]];a]]] eval[e;a] = [atom[e] -> cdr[assoc[e;a]]; atom[car[e]] -> [eq[car[e],QUOTE] -> cadr[e]; eq[car[e];COND] -> evcon[cdr[e];a]; T -> apply[car[e];evlis[cdr[e];a];a]]; T -> apply[car[e];evlis[cdr[e];a];a]] evcon[c;a] = [eval[caar[c];a] -> eval[cadar[c];a]; T -> evcon[cdr[c];a]] evlis[m;a] = [null[m] -> NIL; T -> cons[eval[car[m];a];evlis[cdr[m];a]]] </pre> <p> The above code is defined in a meta-language (M-expressions), which can be straighforwardly translated into S-expressions. Functions in M-expressions use square brackets and have arguments separated by semicolons. M-expressions conditionals are of the form <code>[predicate -> value; predicate -> value; ...]</code>. M-expression <code>label</code> is analogous to <code>defun</code> or <code>define</code>. <p> The point of all this is that M-expressions are the code that operates on the S-expression data, but the M-expression meta-language and S-expression data actually coincide. Thus, code and data are the same thing in Lisp, and a half-page of code is sufficient to define a basic Lisp interpreter in Lisp given a few primitives (<code>car, cdr, cons, eq, atom</code>). The code presents a <a href="https://en.wikipedia.org/wiki/Meta-circular_evaluator">Meta-circular evaluator</a> for Lisp; see (<a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-26.html">SICP chapter 4.1</a> for more details on metacircular evaluators. (Unfortunately, this won't give you a working Lisp interpreter for free; things such as the garbage collector, the list primitives, and parsing need to be implemented somewhere. Also note that this metacircular evaluator doesn't give you niceties such as arithmetic.)) <p> To understand the above code, <code>apply</code> takes a function and argument, while <code>eval</code> acts on a form. The last argument to these is an association list for the environment, which stores the values of bound values and function names. In brief, <code>apply</code> implements <code>CAR</code>, <code>CDR</code>, <code>CONS</code>, <code>ATOM</code>, and <code>EQ</code> in terms of the primitives. It implements <code>LAMBDA</code> by pairing up the variables and arguments and passing them to <code>eval</code>. It implements <code>LABEL</code> (which defines a function) by adding the function name and definition to the association list. <p> The code for <code>eval</code> processes a form in a straightforward manner. It handles the <code>QUOTE</code> form by returning the quoted value. It handles <code>COND</code> by evaluating the predicates with the help of <code>evcon</code>. Otherwise, it interprets an atom as a variable and returns the value. If given a list, it interprets this as a function application; the arguments are evaluated with <code>evalis</code> and the function is evaluated by <code>apply</code>. <p> The above code is not quite complete; it relies on some other simple functions that were previously defined in the manual, such as <code>equals</code> and <code>cadr</code> Less obvious functions are <code>pairlis[x;y;a]</code> pairs up lists <code>x</code> and <code>y</code> and adds them to association list <code>a</code>. <code>assoc[x;a]</code> looks up <code>x</code> in association list <code>a</code>. <code>sublis[a;y]</code> treats association list <code>a</code> as a mapping of variables to values, and replaces variables in S-expression <code>y</code> with the associated variables. These functions can be straightforwardly built from the primitive functions. <p> (By the way, I'm pretty sure the comma in <code>eq[car[e],QUOTE]</code> is a typo, but that's how it is in the original.) <div style='clear: both;'></div> </div> <div class='post-footer'> <div 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/6264947694886887540/2219572455219389220' onclick=''> 4 comments: </a> </span> <span class='post-icons'> <span class='item-action'> <a href='https://www.blogger.com/email-post.g?blogID=6264947694886887540&postID=2219572455219389220' title='Email Post'> <img alt='' class='icon-action' height='13' src='http://img1.blogblog.com/img/icon18_email.gif' width='18'/> </a> </span> <span class='item-control blog-admin pid-1138732533'> <a href='https://www.blogger.com/post-edit.g?blogID=6264947694886887540&postID=2219572455219389220&from=pencil' title='Edit Post'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> <span class='post-backlinks post-comment-link'> </span> <div class='post-share-buttons goog-inline-block'> <a class='goog-inline-block share-button sb-email' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=2219572455219389220&target=email' target='_blank' title='Email This'><span class='share-button-link-text'>Email This</span></a><a class='goog-inline-block share-button sb-blog' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=2219572455219389220&target=blog' onclick='window.open(this.href, "_blank", "height=270,width=475"); return false;' target='_blank' title='BlogThis!'><span class='share-button-link-text'>BlogThis!</span></a><a class='goog-inline-block share-button sb-twitter' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=2219572455219389220&target=twitter' target='_blank' title='Share to X'><span class='share-button-link-text'>Share to X</span></a><a class='goog-inline-block share-button sb-facebook' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=2219572455219389220&target=facebook' onclick='window.open(this.href, "_blank", "height=430,width=640"); return false;' target='_blank' title='Share to Facebook'><span class='share-button-link-text'>Share to Facebook</span></a><a class='goog-inline-block share-button sb-pinterest' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=2219572455219389220&target=pinterest' target='_blank' title='Share to Pinterest'><span class='share-button-link-text'>Share to Pinterest</span></a> </div> </div> <div class='post-footer-line post-footer-line-2'><span class='post-labels'> Labels: <a href='http://www.righto.com/search/label/random' rel='tag'>random</a> </span> </div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> </div></div> <div class="date-outer"> <div class="date-posts"> <div class='post-outer'> <div class='post hentry' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='http://static.righto.com/images/tet.gif' itemprop='image_url'/> <meta content='6264947694886887540' itemprop='blogId'/> <meta content='202242580147372508' itemprop='postId'/> <a name='202242580147372508'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='http://www.righto.com/2008/06/why-arc-is-good-for-video-games.html'>Why Arc is good for video games</a> </h3> <div class='post-header'> <div class='post-header-line-1'></div> </div> <div class='post-body entry-content' id='post-body-202242580147372508' itemprop='description articleBody'> Can Arc be used to create a Tetris-like game? In my previous posting on <a href="http://www.righto.com/2008/05/using-opengl-with-arc.html">using OpenGL with Arc</a>, I described how the effort to set up OpenGL had stalled my game-writing adventure. I finally got the game written, only to discover that Conan Dalton had beat me by writing <a href="http://arclanguage.org/item?id=7063">Arc Tetris</a> running on <a href="http://www.righto.com/2008/04/many-arc-compilers-and-interpreters.html">Rainbow</a>, his version of Arc running on Java. Nonetheless, here's my implementation in Arc using OpenGL. <p> <img alt="screenshot of game" src="http://static.righto.com/images/tet.gif"> <br> <h3>Playing the game</h3> See <a href="http://www.righto.com/2008/05/using-opengl-with-arc.html">using OpenGL with Arc</a> for details on setting up OpenGL. To summarize, the files are in the opengl directory of the <a href="http://www.righto.com/2008/02/git-and-anarki-arc-repository-brief.html">Anarki git</a>. Run <code>gl-arc.scm</code> in DrScheme. Then load "tet.arc" into the Arc REPL, and the game will start. <p> To control the game, use the arrow keys. Left and right arrows move the tile. Up-arrow rotates the tile, and down-arrow drops it faster. When the game ends, "s" will start a new game. <h3>Implementing games in Arc</h3> <iframe src="http://rcm.amazon.com/e/cm?t=rightocom&o=1&p=8&l=as1&asins=1592003699&fc1=000000&IS2=1&lt1=_blank&lc1=0000FF&bc1=000000&bg1=FFFFFF&f=ifr&npa=1" style="width: 120px; height: 240px; float: right;" marginwidth="0" marginheight="0" frameborder="0" scrolling="no"></iframe> Note that Arc itself doesn't have any graphics support, or any way to get at Scheme libraries. I hacked on Arc's implementation in Scheme to get access to the OpenGL libraries in PLT Scheme. <p> My first concern with using Arc was speed. It turns out that Arc on a newish laptop is plenty fast to run the game, apart from occasional garbage collection glitches. The game itself doesn't require a fast refresh rate, and the amount of processing per frame is pretty small, so Arc manages just fine. <p> The biggest problem with implementing the game in Arc was the lack of useful error reporting in Arc; I should have emphasized this in <a href="http://www.righto.com/2008/05/why-arc-is-bad-for-exploratory.html">Why Arc is bad for exploratory programming</a>. Every time I wrote more than a few lines at a time, I'd encounter a mystery error such as "ac.scm::18267: car: expects argument of type <pair>; given 1" or "ac.scm::17324: Function call on inappropriate object 2 ()". I often had to stick print statements throughout the code, just to figure out where the error was happening. Reporting what is the error and where an error occurs is basic functionality that a programming language implementation should provide. An actual debugger would be a bonus. <p> I found that game programming doesn't really let you take advantage of the REPL for development. OpenGL is very stateful, so I can't just call a drawing routine from the REPL to see how it's working. I usually had to restart my code, and often reload the Arc interpreter itself to clear up the various Scheme objects. When I worked incrementally, I often ended up with startup issues when I ran from the start (i.e. variables getting initialized in the wrong order). <p> One annoyance is Arc's lack of arrays. I used tables in some places, and lists of lists in other places, but vectors and arrays seem like really basic datatypes. <p> Another annoyance is OpenGL's lack of any text support. If you're wondering about the lack of text in the screenshot, that's why. I implemented a simple 7-segment number-drawing function to display the score. <p> Some (pretty obvious in retrospect) advice to other game writers: Figure out in advance if the Y axis points up or down. I wrote some of the code assuming Y increases going down before realizing that other parts of the code expected the Y axis to point up. Also, figuring out the origin and scale in advance is a good thing. <p> Another tricky part of game implementation is state transitions. Both startup and end-of-game caused me more difficulty than I expected. <p> Implementing the game became much more rewarding once I got a minimal interactive display working. I should have done that sooner, rather than implementing the algorithms up front. On the other hand, I found it useful to disable animation much of the time, using keypresses to single-step movement. <iframe src="http://rcm.amazon.com/e/cm?t=rightocom&o=1&p=8&l=as1&asins=1556220782&fc1=000000&IS2=1&lt1=_blank&lc1=0000FF&bc1=000000&bg1=FFFFFF&f=ifr&npa=1" style="width: 120px; height: 240px; float: right;" marginwidth="0" marginheight="0" frameborder="0" scrolling="no"></iframe> <p> The game has no audio, since PLT Scheme doesn't have audio support. <p> It took me a long time to realize that the pieces in Tetris don't actually rotate around a fixed point. Once I realized this and hard-coded the rotations instead of implementing a rotation function, things became easier. <p> I display the piece in motion separately from the playing field array that holds the stationary pieces. When a line is completed, instead of updating the playing field array in place, I decided it would be interesting to write <code>remove-rows</code> in a functional way so it returns an entirely new playing field array, rather than updating the existing array (as I did in <code>saveshape</code> when a piece hits bottom). Writing the whole game in a functional style would be very difficult, as <a href="http://prog21.dadgum.com/3.html">others have described</a>. <p> I could make the code more "Arcish" with various macros (e.g. <code>w/matrix</code> to wrap code in <code>gl-push-matrix</code> and <code>gl-pop-matrix</code>). But I decided to "ship early". Likewise I didn't bother implementing game levels, although the game does speed up as it progreses. And I've only made minimal efforts to clean up the code, so I'm not presenting it as a model of good style. <h3>Conclusion</h3> It's possible to write a playable game in Arc (with enough hacking on the language to get OpenGL support). I think it would have been considerably easier to write it in PLT Scheme directly, but the Arc implementation builds character. I was pleasantly surprised that Arc had enough speed to run the game. The Arc code works out to 389 lines for those keeping score; OpenGL is responsible for much of the length (50 lines just to display the score). I expect writing in Arc will be considerably easier if the language gets decent error reporting. <div style='clear: both;'></div> </div> <div class='post-footer'> <div 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/6264947694886887540/202242580147372508' onclick=''> No comments: </a> </span> <span class='post-icons'> <span class='item-action'> <a href='https://www.blogger.com/email-post.g?blogID=6264947694886887540&postID=202242580147372508' title='Email Post'> <img alt='' class='icon-action' height='13' src='http://img1.blogblog.com/img/icon18_email.gif' width='18'/> </a> </span> <span class='item-control blog-admin pid-1138732533'> <a href='https://www.blogger.com/post-edit.g?blogID=6264947694886887540&postID=202242580147372508&from=pencil' title='Edit Post'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> <span class='post-backlinks post-comment-link'> </span> <div class='post-share-buttons goog-inline-block'> <a class='goog-inline-block share-button sb-email' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=202242580147372508&target=email' target='_blank' title='Email This'><span class='share-button-link-text'>Email This</span></a><a class='goog-inline-block share-button sb-blog' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=202242580147372508&target=blog' onclick='window.open(this.href, "_blank", "height=270,width=475"); return false;' target='_blank' title='BlogThis!'><span class='share-button-link-text'>BlogThis!</span></a><a class='goog-inline-block share-button sb-twitter' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=202242580147372508&target=twitter' target='_blank' title='Share to X'><span class='share-button-link-text'>Share to X</span></a><a class='goog-inline-block share-button sb-facebook' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=202242580147372508&target=facebook' onclick='window.open(this.href, "_blank", "height=430,width=640"); return false;' target='_blank' title='Share to Facebook'><span class='share-button-link-text'>Share to Facebook</span></a><a class='goog-inline-block share-button sb-pinterest' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=202242580147372508&target=pinterest' target='_blank' title='Share to Pinterest'><span class='share-button-link-text'>Share to Pinterest</span></a> </div> </div> <div class='post-footer-line post-footer-line-2'><span class='post-labels'> Labels: <a href='http://www.righto.com/search/label/arc' rel='tag'>arc</a> </span> </div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> </div></div> <div class="date-outer"> <div class="date-posts"> <div class='post-outer'> <div class='post hentry' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='http://static.righto.com/images/gears-anim.gif' itemprop='image_url'/> <meta content='6264947694886887540' itemprop='blogId'/> <meta content='8566439659177835317' itemprop='postId'/> <a name='8566439659177835317'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='http://www.righto.com/2008/05/using-opengl-with-arc.html'>Using OpenGL with Arc</a> </h3> <div class='post-header'> <div class='post-header-line-1'></div> </div> <div class='post-body entry-content' id='post-body-8566439659177835317' itemprop='description articleBody'> <script language="javascript"> function toggle(img, button, img1, img2) { if (document.getElementById(button).value == "Start animation") { document.getElementById(button).value = "Stop animation"; document.getElementById(img).src = img2; } else { document.getElementById(button).value = "Start animation"; document.getElementById(img).src = img1; } } </script> I saw a posting on news.ycombinator entitled "<a href="http://news.ycombinator.com/item?id=171796">Take the Tetris test (an Arc version, anyone?)</a>", which suggested writing a simple Tetris-like game. One obvious problem with doing this in Arc is the lack of graphics support. But how hard could it be to use OpenGL graphics from Arc? <p> It turns out that using OpenGL from Arc is harder than I expected, but possible, given enough hacking on Arc's underlying Scheme implementation. In this article, I discuss how I got OpenGL to work. <p> <iframe src="http://rcm.amazon.com/e/cm?t=rightocom&o=1&p=8&l=as1&asins=0321481003&fc1=000000&IS2=1&lt1=_blank&lc1=0000FF&bc1=000000&bg1=FFFFFF&f=ifr&npa=1" style="width: 120px; height: 240px; float: right;" marginwidth="0" marginheight="0" frameborder="0" scrolling="no"></iframe> <img height="337" id="gearsi" onclick="alert('This is just a GIF, not the real program. The buttons do not do anything.')" src="http://static.righto.com/images/gears-anim.gif" width="249" /> <input id="gearsb" onclick="toggle('gearsi', 'gearsb', '/images/gears-frame.gif', '/images/gears-anim.gif');" value="Stop animation" type="button"> </p><h3>Challenge 1: How to access libraries from Arc</h3> The first challenge is that the official Arc release does not let you access Scheme libraries or functions. Not at all. Even though Arc is <a href="http://www.righto.com/2008/02/arc-internals-part-1.html">implemented on top of MzScheme</a>, there is no mechanism to access the underlying MzScheme implementation. If you want to access Scheme, you must actually modify the Arc language implementation by hacking on the Scheme code that implements Arc. <p> The unofficial <a href="http://www.righto.com/2008/02/git-and-anarki-arc-repository-brief.html">Anarki implementation</a> is a modified version of Arc that provides access to Scheme (as well as many other useful improvements). However, I decided to base my OpenGL project on the offical Arc implementation rather than Anarki. </p><p> I replaced the Arc implementation file <code>ac.scm</code> with a modified version called <code>arc-gl.scm</code> that gives me access to the necessary Scheme functions. The relevant Scheme code is: </p><pre class="code"> (require (lib "mred.ss" "mred") (lib "class.ss") (lib "math.ss") (prefix gl- (lib "sgl.ss" "sgl")) (lib "gl-vectors.ss" "sgl")) ; List of functions to export from Scheme to Arc (map (lambda (s) (xdef s (eval s))) '(gl-shade-model gl-normal gl-begin gl-end gl-vertex gl-clear-color gl-clear gl-push-matrix gl-pop-matrix gl-rotate gl-translate gl-call-list gl-flush gl-light-v gl-enable gl-new-list gl-gen-lists gl-material-v gl-viewport gl-matrix-mode gl-load-identity gl-frustum gl-light-v gl-enable gl-end-list gl-scale sin cos)) ; Arc doesn't provide access to vector, so make gl-float-vector ; take individual arguments instead of a vector (xdef 'gl-float-vector (lambda (a b c d) (vector->gl-float-vector (vector a b c d)))) </pre> First, the code imports the necessary libraries. Next, it uses <code>xdef</code> to allow access to the list of specified Scheme functions. I included the OpenGL functions I used; you will need to extend this list if you want additional OpenGL functionality. I also include <code>sin</code> and <code>cos</code>; they are missing from Arc, which is <a href="http://www.paulgraham.com/arcll1.html">almost pervesely inconvenient</a>. <p> To get my code: </p><ul> <li>Download <a href="http://static.righto.com/files/ar-gl.zip">arc-gl.zip</a>. </li></ul> This contains <code>arc-gl.scm</code>, the updated Scheme code; <code>arch.arc</code>, the arch demo in Arc; and <code>gears.arc</code>, the gears demo in Arc. It is also available from the <a href="http://www.righto.com/2008/02/git-and-anarki-arc-repository-brief.html">Anarki git</a>. <h3>Challenge 2: Where is OpenGL?</h3> OpenGL isn't part of the plain vanilla MzScheme that is recommended for Arc, but it is part of DrScheme. Both DrScheme and MzScheme are versions of Scheme under the PLT Scheme umbrella; MzScheme is the lightweight version, while DrScheme is the graphical version that includes MrEd graphics toolbox and the <a href="http://www.cs.utah.edu/%7Esowens/sgl.html">OpenGL bindings for Scheme</a>. Thus: <ul> <li> Download and install <a href="http://download.plt-scheme.org/drscheme/all-versions.html">DrScheme</a> version 352. </li></ul> <p> An alternative to OpenGL would be using MrEd's 2-d graphics; I've described before <a href="http://arclanguage.org/item?id=1616">how to add simple graphics to Arc</a>. However, I wanted to use the opportunity to learn more about OpenGL. </p><h3>Challenge 3: Running an Arc REPL in PLT Scheme</h3> It's <a href="http://arclanguage.org/item?id=1609">straightforward</a> to run <code>as.scm</code> inside PLT Scheme and get an Arc REPL. However, a problem immediately turns up with OpenGL <p> An OpenGL animation will lock up as soon as the Arc REPL is waiting for input. The problem is that MrEd is built around an <a href="https://en.wikipedia.org/wiki/Event_loop">event loop</a>, which needs to keep running (similar to the Windows message loop). When the REPL blocks on a read call, the entire system blocks. </p><p> The solution is to implement a new GUI-based Arc REPL instead of the read-based REPL. MrEd provides text fields that can be used to provide non-blocking input. When the input is submitted, the event loop executes a callback, which can then run the Arc code. Of course, the Arc code needs to return reasonably promptly, or else things will be locked up again. However, the Arc code can start a new thread if it needs to do a long-running computation. </p><p> The following MzScheme code creates a frame, text-field for output, text-field for input, and a submit button, and executes the submitted code through <code>arc-eval</code>. It is analogous to the REPL code in <code>ac.scm</code>. I put this code in <code>arc-gl.scm</code>. </p><pre class="code"> (define frame (instantiate frame% ("Arc REPL"))) (send frame show #t) (define (cb-submit a b) (on-err (lambda (c) (append-tf (exn-message c))) (lambda () (append-tf (send in-field get-value)) (append-tf (format "~a" (ac-denil (arc-eval (read (open-input-string (send in-field get-value))))))) (send in-field set-value "")))) (define tf (instantiate text-field% ("" frame) (style '(multiple)) (min-width 600) (min-height 150) (enabled #f))) (define (append-tf str) (send tf set-value (string-append (send tf get-value) str "\n"))) (define in-field (instantiate text-field% ("" frame) (style '(single)) )) (define bb (instantiate button% ("submit" frame) (style '(border)) (callback cb-submit))) </pre> To start up Arc with the new REPL: <ul> <li>Load the new REPL code into the same directory as the original Arc files. </li><li>Run <code>drscheme</code>. </li><li>Go to Language -> Choose Language -> PLT -> Graphical. Click Ok. </li><li>Go to File -> Open -> arc-gl.scm </li><li>Click Run </li></ul> As you can see from the screenshot, the REPL doesn't get any points for style, but it gets the job done. <br> <img height="151" src="http://static.righto.com/images/repl-screenshot.gif" width="224" /> <h3>Challenge 4: Using Scheme's object model</h3> <iframe src="http://rcm.amazon.com/e/cm?t=rightocom&o=1&p=8&l=as1&asins=1571691642&fc1=000000&IS2=1&lt1=_blank&lc1=0000FF&bc1=000000&bg1=FFFFFF&f=ifr&npa=1" style="width: 120px; height: 240px; float: right;" marginwidth="0" marginheight="0" frameborder="0" scrolling="no"></iframe> The mechanism above can't be used to access PLT Scheme's windowing operations, because they are heavily based on the Scheme object implementation, which is implemented through complex Scheme macros. Thus, I can't simply map the windowing operations into Arc, as I did with <code>sin</code>. If the operations are called directly, they will try to apply Scheme macros to Arc code, which won't work. If they're called after Arc evaluation, the Arc implementation will have already tried to evaluate the Scheme macros as Arc code, which won't work either. <p> I tried several methods of welding the Scheme objects into Arc, none of which are entirely satisfactory. The first approach was to encapsulate everything in Scheme and provide simple non-object-based methods that can be called from Arc. For example, an Arc function <code>make-window</code> could be implemented by executing the necessary Scheme code. This works for simple operations, and is the approach I used for simple 2-d graphics, but the encapsulation breaks when the code gets more complex, for example with callbacks and method invocations. It is also unsatisfying because most of the interesting code is written in Scheme, not Arc. </p><p> Another approach would be to fully implement Scheme's object model in Arc, so everything could be written in Arc. That was way more difficulty and work than I wanted to do, especially since the object system is implemented in very complex Scheme macros. </p><p> My next approach was to implement an <code>exec-scheme</code> function that allows chunks of Scheme code to be called directly from inside Arc. This worked, but was pretty hacky. </p><p> Minor semantic differences between Arc and Scheme add more ugliness. Arc converts <code>#f</code> to <code>nil</code>, which doesn't work for Scheme code that is expecting <code>#f</code>. I hacked around this by adding a symbol <code>false</code> that gets converted to <code>#f</code>. Another problem is Arc lists get <code>nil</code> added at the end; so the lists must be converted going to and from Scheme. </p><p> Finally, I ended up with a somewhat hybrid approach. On top of <code>eval-scheme</code>, I implemented Arc macros to wrap the object operations of <code>send</code> and <code>invoke</code>. These macros try to do Arc compilation on the Arc things, and leave the Scheme things untouched. Even so, it's still kind of an ugly mix of Scheme and Arc with lots of quoting. I found writing these macros surprisingly difficult, mixing evaluated and unevaluated stuff. </p><p> As an aside, Scheme's object framework uses <code>send foo bar baz</code> to invoke <code>bar</code> on object <code>foo</code> with argument <code>baz</code>. I.e. <code>foo.bar(baz)</code> in Java. I found it interesting that this semantic difference made me think about object-oriented programming differently: Scheme objects are getting sent a message, doing something with the message, and providing a reply. Of course, this is the same as invoking a method, but it feels more "distant" somehow. </p><p> At the end of this, I ended up with a moderately ugly way of creating Scheme objects from Arc, providing callbacks to Arc functions, and implementing <code>instantiate</code> and <code>send</code> in Arc. This isn't a full object implementation, but it was enough to get the job done. For example, to instantiate the MrEd <code>frame%</code> class and assign it to an Arc variable: </p><pre class="arc"> (= frame (instantiate 'frame% '("OpenGL Demo" 'false))) </pre> A function to send a refresh message to the canvas: <pre class="arc"> (def refresh () (send arc-canvas refresh)) </pre> Defining a subclass of <code>canvas%</code> to display the image is uglier as it is Arc code that's mostly in Scheme, but using the Arc callbacks: <pre class="arc"> (eval-scheme `(define arc-canvas% (class* canvas% () (inherit refresh with-gl-context swap-gl-buffers get-parent) (define/public (run) (,ex-run)) (define/override (on-size width height) (with-gl-context (lambda () (,ex-on-size width height)))) (define/override (on-paint) (with-gl-context ,ex-on-paint)) (super-instantiate () (style '(gl no-autoclear)))))) </pre> <h3>Finally doing something with OpenGL in Arc</h3> Here's a simple example of an animated arch displayed in OpenGL. To run this example, download the code and start up DrScheme as described above. Then: <ul><li>From the Arc REPL (not the Scheme REPL) execute: <pre class="arc"> (load "arch.arc") (motion) </pre> </li></ul> <br> <iframe src="http://rcm.amazon.com/e/cm?t=rightocom&o=1&p=8&l=as1&asins=0201848406&fc1=000000&IS2=1&lt1=_blank&lc1=0000FF&bc1=000000&bg1=FFFFFF&f=ifr&npa=1" style="width: 120px; height: 240px; float: right;" marginwidth="0" marginheight="0" frameborder="0" scrolling="no"></iframe> <img height="292" id="archi" src="http://static.righto.com/images/arch-anim.gif" width="292" /> <input id="archb" onclick="toggle('archi', 'archb', '/images/arch-frame.gif', '/images/arch-anim.gif');" value="Stop animation" type="button"> <p> The code, in <code>arch.arc</code>, has several parts. The <code>arch</code> function does the OpenGL work to create the Arch out of triangles and quadrilaterals. It uses <code>archfan</code> to generate the triangle fan for half of the front of the arch. The full code is too long to include here, but the following code, which generates the inside of the arch, should give a taste: </p><pre class="arc"> (for i 0 (+ n n -1) (withs (angle (* (/ 3.1415926 n 2) i) angle2 (* (/ 3.1415926 n 2) (+ i 1))) (gl-normal (* r (cos angle)) (* r -1 (sin angle)) 0) (gl-vertex (* r -1 (cos angle)) (* r (sin angle)) z) (gl-vertex (* r -1 (cos angle)) (* r (sin angle)) negz) (gl-normal (* r (cos angle2)) (* r -1 (sin angle2)) 0) (gl-vertex (* r -1 (cos angle2)) (* r (sin angle2)) negz) (gl-vertex (* r -1 (cos angle2)) (* r (sin angle2)) z))) </pre> The next section of the code contains the graphics callback functions: <ul> <li>ex-run: the animation entry point called by the timer. Updates the rotation and refreshes the image. </li><li>ex-on-paint: uses OpenGL commands to draw the arch </li><li>ex-on-size: handles window resize and initial size. The OpenGL model (arch, lighting, projection) is set up here. </li></ul> The last part of the code calls into Scheme to create the canvas and tie it to the appropriate callbacks, create the frame holding the canvas, and display the frame. <p> I find the arch-generation code somewhat unsatisfying stylistically, as there is a lot of duplicated code to generate the vertices and normal vectors for the front, back, and sides. I couldn't come up with a nice way to fold everything together. I suppose the Arc-y solution would be to write a DSL to express graphical objects, but that's beyond the scope of this project. </p><p> Let me mention that low-level OpenGL is not particuarly friendly for exploratory programming. It's tricky to generate complex shapes correctly: it's really easy to end up with the wrong normals, vertices that aren't clockwise, non-convex polygons, and many other random problems. I find it works much better to sketch out what I'm doing on paper first; if I just start coding, I end up with a mess of bad polygons. In addition, I've found that doing the wrong thing in OpenGL will lock up DrScheme and/or crash my machine if I'm unlucky. </p><h3>The gears example</h3> I also ported the <a href="https://images.google.com/images?um=1&q=opengl+gears+&btnG=Search+Images">classic</a> OpenGL "gears" demo from Scheme to Arc. This demo includes GUI buttons to rotate the gears. (The animated GIF at the top of the page shows the program in operation.) This is a fairly straightforward port of <code>gears.scm</code> that comes with DrScheme. To run it: <ul><li>Enter into the Arc REPL: <code>(load "gears.arc")</code> </li></ul> <p> The interesting thing to note in <code>gear.arc</code> is the <code>horizontal-panel%</code>, <code>vertical-panel%</code>, and <code>button%</code> objects that provide the UI controls. They are linked to Arc functions to update the viewing parameters. For example, in the following, note that <code>instantiate</code> is passing Arc code (using <code>fn</code>) to the Scheme constructor for <code>button%</code>. The tricky part is making sure the right things get evaluated in the right language: </p><pre class="arc"> (instantiate 'button% (list "Right" h (fn x (ex-move-right))) '(stretchable-width #t)) </pre> How did I generate the animated gifs? Just brute force: I took some screenshots and joined them into an animated gif using gimp. The real animation is smoother. I found the animated gifs are a bit annoying, so I added JavaScript to start and stop them. The animation is stopped by substituting a static gif. <h3>Conclusion</h3> So what about the Tetris challenge that inspired my work on OpenGL? After all the effort to get OpenGL to work in Arc, I lost momentum on the original project of implementing the game. (This is an example of <a href="http://www.righto.com/2008/05/why-arc-is-bad-for-exploratory.html">why Arc is bad for exploratory programming</a>. If I wanted to get something done, I would have been much better off using DrScheme directly.) Maybe I'll complete the game for a future posting. <div style='clear: both;'></div> </div> <div class='post-footer'> <div 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/6264947694886887540/8566439659177835317' onclick=''> 1 comment: </a> </span> <span class='post-icons'> <span class='item-action'> <a href='https://www.blogger.com/email-post.g?blogID=6264947694886887540&postID=8566439659177835317' title='Email Post'> <img alt='' class='icon-action' height='13' src='http://img1.blogblog.com/img/icon18_email.gif' width='18'/> </a> </span> <span class='item-control blog-admin pid-1138732533'> <a href='https://www.blogger.com/post-edit.g?blogID=6264947694886887540&postID=8566439659177835317&from=pencil' title='Edit Post'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> <span class='post-backlinks post-comment-link'> </span> <div class='post-share-buttons goog-inline-block'> <a class='goog-inline-block share-button sb-email' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=8566439659177835317&target=email' target='_blank' title='Email This'><span class='share-button-link-text'>Email This</span></a><a class='goog-inline-block share-button sb-blog' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=8566439659177835317&target=blog' onclick='window.open(this.href, "_blank", "height=270,width=475"); return false;' target='_blank' title='BlogThis!'><span class='share-button-link-text'>BlogThis!</span></a><a class='goog-inline-block share-button sb-twitter' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=8566439659177835317&target=twitter' target='_blank' title='Share to X'><span class='share-button-link-text'>Share to X</span></a><a class='goog-inline-block share-button sb-facebook' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=8566439659177835317&target=facebook' onclick='window.open(this.href, "_blank", "height=430,width=640"); return false;' target='_blank' title='Share to Facebook'><span class='share-button-link-text'>Share to Facebook</span></a><a class='goog-inline-block share-button sb-pinterest' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=8566439659177835317&target=pinterest' target='_blank' title='Share to Pinterest'><span class='share-button-link-text'>Share to Pinterest</span></a> </div> </div> <div class='post-footer-line post-footer-line-2'><span class='post-labels'> Labels: <a href='http://www.righto.com/search/label/arc' rel='tag'>arc</a> </span> </div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> </div></div> <div class="date-outer"> <div class="date-posts"> <div class='post-outer'> <div class='post hentry' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='6264947694886887540' itemprop='blogId'/> <meta content='1703182505241437779' itemprop='postId'/> <a name='1703182505241437779'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='http://www.righto.com/2008/05/why-arc-is-bad-for-exploratory.html'>Why Arc is bad for exploratory programming</a> </h3> <div class='post-header'> <div class='post-header-line-1'></div> </div> <div class='post-body entry-content' id='post-body-1703182505241437779' itemprop='description articleBody'> Recently, I've been reading <a href="https://www.amazon.com/exec/obidos/ASIN/0596529325/rightocom">Programming Collective Intelligence</a>, which is a practical guide to machine learning algorithms, showing how to build a recommendation system, implement a search engine, classify documents, mine websites, use genetic algorithms and simulated annealing, and implement other machine learning tasks. The book shows how to implement each of these in surprisingly few lines of Python. <p> <iframe src="http://rcm.amazon.com/e/cm?t=rightocom&o=1&p=8&l=as1&asins=0596529325&fc1=000000&IS2=1<1=_blank&lc1=0000FF&bc1=000000&bg1=FFFFFF&f=ifr&npa=1" style="width:120px;height:240px;float:right;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe> The book is an excellent example of exploratory programming, showing how to incrementally build up these applications and experiment with different algorithms from the Python interactive prompt. For instance, topic clustering is illustrated by first implementing code to fetch blog pages from RSS feeds, breaking the pages into words, applying first a hierarchical clustering algorithm and then a K-means clustering algorithm to the contents, and then graphically displaying a dendrogram showing related blogs. At each step, the book shows how to try out the code and perform different experiments from the interactive prompt. <p> By using Python libraries, each step of implementation is pretty easy; the book can focus on the core algorithms, and leave the routine stuff to libraries: urllib2 to fetch web pages, Universal Feed Parser to access RSS feeds, Beautiful Soup to parse HTML, Python Imaging Library to generate images, pydelicious to access links on del.icio.us, and so forth. <p> If you want more details than the book provides (it is surprisingly lacking in references), I recommend Andrew Moore's online <a href="http://www.autonlab.org/tutorials/">Statistical Data Mining Tutorials</a>, which covers many of the same topics. <h3>What does this have to do with Arc?</h3> While reading this book, I was struck by the contradiction that this book is a perfect example of exploratory programming, Arc is "<a href="http://www.paulgraham.com/arc0.html">tuned for exploratory programming</a>", and yet using Arc to work through the Collective Intelligence algorithms in Arc is an exercise in frustration. <p> The problem, of course, is that Arc lacks libraries. Arc lacks basic functionality such as fetching a web page, parsing an XML document, or accessing a database. Arc lacks utility libraries to parse HTML pages or perform numerical analysis. Arc lacks specialized API libraries to access sites such as del.icio.us or Akismet. Arc lacks specialized numerical libraries such as a support-vector machine implementation. (In fact, Arc doesn't even have all the functionality of <a href="http://www3.nbnet.nb.ca/mclays/level2.html">TRS-80 BASIC</a>, which is a pretty low bar. Arc is inexplicably lacking trig, exp, and log, not to mention arrays and decent error reporting.) <p> To be sure, one could implement these libraries in Arc. The point is that implementing libraries detours you from the exploratory programming you're trying to do. <p> Paul Graham has commented that <a href="http://www.paulgraham.com/langdes.html">libraries are becoming an increasingly important component of programming languages</a>, that <a href="http://www.paulgraham.com/arcll1.html">huge libraries</a> are now an expected part of a new programming language, and that libraries are <a href="http://www.paulgraham.com/popular.html">an increasing important feature of programming languages</a>. Given this understanding of the importance of libraries, it's surprising that Arc is so lacking in libraries. (It's also surprising that it lacks a module system or some other way to package libraries.) It's a commonplace complaint about Lisp that it lacks libraries compared to other languages, and Arc makes this even worse. <p> I think there are two different kinds of exploratory programming. The first I'll call the "Lisp model", where you are building a system from scratch, without external dependencies. The second, which I believe is much more common, is the "Perl/Python model", where you are interacting with existing systems and building on previous work. In the first case, libraries don't really matter, but in the second case, libraries are critical. The recently-popular article <a href="http://www.stanford.edu/~pgbovine/programming-vacuum.htm">Programming in a Vacuum</a> makes this point well, that picking the "best" language is fine in a vacuum, but in the real world what libraries are available is usually the key. <p> Besides the lack of libraries. Arc's slow performance rules it out for many of the algorithms from Programming Collective Intelligence. Many of the algorithms run uncomfortably slow in Python, and running Arc is <a href="http://arclanguage.org/item?id=2455">that much</a> worse. It's just not true that speed is unimportant in exploratory programming. <p> On the positive side for Arc, chapter 11 of Programming Collective Intelligence implements genetic programming algorithms by representing programs as trees, which are then evolved and executed. To support this, the book provides Python classes to represent code as a parse tree, execute the code tree, and prettyprint the tree. As the book points out, Lisp and its variants let you represent programs as trees directly. Thus, using Arc gives you the ability to represent code as a tree and dynamically modify the code tree for free. (However, it only takes 50 lines of Python to implement the tree interpreter, so the cost of <a href="https://en.wikipedia.org/wiki/Greenspun's_Tenth_Rule">Greenspunning</a> is not particularly severe.) <p> To summarize, a language for exploratory programming should be concise, interactive, reasonably fast, and have sufficient libraries. Arc currently fails on the last two factors. Time will tell if these issues get resolved or not. <div style='clear: both;'></div> </div> <div class='post-footer'> <div 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/6264947694886887540/1703182505241437779' onclick=''> 13 comments: </a> </span> <span class='post-icons'> <span class='item-action'> <a href='https://www.blogger.com/email-post.g?blogID=6264947694886887540&postID=1703182505241437779' title='Email Post'> <img alt='' class='icon-action' height='13' src='http://img1.blogblog.com/img/icon18_email.gif' width='18'/> </a> </span> <span class='item-control blog-admin pid-1138732533'> <a href='https://www.blogger.com/post-edit.g?blogID=6264947694886887540&postID=1703182505241437779&from=pencil' title='Edit Post'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> <span class='post-backlinks post-comment-link'> </span> <div class='post-share-buttons goog-inline-block'> <a class='goog-inline-block share-button sb-email' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=1703182505241437779&target=email' target='_blank' title='Email This'><span class='share-button-link-text'>Email This</span></a><a class='goog-inline-block share-button sb-blog' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=1703182505241437779&target=blog' onclick='window.open(this.href, "_blank", "height=270,width=475"); return false;' target='_blank' title='BlogThis!'><span class='share-button-link-text'>BlogThis!</span></a><a class='goog-inline-block share-button sb-twitter' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=1703182505241437779&target=twitter' target='_blank' title='Share to X'><span class='share-button-link-text'>Share to X</span></a><a class='goog-inline-block share-button sb-facebook' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=1703182505241437779&target=facebook' onclick='window.open(this.href, "_blank", "height=430,width=640"); return false;' target='_blank' title='Share to Facebook'><span class='share-button-link-text'>Share to Facebook</span></a><a class='goog-inline-block share-button sb-pinterest' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=1703182505241437779&target=pinterest' target='_blank' title='Share to Pinterest'><span class='share-button-link-text'>Share to Pinterest</span></a> </div> </div> <div class='post-footer-line post-footer-line-2'><span class='post-labels'> Labels: <a href='http://www.righto.com/search/label/arc' rel='tag'>arc</a>, <a href='http://www.righto.com/search/label/snark' rel='tag'>snark</a> </span> </div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> </div></div> <div class="date-outer"> <div class="date-posts"> <div class='post-outer'> <div class='post hentry' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='http://static.righto.com/images/postage.jpg' itemprop='image_url'/> <meta content='6264947694886887540' itemprop='blogId'/> <meta content='5155604641366609339' itemprop='postId'/> <a name='5155604641366609339'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='http://www.righto.com/2008/05/importance-of-software-testing.html'>The importance of software testing</a> </h3> <div class='post-header'> <div class='post-header-line-1'></div> </div> <div class='post-body entry-content' id='post-body-5155604641366609339' itemprop='description articleBody'> At work we have a nifty electronic postage kiosk that will weigh letters, compute the postage, print a postage strip, and bill a credit card all through a display and touch screen. When I tried using it to mail a letter, everything went fine until I got a Internet Explorer error dialog: <br> <img alt="Error message" src="http://static.righto.com/images/postage.jpg"> <br> It's always a surprise when an embedded system reveals its inner workings. Somehow I assume such systems are built on some super-special technology, not HTML and Internet Explorer. <p> I should mention that I was just sending a letter to Canada. While this isn't the most common thing to do, it's not a particularly bizarre action either. And I definitely wasn't doing a sinister action such as sending a letter to the country of "DROP TABLE". (I should also mention that this blog posting has nothing to do with Arc, in case my regular readers are wondering.) <p> I started over with the kiosk and the same error dialog appeared again. At this point, I dismissed the dialog box via the touch screen and continued with Buy Postage. It displayed "Total Postage $NaN" (i.e. <a href="https://en.wikipedia.org/wiki/NaN">Not a Number</a>). When it asked for my credit card, I hesitated briefly, I figured the worst case was I'd have to send them a check for 0/0; it's not like they were going to bill me +Infinity. Curiosity got the better of me and I decided to plunge forward in the interests of science. After I swiped my credit card, the kiosk printed a $0.69 postage strip, and gave me a receipt: <br><img alt="receipt" src="http://static.righto.com/images/receipt.gif"><br> Sure enough, the receipt said my credit card had been charged $NaN. I can only imagine what the billing backend would make of that. I called my credit card company to check what really happened, but the day's transactions weren't available yet. <p> I see a couple morals to this story. The most obvious is that normal people don't swipe their credit cards through a machine offering to bill them $NaN. But the more relevant moral is that error checking and software testing is a good thing, especially when monetary transactions are concerned. <p> P.S. I emailed the kiosk support, and they assured me that the billing problems following a "system change" were resolved, and I'd be billed the proper $0.69. <div style='clear: both;'></div> </div> <div class='post-footer'> <div 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/6264947694886887540/5155604641366609339' onclick=''> 1 comment: </a> </span> <span class='post-icons'> <span class='item-action'> <a href='https://www.blogger.com/email-post.g?blogID=6264947694886887540&postID=5155604641366609339' title='Email Post'> <img alt='' class='icon-action' height='13' src='http://img1.blogblog.com/img/icon18_email.gif' width='18'/> </a> </span> <span class='item-control blog-admin pid-1138732533'> <a href='https://www.blogger.com/post-edit.g?blogID=6264947694886887540&postID=5155604641366609339&from=pencil' title='Edit Post'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> <span class='post-backlinks post-comment-link'> </span> <div class='post-share-buttons goog-inline-block'> <a class='goog-inline-block share-button sb-email' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=5155604641366609339&target=email' target='_blank' title='Email This'><span class='share-button-link-text'>Email This</span></a><a class='goog-inline-block share-button sb-blog' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=5155604641366609339&target=blog' onclick='window.open(this.href, "_blank", "height=270,width=475"); return false;' target='_blank' title='BlogThis!'><span class='share-button-link-text'>BlogThis!</span></a><a class='goog-inline-block share-button sb-twitter' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=5155604641366609339&target=twitter' target='_blank' title='Share to X'><span class='share-button-link-text'>Share to X</span></a><a class='goog-inline-block share-button sb-facebook' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=5155604641366609339&target=facebook' onclick='window.open(this.href, "_blank", "height=430,width=640"); return false;' target='_blank' title='Share to Facebook'><span class='share-button-link-text'>Share to Facebook</span></a><a class='goog-inline-block share-button sb-pinterest' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=5155604641366609339&target=pinterest' target='_blank' title='Share to Pinterest'><span class='share-button-link-text'>Share to Pinterest</span></a> </div> </div> <div class='post-footer-line post-footer-line-2'><span class='post-labels'> Labels: <a href='http://www.righto.com/search/label/snark' rel='tag'>snark</a> </span> </div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> </div></div> <div class="date-outer"> <div class="date-posts"> <div class='post-outer'> <div class='post hentry' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='6264947694886887540' itemprop='blogId'/> <meta content='6955417856636538737' itemprop='postId'/> <a name='6955417856636538737'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='http://www.righto.com/2008/04/idioms-and-patterns-in-arc.html'>Idioms for programming in Arc</a> </h3> <div class='post-header'> <div class='post-header-line-1'></div> </div> <div class='post-body entry-content' id='post-body-6955417856636538737' itemprop='description articleBody'> The code that implements Arc illustrates many useful programming techniques. Some of the techniques occur multiple times, and can be considered idioms of Arc programming; techniques that can be applied to many problems. This article describes some of the most common idioms, and how they can be used in Arc programming. The techniques described focus largely on macros and recursion. <h3>Macros</h3> Not surprisingly, given Paul Graham's enthusiasm for macros, Arc makes heavy use of macros. A few idioms appear commonly in the code. <h4>"Decorated body"</h4> The most common use of macros in Arc is something I call the "decorated body", which wraps a chunk of body code with something to extend it, analogous to the <a href="https://en.wikipedia.org/wiki/Decorator_pattern">decorator design pattern</a>. Typically the decorator will set something up before executing the body code, as in <a href="/doc/io.html#w%2foutstring">w/outstring</a>, <a href="/doc/table.html#w%2ftable">w/table</a>, and <a href="/doc/io.html#fromstring">fromstring</a>. (Note: the link for each operation goes to the documentation. Clicking on the code icon in the documentation will show the code for the operation.) The pattern is also used to set something up before execution and then clean up afterwards. This is especially useful for file operations, as in <a href="http://www.righto.com/doc/io.html#w%2finfile">w/infile</a>, <a href="http://www.righto.com/doc/io.html#w%2foutfile">w/outfile</a>, and <a href="http://www.righto.com/doc/io.html#w%2finstring">w/instring</a>. These macros often have names starting with "w/", short for "with/", indicating what they are providing to the body. The <a href="http://www.righto.com/doc/html.html">HTML library</a> makes heavy use of this idiom, for example in <a href="http://www.righto.com/doc/html.html#tag">tag</a>, <a href="http://www.righto.com/doc/html.html#form">form</a>, and <a href="http://www.righto.com/doc/html.html#cdata">cdata</a>, which wrap the body in various HTML opening and closing tags. <p> To examine the implementation of this idiom, consider <a href="/doc/variables.html#let">let</a>, which is defined as: <pre class="code"> (mac let (var val . body) `(with (,var ,val) ,@body)) </pre> The typical features of this idiom are a macro definition with argument <code> . body</code> to pick up the remainder of the arguments, a macro definition starting with quasiquote <code>`</code>, and unquote-splicing <code>,@body</code> to substitute the body code into the macro. The macro performs simple substitution: <pre class="arc"> arc> (macex1 '(let foo 42 body1 body2)) (with (foo 42) body1 body2) </pre> <h4>Macro for control of evaluation</h4> Unlike functions, macros receive their arguments unevaluated. This allows macros to be used for <a href="/doc/conditionals.html">conditional</a> execution of code, or to execute code multiple times <a href="/doc/iteration.html">iteratively</a>. Some examples are <a href="http://www.righto.com/doc/conditionals.html#when">when</a>, <a href="http://www.righto.com/doc/conditionals.html#unless">unless</a>, <a href="http://www.righto.com/doc/iteration.html#while">while</a>, and <a href="http://www.righto.com/doc/iteration.html#for">for</a>. <p> (You might expect <a href="http://www.righto.com/doc/conditionals.html#if">if</a> to be a macro. It is actually a built-in special form, since conditional macros need to be based on some underlying conditional form.) <p> The code for <a href="http://www.righto.com/doc/iteration.html#repeat">repeat</a> illustrates that this idiom also uses the <code>,@body</code> structure as "decorated body": <pre class="code"> (mac repeat (n . body) `(for ,(uniq) 1 ,n ,@body)) </pre> <h4>Macro as lambda adapter</h4> A variant of the body decorator is to use a macro to convert body code into a lambda function, which is similar to an <a href="https://en.wikipedia.org/wiki/Adapter_pattern">adapter design pattern</a>. This idiom is used when a function expects to receive a lambda function, but passing in body code is more convenient, especially when the base function is a Scheme primitive. Examples are <a href="http://www.righto.com/doc/threading.html#thread">thread</a>, <a href="/doc/atomic.html#atomic">atomic</a>, <a href="http://www.righto.com/doc/io.html#w%2fstdin">w/stdin</a>, and <a href="http://www.righto.com/doc/io.html#w%2fstdout">w/stdout</a>: <pre class="code"> (mac w/stdout (str . body) `(call-w/stdout ,str (fn () ,@body))) </pre> <pre class="arc"> arc> (macex '(w/stdout foo body1 body2)) (call-w/stdout foo (fn nil body1 body2)) </pre> <h4>Macro to create functions with parameters</h4> Another common macro idiom is to take a list of parameters and body code, and build a function out of these. This idiom is typically used to define a function that has special properties, and is often given a name that starts with "def". Some examples are <a href="http://www.righto.com/doc/anaphoric.html#rfn">rfn</a>, <a href="http://www.righto.com/doc/anaphoric.html#afn">afn</a>, <a href="http://www.righto.com/doc/variables.html#defmemo">defmemo</a>, <a href="http://www.righto.com/doc/srv.html#defop">defop</a>, <a href="http://www.righto.com/doc/srv.html#defopr">defopr</a>, <a href="http://www.righto.com/doc/srv.html#linkf">linkf</a>, and <a href="http://www.righto.com/doc/srv.html#rlinkf">rlinkf</a>. <p> The code for <code>defmemo</code> shows the key component of this idiom: <code>(fn ,parms ,@body)</code> to build the function out of the parameters and body. <pre class="code"> (mac defmemo (name parms . body) `(safeset ,name (memo (fn ,parms ,@body)))) </pre> <h4>Complex macros</h4> One irony is that even though though macros are extremely powerful, most of the macros in Arc perform simple substitutions. There are, however, some macros that perform complex manipulation of their arguments. Assignment is built from the <a href="http://www.righto.com/doc/setforms.html">setform</a> macro, which implements generalized variables through intricate macro processing of the arguments. Slightly less complex is <a href="http://www.righto.com/doc/combining.html#and">and</a>, which implements short-circuit evaluation by turning its arguments into nested <code>if</code> statements. Another interesting example is <a href="http://www.righto.com/doc/variables.html#with">with</a>; the macro splits up the arguments into variables and values: <pre class="arc"> arc> (macex '(with (a 1 b 2) (prn a b))) ((fn (a b) (prn a b)) 1 2) </pre> The <a href="http://www.righto.com/doc/string.html#litmatch">litmatch</a> macro performs string matching by generating code to perform a sequence of character comparisons. <pre class="arc"> arc> (macex '(litmatch "abc" foo)) ((fn (gs1442 gs1443) (unless (> (+ gs1443 3) (len gs1442)) (and (is #\a (gs1442 (+ gs1443 0))) (is #\b (gs1442 (+ gs1443 1))) (is #\c (gs1442 (+ gs1443 2)))))) foo 0) </pre> <h3>Recursion</h3> <a href="https://en.wikipedia.org/wiki/Tail_recursion">Tail recursion</a> is a standard Scheme technique for efficient recursion. If the last operation of a function is a recursive call, the compiler will use tail-call optimization to turn the recursion into iteration, avoiding creation of a stack frame on each call. <p> Iteration in Arc is built on top of tail recursion. Basic loop operations such as <a href="http://www.righto.com/doc/iteration.html#while">while</a>, <a href="http://www.righto.com/doc/iteration.html#loop">loop</a>, and <a href="http://www.righto.com/doc/iteration.html#whilet">whilet</a> use tail recursion on a function built from <a href="http://www.righto.com/doc/anaphoric.html#rfn">rfn</a>: <pre class="code"> (mac while (test . body) (w/uniq (gf gp) `((rfn ,gf (,gp) (when ,gp ,@body (,gf ,test))) ,test))) </pre> <h4>cdr-scanning</h4> <p> A typical idiom for scanning a list is to tail-recursively call the function on the <code>cdr</code> of the list. Some examples are <a href="http://www.righto.com/doc/list.html#reclist">reclist</a>, <a href="http://www.righto.com/doc/list.html#nthcdr">nthcdr</a>, <a href="http://www.righto.com/doc/list.html#last">last</a>, and <a href="http://www.righto.com/doc/list.html#rev">rev</a>. <p> The code for <a href="http://www.righto.com/doc/assoc.html#assoc">assoc</a> illustrates this idiom. If there is no match, <code>assoc</code> is called on the <code>cdr</code>, until the whole list has been scanned: <pre class="code"> (def assoc (key al) (if (atom al) nil (and (acons (car al)) (is (caar al) key)) (car al) (assoc key (cdr al)))) </pre> <h4>Tail-recursive string functions</h4> One idiom in Arc for using tail recursion with strings is to add an index parameter to the function. This index parameter indexes into the string, and by incrementing it in each call, the function can be made tail-recursive and doesn't require modifying the string. The index parameter is often made an optional parameter so "normal" uses of the function don't need to specify the index. Some examples of this idiom are <a href="http://www.righto.com/doc/string.html#recstring">recstring</a>, <a href="http://www.righto.com/doc/string.html#findsubseq">findsubseq</a>, <a href="http://www.righto.com/doc/app.html#indented-code">indented-code</a>, <a href="http://www.righto.com/doc/app.html#parabreak">parabreak</a>, and <a href="http://www.righto.com/doc/app.html#urlend">urlend</a>. <p> The code for <a href="http://www.righto.com/doc/string.html#headmatch">headmatch</a> illustrates this idiom; in this case the tail-recursion uses an <a href="/doc/anaphoric.html">anaphoric function</a>: <pre class="code"> (def headmatch (pat seq (o start 0)) (let p (len pat) ((afn (i) (or (is i p) (and (is (pat i) (seq (+ i start))) (self (+ i 1))))) 0))) </pre> <h4>Recursion with cons</h4> Many operations in Arc need to perform operations on a sequence and create a result list. The common Arc idiom is to recurse through a sequence, building up the result with <code>cons</code>. Specifically, a macro <code>(op seq)</code> will return the cons of something done to <code>(car seq)</code> and <code>(op (cdr seq))</code>. Thus, <code>op</code> recursively steps through <code>seq</code>, processing an element at a time and building up the result. This idiom provides an interesting contrast to the previous recursion examples because this idiom is not tail-recursive. Because the <code>cons</code> is applied to the result of the recursive function call, tail-call optimization cannot be applied. Several examples of this idiom are <a href="http://www.righto.com/doc/list.html#join">join</a>, <a href="http://www.righto.com/doc/list.html#rem">rem</a>, <a href="http://www.righto.com/doc/list.html#reinsert-sorted">reinsert-sorted</a>, <a href="http://www.righto.com/doc/list.html#pair">pair</a>, <a href="http://www.righto.com/doc/list.html#firstn">firstn</a>, <a href="http://www.righto.com/doc/list.html#firstn-that">firstn-that</a>, <a href="http://www.righto.com/doc/list.html#tuples">tuples</a>, and <a href="http://www.righto.com/doc/list.html#range">range</a>. <p> The code for <a href="http://www.righto.com/doc/list.html#map1">map1</a> illustrates this idiom: <pre class="code"> (def map1 (f xs) (if (no xs) nil (cons (f (car xs)) (map1 f (cdr xs))))) </pre> Note that <code>f</code> is applied to <code>(car xs)</code>, <code>map1</code> is called recursively on <code>(cdr xs)</code>, and the two are cons'd together. <h3>Miscellaneous</h3> The majority of the idioms I discuss are based on macros or recursion. This secion discusses some miscellaneous idioms that don't fit those categories. <h4>Push and reverse</h4> The "push and reverse" idiom is an efficient, but somewhat surprising way to generate a list. In this idiom, successive elements are pushed onto the front of the list, and when the entire list is generated, it is reversed to obtain the desired order. This is a well-known <a href="http://cybertiggyr.com/gene/lid/">Lisp idiom</a> and is more efficient than the obvious method of appending elements to the end of the list. Several examples of "push and reverse" are <a href="http://www.righto.com/doc/iteration.html#drain">drain</a>, <a href="http://www.righto.com/doc/list.html#dedup">dedup</a>, <a href="http://www.righto.com/doc/io.html#parse-format">parse-format</a>, <a href="http://www.righto.com/doc/string.html#litmatch">litmatch</a>, <a href="http://www.righto.com/doc/string.html#endmatch">endmatch</a>, and <a href="http://www.righto.com/doc/srv.html#handle-post">handle-post</a>. <p> The code for <a href="http://www.righto.com/doc/list.html#n-of">n-of</a> illustrates the idiom. Items are added with <a href="http://www.righto.com/doc/assignment.html#push">push</a> to an accumulator (<code>ga</code> in this case), and the accumulator is reversed with <a href="http://www.righto.com/doc/list.html#rev">rev</a> at the end: <pre class="code"> (mac n-of (n expr) (w/uniq ga `(let ,ga nil (repeat ,n (push ,expr ,ga)) (rev ,ga)))) </pre> <h4>String stdout</h4> Arc makes extensive use of an idiom I'll call "string stdout" because a string is used as stdout. The code writes multiple chunks to stdout, and the results are gathered into a string. This idiom avoids having to manually concatenate the components into the result string. The <a href="http://www.righto.com/doc/io.html#tostring">tostring</a> macro is used to implement this idiom. Arc has a surprisingly large number of macros that use this idiom, including <a href="http://www.righto.com/doc/io.html#readline">readline</a>, <a href="http://www.righto.com/doc/app.html#code-block">code-block</a>, <a href="http://www.righto.com/doc/app.html#unmarkdown">unmarkdown</a>, <a href="http://www.righto.com/doc/app.html#varfield">varfield</a>, <a href="http://www.righto.com/doc/app.html#markdown">markdown</a>, <a href="http://www.righto.com/doc/html.html#eschtml">eschtml</a>, <a href="http://www.righto.com/doc/html.html#striptags">striptags</a>, <a href="http://www.righto.com/doc/html.html#parafy">parafy</a>, <a href="http://www.righto.com/doc/string.html#subst">subst</a>, <a href="http://www.righto.com/doc/string.html#multisubst">multisubst</a>, and <a href="http://www.righto.com/doc/string.html#num">num</a>. <p> Typically, code using this idiom will use produce output with <code>pr</code> or <code>writec</code>, and use <code>tostring</code> to collect the output. The code for <a href="http://www.righto.com/doc/string.html#multisubst">multisubst</a> illustrates this: <pre class="code"> (def multisubst (pairs seq) (tostring (forlen i seq (iflet (old new) (find [begins seq (car _) i] pairs) (do (++ i (- (len old) 1)) (pr new)) (pr (seq i)))))) </pre> <p> The flip side of this idiom is the "string stdin" idiom, where a string is used as stdin. The "string stdin" idiom is rarely used; one example is <a href="http://www.righto.com/doc/io.html#parse-format">parse-format</a>. <h3>Summary</h3> The Arc code illustrates several common Arc idioms, some of which are well-known Scheme or Lisp idioms. Since Paul Graham is a Lisp expert, carefully studying his Arc code is a rewarding way to learn more about programming Lisp-like languages. <p> Undoubtedly I've missed some important idioms. Please let me know if your favorite idiom is missing, or if I've mangled the descriptions of any idioms. <div style='clear: both;'></div> </div> <div class='post-footer'> <div 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/6264947694886887540/6955417856636538737' onclick=''> 2 comments: </a> </span> <span class='post-icons'> <span class='item-action'> <a href='https://www.blogger.com/email-post.g?blogID=6264947694886887540&postID=6955417856636538737' title='Email Post'> <img alt='' class='icon-action' height='13' src='http://img1.blogblog.com/img/icon18_email.gif' width='18'/> </a> </span> <span class='item-control blog-admin pid-1138732533'> <a href='https://www.blogger.com/post-edit.g?blogID=6264947694886887540&postID=6955417856636538737&from=pencil' title='Edit Post'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> <span class='post-backlinks post-comment-link'> </span> <div class='post-share-buttons goog-inline-block'> <a class='goog-inline-block share-button sb-email' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=6955417856636538737&target=email' target='_blank' title='Email This'><span class='share-button-link-text'>Email This</span></a><a class='goog-inline-block share-button sb-blog' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=6955417856636538737&target=blog' onclick='window.open(this.href, "_blank", "height=270,width=475"); return false;' target='_blank' title='BlogThis!'><span class='share-button-link-text'>BlogThis!</span></a><a class='goog-inline-block share-button sb-twitter' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=6955417856636538737&target=twitter' target='_blank' title='Share to X'><span class='share-button-link-text'>Share to X</span></a><a class='goog-inline-block share-button sb-facebook' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=6955417856636538737&target=facebook' onclick='window.open(this.href, "_blank", "height=430,width=640"); return false;' target='_blank' title='Share to Facebook'><span class='share-button-link-text'>Share to Facebook</span></a><a class='goog-inline-block share-button sb-pinterest' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=6955417856636538737&target=pinterest' target='_blank' title='Share to Pinterest'><span class='share-button-link-text'>Share to Pinterest</span></a> </div> </div> <div class='post-footer-line post-footer-line-2'><span class='post-labels'> Labels: <a href='http://www.righto.com/search/label/arc' rel='tag'>arc</a> </span> </div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> </div></div> <div class="date-outer"> <div class="date-posts"> <div class='post-outer'> <div class='post hentry' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='6264947694886887540' itemprop='blogId'/> <meta content='7970471716700777702' itemprop='postId'/> <a name='7970471716700777702'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='http://www.righto.com/2008/04/many-arc-compilers-and-interpreters.html'>Many Arc compilers and interpreters</a> </h3> <div class='post-header'> <div class='post-header-line-1'></div> </div> <div class='post-body entry-content' id='post-body-7970471716700777702' itemprop='description articleBody'> The introduction of the Arc language has spawned a mini-boom of Arc compilers and interpreters implemented in everything from JavaScript to .NET. Because Arc is a fairly simple Lisp dialect, it is relatively straightforward to implement, and many people are using it to learn about compiler and interpreter design, and to showcase different implementation techniques and languages. <p> Paul Graham's <a href="http://arclanguage.org/install">official distribution</a> started it all, of course. This version is implemented in MzScheme and translates Arc into Scheme code. The writeup on <a href="http://www.righto.com/2008/02/arc-internals-part-1.html">Arc Internals</a> provides more information on how it is implemented. <p> The <a href="http://arclanguage.org/form">Arc Forum</a> is the site of most of the unofficial Arc development effort. The "Anarki" branches of Arc on <a href="https://github.com/nex3/arc">github</a> consist of a "stable" bug-fixed version of official Arc, and a more exploratory version with many modifications. (For information on using github, see <a href="http://www.righto.com/2008/02/git-and-anarki-arc-repository-brief.html">Brief Guide to Anarki and Git</a>. <p> Anarki includes "ac.sbcl.lisp", an implementation of Arc in SBCL. It implements closures using CPS (<a href="https://en.wikipedia.org/wiki/Continuation-passing_style">Continuation-passing style)</a> transformations, but doesn't include threads or networking according to the <a href="http://arclanguage.org/item?id=5509">brief description</a>. <p> Perhaps the first reimplementation of Arc was ArcLite, which is Arc ported to JavaScript. This version of Arc is unique because it runs in the browser. The running version can be accessed <a href="http://halogen.note.amherst.edu/~jdtang/arclite/">online</a>. It provides a subset of functionality, omitting tail-call optimization, continuations, and various operations. <p> Rainbow (<i>l'arc en ciel</i> in French) is an implementation of Arc in Java. It is fairly complete, providing continuations and tail-call optimization according to the <a href="http://arclanguage.org/item?id=6002">description</a>. It is available at <a href="https://github.com/conanite/rainbow">github</a>. <p> An Arc compiler for .NET has been developed, based on the MBase compiler prototyping framework. The <a href="http://arclanguage.org/item?id=4715">description</a> states that it implements a subset of Arc, but is much faster than standard Arc. It is available from <a href="http://www.meta-alternative.net/techpreview.html">Meta Alternative</a>. <p> Currently under active development is "arc2c", which compiles Arc to C. Current status is at <a href="http://arclanguage.org/item?id=5818">arclanguage.org</a>. This compiler is intended to be a full, high-performance implementation of Arc. It uses CPS transformations to implement continuations. It uses the <a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/">Boehm garbage collector</a>. arc2c is available at <a href="https://github.com/sacado/arc2c">github</a>. <p> CL-Arc is a <a href="http://blackthorncentral.net/node/47">proposal</a> to compile Arc to Common Lisp; work hasn't started on it yet. <p> Many of these Arc implementations actively welcome participation. The future is likely to hold continuing improvement in the quality, functionality, and performance of Arc implementations, as well as surprising and unusual variants. <div style='clear: both;'></div> </div> <div class='post-footer'> <div 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/6264947694886887540/7970471716700777702' onclick=''> No comments: </a> </span> <span class='post-icons'> <span class='item-action'> <a href='https://www.blogger.com/email-post.g?blogID=6264947694886887540&postID=7970471716700777702' title='Email Post'> <img alt='' class='icon-action' height='13' src='http://img1.blogblog.com/img/icon18_email.gif' width='18'/> </a> </span> <span class='item-control blog-admin pid-1138732533'> <a href='https://www.blogger.com/post-edit.g?blogID=6264947694886887540&postID=7970471716700777702&from=pencil' title='Edit Post'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> <span class='post-backlinks post-comment-link'> </span> <div class='post-share-buttons goog-inline-block'> <a class='goog-inline-block share-button sb-email' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=7970471716700777702&target=email' target='_blank' title='Email This'><span class='share-button-link-text'>Email This</span></a><a class='goog-inline-block share-button sb-blog' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=7970471716700777702&target=blog' onclick='window.open(this.href, "_blank", "height=270,width=475"); return false;' target='_blank' title='BlogThis!'><span class='share-button-link-text'>BlogThis!</span></a><a class='goog-inline-block share-button sb-twitter' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=7970471716700777702&target=twitter' target='_blank' title='Share to X'><span class='share-button-link-text'>Share to X</span></a><a class='goog-inline-block share-button sb-facebook' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=7970471716700777702&target=facebook' onclick='window.open(this.href, "_blank", "height=430,width=640"); return false;' target='_blank' title='Share to Facebook'><span class='share-button-link-text'>Share to Facebook</span></a><a class='goog-inline-block share-button sb-pinterest' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=7970471716700777702&target=pinterest' target='_blank' title='Share to Pinterest'><span class='share-button-link-text'>Share to Pinterest</span></a> </div> </div> <div class='post-footer-line post-footer-line-2'><span class='post-labels'> Labels: <a href='http://www.righto.com/search/label/arc' rel='tag'>arc</a> </span> </div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> </div></div> <div class="date-outer"> <div class="date-posts"> <div class='post-outer'> <div class='post hentry' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='/ajax/ajax.gif' itemprop='image_url'/> <meta content='6264947694886887540' itemprop='blogId'/> <meta content='8103971589909053546' itemprop='postId'/> <a name='8103971589909053546'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='http://www.righto.com/2008/04/ajax-and-arc.html'>Ajax and Arc</a> </h3> <div class='post-header'> <div class='post-header-line-1'></div> </div> <div class='post-body entry-content' id='post-body-8103971589909053546' itemprop='description articleBody'> Ajax is surprisingly easy to use with the Arc language. This article shows how to implement Ajax-based autocompletion and dynamic page updates using the <a href="http://wiki.script.aculo.us/scriptaculous/">script.aculo.us</a> and <a href="http://prototypejs.org/">Prototype</a> JavaScript frameworks. These frameworks allow Ajax applications to be implemented with just a few lines of additional code. The hard work is done by the script.aculo.us and Prototype libraries. All the Arc code needs to do is provide the list of autocompletion candidates, and the dynamic page content. <h3>The example</h3> This example implements a simple Ajax input autocompleter and dynamic page update. For the autocompleter, as soon as you enter a few letters into the input, it provides a list of matching terms. As soon as you select a term, the page is dynamically updated with associated data, as in the following screenshot: <br> <img alt="screenshot" src="/ajax/ajax.gif" style="border:1px solid #000000;"> <br> For the purposes of the demonstration, the content is information on the countries of the world, obtained from the <a href="https://www.cia.gov/library/publications/the-world-factbook/">CIA World Factbook</a>. <p> To summarize how it all works: When you enter characters in the input field, the script.aculo.us autocompleter JavaScript sends the charaters to the Arc server, which returns the autocomplete suggestions. The autocompleter JavaScript displays the suggestions on the page. When you select a country, the updater JavaScript does three separate requests to the Arc server, to request the population, area, and capital. When the responses arrive, they are inserted into the page. <p> In more detail, the autocompletion is performed by <a href="http://wiki.script.aculo.us/scriptaculous/show/Ajax.Autocompleter">Ajax.Autocompleter</a>, and the dynamic updating is performed by <a href="http://www.prototypejs.org/api/ajax/updater">Ajax.Updater</a>. The control flow is: <ul> <li> The <code>Ajax.Autocompleter</code> associated with the <code>autocomplete</code> input and <code>autocomplete_choices</code> div sends inputs to <code>/auto_complete?prefix=<i>chars</i></code>. <li>The Arc handler sends back a formatted list of autocomplete candidates, e.g. <code> <ul><li>Iran</li><li>Iraq</li><li>Ireland</li></ul></code>. <li>The <code>Ajax.Autocompleter</code> displays the candidates in the <code>autocomplete</code> div. <li>When an autocompletion is selected, the <code>update</code> JavaScript function starts three <code>Ajax.Updater</code> instances, which send an Ajax request to URL <code>/getcontents?field=population&name=<i>value</i>, and similarly for area and capital in parallel. <li>The Arc handler for <code>getcontents</code> returns the desired contents. <li><code>Ajax.Updater</code> puts the contents into the <code>contents</code> div. </ul> <h3>Running the example</h3> First set up the necessary files. <ul> <li>Download <a href="/ajax/ajax.zip">ajax.zip</a> and uncompress it into the same directory that Arc runs in. This zip file provides <code>ajax.html</code>, <code>ajax.arc</code>, <code>data.arc</code>, and <code>autocomplete.css</code>. <li> Download the script.aculo.us library files from <a href="http://script.aculo.us/downloads">script.aculo.us</a>. Copy the <code>.js</code> files from <code>lib</code> and <code>src</code> into the same directory that Arc runs in. </ul> Next, start up the Arc interpreter, load the <code>ajax.arc</code> file, and start the web server. <pre class="arc"> arc> (load "ajax.arc") arc> (thread (serve 8080)) arc> ready to serve port 8080 </pre> Then go to <a href="http://localhost:8080/ajax.html">http://localhost:8080/ajax.html</a>. (Unfortunately I don't have a live demo on a public machine. If anyone sets one up, let me know and I'll add a link here.) <p> Start typing in the box, and you should see a dropdown with autocompleted choices. Click one, and the code will be displayed below asynchronously. <h3>The Arc code</h3> The Arc server code is in <a href="/ajax/ajax.arc"><code>ajax.arc</code></a>. Two Arc handlers are implemented to provide the client-side Ajax support. The first, <code>auto_complete</code> receives the current input contents and returns a list of up to 10 autocompletion candidates formatted in HTML. The second handler, <code>getcontents</code> returns the dynamic content for the page, from the <code>database</code> table. Note that the handlers do nothing particularly special to make them "Ajax"; they are standard Arc web handlers based on <code>defop</code> and can be accessed directly through the browser. See <a href="http://www.righto.com/doc/srv.html">Arc Web Server</a> for more information on web serving with Arc. <pre class="code"> (defop auto_complete req (let prefix (downcase (arg req "prefix")) (prn (to-html-list (cut (startselts prefix keylist) 0 10))))) (defop getcontents req (with (field (arg req "field") name (arg req "name")) (if (is field "population") (prn ((database name) 1)) (is field "area") (prn ((database name) 2)) (is field "capital") (prn ((database name) 3))))) </pre> The handlers use a couple helpers; <code>startselts</code> returns the elements that match the autocomplete prefix and <code>to-html-list</code> wraps the elements in HTML list tags. <pre class="code"> ; Returns a list of elements that start with prefix (def startselts (prefix seq) (rem [no (begins (downcase _) prefix)] seq)) ; Wraps elts in HTML list tags (def to-html-list (elts) (tostring (prall elts "<ul><li>" "</li><li>") (pr "</li></ul>"))) </pre> The actual content is obtained from <a href="/ajax/data.arc"><code>data.arc</code></a>, which contains the information on each country as a list of lists. <pre class="code"> ("United States" "301,139,947" "9,826,630" "Washington, DC") </pre> Some simple code converts the list into a table called <code>database</code> indexed by country for easy lookup, and generates a sorted list of countries for use in autocompletion: <pre class="code"> (= database (table)) (w/infile inf "data.arc" (let datalist (sread inf nil) (each elt datalist (= (database (elt 0)) elt)))) (= keylist (mergesort < (keys database))) </pre> <p> For some reason, the default Arc web server <code>srv.arc</code> doesn't support <code>.js</code> files. The <code>ajax.arc</code> file modifies the server slightly to support these files: <pre class="code"> (= (srv-header* 'text/javascript) "HTTP/1.0 200 OK Content-Type: text/javascript; charset=UTF-8 Connection: close") (def static-filetype (sym) (let fname (string sym) (and (~find #\/ fname) (case (last (check (tokens fname #\.) ~single)) "gif" 'gif "jpg" 'jpg "css" 'text/css "txt" 'text/html "html" 'text/html "js" 'text/javascript )))) </pre> <h3>Debugging</h3> Several things can go wrong when trying to run the example. If the initial page doesn't load at all, something is probably wrong with the Arc server. If no autocompletion happens, the JavaScript may not be loading, or the Arc server may have problems. If the autocompletion shows up as a bulleted list, the CSS file is probably not loading. <p> The Arc code can be debugged in several ways. The first is to access the handlers directly. The autocomplete handler <a href="http://localhost:8080/auto_complete?prefix=a">http://localhost:8080/auto_complete?prefix=a</a> should return a bullet list of autocomplete suggestions. The contents handler: <a href="http://localhost:8080/getcontents?field=area&name=Algeria">http://localhost:8080/getcontents?field=area&name=Algeria</a> should return the dynamic contents value. <p> The Arc code can also be debugged by strategically inserting print statements such as: <pre class="code"> (write req (stderr)) </pre> This will display the request on the Arc console. <p> To debug Ajax, you can use Firefox plugins <a href="http://livehttpheaders.mozdev.org/">Live HTTP Headers</a> and <a href="http://www.getfirebug.com/">Firebug</a>. Live HTTP Headers lets you see the headers between the browser and the server, and is very helpful to determine if something is failing. Firebug allows much more in-depth JavaScript debugging. The browser's JavaScript console is also useful to see JavaScript errors. <p> This article has just scratched the surface of script.aculo.us and Ajax. More information is available at the <a href="http://script.aculo.us/">script.aculo.us</a> website or in <a href="https://www.amazon.com/exec/obidos/ASIN/1934356018/rightocom">books</a>. <div style='clear: both;'></div> </div> <div class='post-footer'> <div 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/6264947694886887540/8103971589909053546' onclick=''> No comments: </a> </span> <span class='post-icons'> <span class='item-action'> <a href='https://www.blogger.com/email-post.g?blogID=6264947694886887540&postID=8103971589909053546' title='Email Post'> <img alt='' class='icon-action' height='13' src='http://img1.blogblog.com/img/icon18_email.gif' width='18'/> </a> </span> <span class='item-control blog-admin pid-1138732533'> <a href='https://www.blogger.com/post-edit.g?blogID=6264947694886887540&postID=8103971589909053546&from=pencil' title='Edit Post'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> <span class='post-backlinks post-comment-link'> </span> <div class='post-share-buttons goog-inline-block'> <a class='goog-inline-block share-button sb-email' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=8103971589909053546&target=email' target='_blank' title='Email This'><span class='share-button-link-text'>Email This</span></a><a class='goog-inline-block share-button sb-blog' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=8103971589909053546&target=blog' onclick='window.open(this.href, "_blank", "height=270,width=475"); return false;' target='_blank' title='BlogThis!'><span class='share-button-link-text'>BlogThis!</span></a><a class='goog-inline-block share-button sb-twitter' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=8103971589909053546&target=twitter' target='_blank' title='Share to X'><span class='share-button-link-text'>Share to X</span></a><a class='goog-inline-block share-button sb-facebook' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=8103971589909053546&target=facebook' onclick='window.open(this.href, "_blank", "height=430,width=640"); return false;' target='_blank' title='Share to Facebook'><span class='share-button-link-text'>Share to Facebook</span></a><a class='goog-inline-block share-button sb-pinterest' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=8103971589909053546&target=pinterest' target='_blank' title='Share to Pinterest'><span class='share-button-link-text'>Share to Pinterest</span></a> </div> </div> <div class='post-footer-line post-footer-line-2'><span class='post-labels'> Labels: <a href='http://www.righto.com/search/label/arc' rel='tag'>arc</a> </span> </div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> </div></div> <div class="date-outer"> <div class="date-posts"> <div class='post-outer'> <div class='post hentry' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='6264947694886887540' itemprop='blogId'/> <meta content='5501711125039302189' itemprop='postId'/> <a name='5501711125039302189'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='http://www.righto.com/2008/04/documentation-of-html-generation-in-arc.html'>Documentation of HTML generation in the Arc language</a> </h3> <div class='post-header'> <div class='post-header-line-1'></div> </div> <div class='post-body entry-content' id='post-body-5501711125039302189' itemprop='description articleBody'> I've created documentation of Arc's <a href="/doc/html.html">HTML generation</a> operations (from arc.arc). There are a lot of different functions there, but I've tried to cover them all. <div style='clear: both;'></div> </div> <div class='post-footer'> <div 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/6264947694886887540/5501711125039302189' onclick=''> No comments: </a> </span> <span class='post-icons'> <span class='item-action'> <a href='https://www.blogger.com/email-post.g?blogID=6264947694886887540&postID=5501711125039302189' title='Email Post'> <img alt='' class='icon-action' height='13' src='http://img1.blogblog.com/img/icon18_email.gif' width='18'/> </a> </span> <span class='item-control blog-admin pid-1138732533'> <a href='https://www.blogger.com/post-edit.g?blogID=6264947694886887540&postID=5501711125039302189&from=pencil' title='Edit Post'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> <span class='post-backlinks post-comment-link'> </span> <div class='post-share-buttons goog-inline-block'> <a class='goog-inline-block share-button sb-email' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=5501711125039302189&target=email' target='_blank' title='Email This'><span class='share-button-link-text'>Email This</span></a><a class='goog-inline-block share-button sb-blog' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=5501711125039302189&target=blog' onclick='window.open(this.href, "_blank", "height=270,width=475"); return false;' target='_blank' title='BlogThis!'><span class='share-button-link-text'>BlogThis!</span></a><a class='goog-inline-block share-button sb-twitter' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=5501711125039302189&target=twitter' target='_blank' title='Share to X'><span class='share-button-link-text'>Share to X</span></a><a class='goog-inline-block share-button sb-facebook' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=5501711125039302189&target=facebook' onclick='window.open(this.href, "_blank", "height=430,width=640"); return false;' target='_blank' title='Share to Facebook'><span class='share-button-link-text'>Share to Facebook</span></a><a class='goog-inline-block share-button sb-pinterest' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=5501711125039302189&target=pinterest' target='_blank' title='Share to Pinterest'><span class='share-button-link-text'>Share to Pinterest</span></a> </div> </div> <div class='post-footer-line post-footer-line-2'><span class='post-labels'> Labels: <a href='http://www.righto.com/search/label/arc' rel='tag'>arc</a> </span> </div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> </div></div> <div class="date-outer"> <div class="date-posts"> <div class='post-outer'> <div class='post hentry' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='http://www.assoc-amazon.com/e/ir?t=rightocom&l=as2&o=1&a=0262011530' itemprop='image_url'/> <meta content='6264947694886887540' itemprop='blogId'/> <meta content='3133368973222586211' itemprop='postId'/> <a name='3133368973222586211'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='http://www.righto.com/2008/03/continuations-made-difficult.html'>Continuations made difficult</a> </h3> <div class='post-header'> <div class='post-header-line-1'></div> </div> <div class='post-body entry-content' id='post-body-3133368973222586211' itemprop='description articleBody'> For a challenge, I translated the "mondo-bizarro" <a href="http://www.righto.com/2008/03/arc-continuation-puzzle.html">Arc Continuation Puzzle</a> into Java. <p> Why would I do that? Because I can :-) But seriously, using continuations in a language entirely unsuited for it is a good way to experience the tradeoffs of different styles of languages, as well as a way to learn more about how continuations work. <span class="fullpost"> <p> This code is entirely different from my Arc version, mainly because in the Arc version I decided to see if the <code>throw/catch</code> idiom could replace <code>call/cc</code>; the Java code is much closer to the original Scheme. Because Java doesn't have first-class continuations, I used the <a href="https://en.wikipedia.org/wiki/Continuation-passing_style">Continuation-passing style</a> of explicitly passing continuations around. Then <code>call/cc</code> is simply replaced with use of the current continuation. <p> Because Java doesn't support first-class functions, every continuation function needs to be wrapped in a class that implements an interface, which I unimaginatively call <code>Continuation</code>. The "let" also turns into an object creation, resulting in another class. This results in a fair bit of boilerplate to handle all these classes compared to the Scheme code, but the Java code maps recognizably onto the Scheme code. <p> On the whole, mondo-bizarro worked better in Java than I expected; no Greenspunning required. It produces the expected 11213 output, proving it works. I think the Java code is actually easier to understand, since everything is explicit. <p> I have also found it entertaining to implement some of the complex <a href="https://www.amazon.com/gp/product/0262011530?ie=UTF8&tag=rightocom&linkCode=as2&camp=1789&creative=9325&creativeASIN=0262011530">SICP</a><img alt="" border="0" height="1" src="http://www.assoc-amazon.com/e/ir?t=rightocom&l=as2&o=1&a=0262011530" style="border:none !important; margin:0px !important;" width="1" /> exercises in Java; maybe I'll post details later. <p> (The title of this article is, of course, a homage to <a href="https://www.amazon.com/gp/redirect.html?ie=UTF8&location=http%3A%2F%2Fwww.amazon.com%2FMathematics-made-difficult-Carl-Linderholm%2Fdp%2F0529045524%3Fie%3DUTF8%26s%3Dbooks%26qid%3D1206593776%26sr%3D1-1&tag=rightocom&linkCode=ur2&camp=1789&creative=9325">Mathematics Made Difficult</a><img alt="" border="0" height="1" src="http://www.assoc-amazon.com/e/ir?t=rightocom&l=ur2&o=1" style="border:none !important; margin:0px !important;" width="1" />.) <p> Here's the code. <pre class="code"> /** * Mondo-Bizarro ported to Java. * Based on mondo-bizarro by Eugene Kohlbecker * ACM SIGPLAN Lisp Pointers, Volume 1, Issue 2 (June-July 1987) pp 22-28 */ /* Original Scheme code: (define mondo-bizarro (let ( (k (call/cc (lambda (c) c))) ) (write 1) (call/cc (lambda (c) (k c))) (write 2) (call/cc (lambda (c) (k c))) (write 3))) */ interface Continuation { public void run(Continuation c); } public class Mondo implements Continuation { public static void main(String argv[]) { Continuation c = new Mondo(); c.run(c); } public void run(Continuation c) { Continuation let = new Let(); let.run(c); } class Let implements Continuation { Continuation k; public void run(Continuation c) { k = c; System.out.println("1"); k.run(new C2()); } class C2 implements Continuation { public void run(Continuation c) { System.out.println("2"); k.run(new C3()); } } class C3 implements Continuation { public void run(Continuation c) { System.out.println("3"); } } } } </pre> </span> <span class="summarypost"> <p><a href="http://www.righto.com/2008/03/continuations-made-difficult.html">Continue reading...</a></span> <div style='clear: both;'></div> </div> <div class='post-footer'> <div 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/6264947694886887540/3133368973222586211' onclick=''> No comments: </a> </span> <span class='post-icons'> <span class='item-action'> <a href='https://www.blogger.com/email-post.g?blogID=6264947694886887540&postID=3133368973222586211' title='Email Post'> <img alt='' class='icon-action' height='13' src='http://img1.blogblog.com/img/icon18_email.gif' width='18'/> </a> </span> <span class='item-control blog-admin pid-1138732533'> <a href='https://www.blogger.com/post-edit.g?blogID=6264947694886887540&postID=3133368973222586211&from=pencil' title='Edit Post'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> <span class='post-backlinks post-comment-link'> </span> <div class='post-share-buttons goog-inline-block'> <a class='goog-inline-block share-button sb-email' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=3133368973222586211&target=email' target='_blank' title='Email This'><span class='share-button-link-text'>Email This</span></a><a class='goog-inline-block share-button sb-blog' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=3133368973222586211&target=blog' onclick='window.open(this.href, "_blank", "height=270,width=475"); return false;' target='_blank' title='BlogThis!'><span class='share-button-link-text'>BlogThis!</span></a><a class='goog-inline-block share-button sb-twitter' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=3133368973222586211&target=twitter' target='_blank' title='Share to X'><span class='share-button-link-text'>Share to X</span></a><a class='goog-inline-block share-button sb-facebook' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=3133368973222586211&target=facebook' onclick='window.open(this.href, "_blank", "height=430,width=640"); return false;' target='_blank' title='Share to Facebook'><span class='share-button-link-text'>Share to Facebook</span></a><a class='goog-inline-block share-button sb-pinterest' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=3133368973222586211&target=pinterest' target='_blank' title='Share to Pinterest'><span class='share-button-link-text'>Share to Pinterest</span></a> </div> </div> <div class='post-footer-line post-footer-line-2'><span class='post-labels'> Labels: <a href='http://www.righto.com/search/label/arc' rel='tag'>arc</a>, <a href='http://www.righto.com/search/label/java' rel='tag'>java</a>, <a href='http://www.righto.com/search/label/theory' rel='tag'>theory</a> </span> </div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> </div></div> <div class="date-outer"> <div class="date-posts"> <div class='post-outer'> <div class='post hentry' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='6264947694886887540' itemprop='blogId'/> <meta content='4918480718843356709' itemprop='postId'/> <a name='4918480718843356709'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='http://www.righto.com/2008/03/documentation-for-almost-all-of-arc.html'>Documentation for (almost) all of Arc</a> </h3> <div class='post-header'> <div class='post-header-line-1'></div> </div> <div class='post-body entry-content' id='post-body-4918480718843356709' itemprop='description articleBody'> I've got almost all of the Arc core <a href="http://files.arcfn.com/doc/index.html">documented</a> with an <a href="http://files.arcfn.com/doc/fnindex.html">alphabetical index</a>. I've covered ac.scm, arc.arc, strings.arc, but am currently omitting the web server and applications. <p> For each function, I include a description, examples, a link to the code, and a link to the wiki. I'll fill in a few gaps as time permits. I'll appreciate any feedback on the organization. <div style='clear: both;'></div> </div> <div class='post-footer'> <div 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/6264947694886887540/4918480718843356709' onclick=''> No comments: </a> </span> <span class='post-icons'> <span class='item-action'> <a href='https://www.blogger.com/email-post.g?blogID=6264947694886887540&postID=4918480718843356709' title='Email Post'> <img alt='' class='icon-action' height='13' src='http://img1.blogblog.com/img/icon18_email.gif' width='18'/> </a> </span> <span class='item-control blog-admin pid-1138732533'> <a href='https://www.blogger.com/post-edit.g?blogID=6264947694886887540&postID=4918480718843356709&from=pencil' title='Edit Post'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> <span class='post-backlinks post-comment-link'> </span> <div class='post-share-buttons goog-inline-block'> <a class='goog-inline-block share-button sb-email' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=4918480718843356709&target=email' target='_blank' title='Email This'><span class='share-button-link-text'>Email This</span></a><a class='goog-inline-block share-button sb-blog' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=4918480718843356709&target=blog' onclick='window.open(this.href, "_blank", "height=270,width=475"); return false;' target='_blank' title='BlogThis!'><span class='share-button-link-text'>BlogThis!</span></a><a class='goog-inline-block share-button sb-twitter' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=4918480718843356709&target=twitter' target='_blank' title='Share to X'><span class='share-button-link-text'>Share to X</span></a><a class='goog-inline-block share-button sb-facebook' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=4918480718843356709&target=facebook' onclick='window.open(this.href, "_blank", "height=430,width=640"); return false;' target='_blank' title='Share to Facebook'><span class='share-button-link-text'>Share to Facebook</span></a><a class='goog-inline-block share-button sb-pinterest' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=4918480718843356709&target=pinterest' target='_blank' title='Share to Pinterest'><span class='share-button-link-text'>Share to Pinterest</span></a> </div> </div> <div class='post-footer-line post-footer-line-2'><span class='post-labels'> Labels: <a href='http://www.righto.com/search/label/arc' rel='tag'>arc</a> </span> </div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> </div></div> <div class="date-outer"> <div class="date-posts"> <div class='post-outer'> <div class='post hentry' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='http://www.assoc-amazon.com/e/ir?t=rightocom&l=as2&o=1&a=0596006624' itemprop='image_url'/> <meta content='6264947694886887540' itemprop='blogId'/> <meta content='7506700292543050875' itemprop='postId'/> <a name='7506700292543050875'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='http://www.righto.com/2008/03/arc-popular-since-2004.html'>Arc: popular since 2004!</a> </h3> <div class='post-header'> <div class='post-header-line-1'></div> </div> <div class='post-body entry-content' id='post-body-7506700292543050875' itemprop='description articleBody'> Did you know that Arc has been a popular computer language since 2004? Pretty good for a language released in January 2008. I discovered Arc's longstanding popularity in <a href="http://www.computerworld.com/action/article.do?command=viewArticleBasic&articleId=94695&intsrc=article_pots_side">Computerworld's review</a> of Paul Graham's <a href="https://www.amazon.com/gp/product/0596006624?ie=UTF8&tag=rightocom&linkCode=as2&camp=1789&creative=9325&creativeASIN=0596006624">Hackers and Painters</a><img alt="" border="0" height="1" src="http://www.assoc-amazon.com/e/ir?t=rightocom&l=as2&o=1&a=0596006624" style="border:none !important; margin:0px !important;" width="1" />. The review from July 2004 says, "Paul Graham, well known for developing the popular Arc computer language and other Internet technologies...". I guess they didn't realize Arc hadn't been released at the time. Hopefully we won't see them publishing job listings looking for 4 years of Arc experience. <script type="text/javascript" src="http://www.assoc-amazon.com/s/link-enhancer?tag=rightocom&o=1"> </script> <noscript> <img alt="" src="http://www.assoc-amazon.com/s/noscript?tag=rightocom" /> </noscript> <div style='clear: both;'></div> </div> <div class='post-footer'> <div 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/6264947694886887540/7506700292543050875' onclick=''> No comments: </a> </span> <span class='post-icons'> <span class='item-action'> <a href='https://www.blogger.com/email-post.g?blogID=6264947694886887540&postID=7506700292543050875' title='Email Post'> <img alt='' class='icon-action' height='13' src='http://img1.blogblog.com/img/icon18_email.gif' width='18'/> </a> </span> <span class='item-control blog-admin pid-1138732533'> <a href='https://www.blogger.com/post-edit.g?blogID=6264947694886887540&postID=7506700292543050875&from=pencil' title='Edit Post'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> <span class='post-backlinks post-comment-link'> </span> <div class='post-share-buttons goog-inline-block'> <a class='goog-inline-block share-button sb-email' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=7506700292543050875&target=email' target='_blank' title='Email This'><span class='share-button-link-text'>Email This</span></a><a class='goog-inline-block share-button sb-blog' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=7506700292543050875&target=blog' onclick='window.open(this.href, "_blank", "height=270,width=475"); return false;' target='_blank' title='BlogThis!'><span class='share-button-link-text'>BlogThis!</span></a><a class='goog-inline-block share-button sb-twitter' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=7506700292543050875&target=twitter' target='_blank' title='Share to X'><span class='share-button-link-text'>Share to X</span></a><a class='goog-inline-block share-button sb-facebook' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=7506700292543050875&target=facebook' onclick='window.open(this.href, "_blank", "height=430,width=640"); return false;' target='_blank' title='Share to Facebook'><span class='share-button-link-text'>Share to Facebook</span></a><a class='goog-inline-block share-button sb-pinterest' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=7506700292543050875&target=pinterest' target='_blank' title='Share to Pinterest'><span class='share-button-link-text'>Share to Pinterest</span></a> </div> </div> <div class='post-footer-line post-footer-line-2'><span class='post-labels'> Labels: <a href='http://www.righto.com/search/label/arc' rel='tag'>arc</a>, <a href='http://www.righto.com/search/label/random' rel='tag'>random</a> </span> </div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> </div></div> <div class="date-outer"> <div class="date-posts"> <div class='post-outer'> <div class='post hentry' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='6264947694886887540' itemprop='blogId'/> <meta content='5452151721173487652' itemprop='postId'/> <a name='5452151721173487652'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='http://www.righto.com/2008/03/what-does-even-tried-multi-mean.html'>"Even tried multi" error explained</a> </h3> <div class='post-header'> <div class='post-header-line-1'></div> </div> <div class='post-body entry-content' id='post-body-5452151721173487652' itemprop='description articleBody'> If you were around during the early days of the web, you surely remember the message <br><code>Error 404 Not found - file doesn't exist or is read protected [even tried multi]</code> <br>But what is "multi"? And why does the web server act like it's doing you a big favor trying it? Is it trying multiple times, maybe? <p> <span class="fullpost"> These days, 404 messages are still common, but the "multi" message is <a href="http://www.boulderchamber.com/100aniv">fairly</a> <a href="http://www.oapi.wipo.net/en/index.html">rare</a>. The message was once so common, though, it spawned a <a href="http://users.softlab.ece.ntua.gr/~sivann/pub/swf/may02-smilepop-soapbox4swf">large</a> <a href="http://www.modedaria.com/">number</a> <a href="http://www.geocities.com/Athens/5894/where.htm">of</a> <a href="http://pages.cs.wisc.edu/~veeve/404.html">parodies</a>. <p> I decided to get to the bottom of this, and find out what this "multi" is. It didn't take long to discover that this message comes from the CERN httpd server, written by Tim Berners-Lee and others back in the 1990's. <p> A bit of poking around found the <a href="http://www.w3.org/Daemon/Implementation/HTAAServ.c">source code</a> that generates the infamous multi message. It turns out that "multi" is short for <a href="http://www.w3.org/News/9305.html#z23">multi-format documents</a>, and was a cool new feature back in 1993. It is a technique for the server to have multiple formats of a file and provides the best one your browser can handle. For instance, suppose you try to fetch an image <code>/cat</code>. Back in the olden days, browsers weren't so good with images, so your browser might only display gifs and not jpegs. Your browser asks for <code>/cat</code> and says that it can handle gifs. Now for the multi magic. The server can have multiple files, say <code>/cat.gif</code>, <code>/cat.jpg</code>, and <code>/cat.png</code>. It looks at what your browser can accept, looks at what it has, and returns the best choice, in this case <code>/cat.gif</code>. Likewise, a file could have versions in text and PDF, and the server would return the best type for your browser. Web servers still support <a href="http://httpd.apache.org/docs/1.3/content-negotiation.html">content negotiation</a>, but they generally don't mention it in 404 messages any more. <p> So there you have it, the definitive answer to what "even tried multi" means, and a bit of web history. </span> <div style='clear: both;'></div> </div> <div class='post-footer'> <div 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/6264947694886887540/5452151721173487652' onclick=''> No comments: </a> </span> <span class='post-icons'> <span class='item-action'> <a href='https://www.blogger.com/email-post.g?blogID=6264947694886887540&postID=5452151721173487652' title='Email Post'> <img alt='' class='icon-action' height='13' src='http://img1.blogblog.com/img/icon18_email.gif' width='18'/> </a> </span> <span class='item-control blog-admin pid-1138732533'> <a href='https://www.blogger.com/post-edit.g?blogID=6264947694886887540&postID=5452151721173487652&from=pencil' title='Edit Post'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> <span class='post-backlinks post-comment-link'> </span> <div class='post-share-buttons goog-inline-block'> <a class='goog-inline-block share-button sb-email' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=5452151721173487652&target=email' target='_blank' title='Email This'><span class='share-button-link-text'>Email This</span></a><a class='goog-inline-block share-button sb-blog' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=5452151721173487652&target=blog' onclick='window.open(this.href, "_blank", "height=270,width=475"); return false;' target='_blank' title='BlogThis!'><span class='share-button-link-text'>BlogThis!</span></a><a class='goog-inline-block share-button sb-twitter' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=5452151721173487652&target=twitter' target='_blank' title='Share to X'><span class='share-button-link-text'>Share to X</span></a><a class='goog-inline-block share-button sb-facebook' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=5452151721173487652&target=facebook' onclick='window.open(this.href, "_blank", "height=430,width=640"); return false;' target='_blank' title='Share to Facebook'><span class='share-button-link-text'>Share to Facebook</span></a><a class='goog-inline-block share-button sb-pinterest' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=5452151721173487652&target=pinterest' target='_blank' title='Share to Pinterest'><span class='share-button-link-text'>Share to Pinterest</span></a> </div> </div> <div class='post-footer-line post-footer-line-2'><span class='post-labels'> Labels: <a href='http://www.righto.com/search/label/random' rel='tag'>random</a> </span> </div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> <div class='post-outer'> <div class='post hentry' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='6264947694886887540' itemprop='blogId'/> <meta content='6598459170948537627' itemprop='postId'/> <a name='6598459170948537627'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='http://www.righto.com/2008/03/arc-continuation-puzzle.html'>Arc continuation puzzle</a> </h3> <div class='post-header'> <div class='post-header-line-1'></div> </div> <div class='post-body entry-content' id='post-body-6598459170948537627' itemprop='description articleBody'> In case anyone thinks continuations are straightforward, I've ported Eugene Kohlbecker's classic Scheme puzzle to Arc. What does <code>(mondo-bizarro)</code> print? <pre class="code"> (def mondo-bizarro () (let k (catch throw) (pr 1) (catch (k throw)) (pr 2) (catch (k throw)) (pr 3)) nil) </pre> Reference: ACM SIGPLAN Lisp Pointers, Volume 1, Issue 2 (June-July 1987) <a href="http://doi.acm.org/10.1145/1317193.1317197">pp 22-28</a>. <div style='clear: both;'></div> </div> <div class='post-footer'> <div 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/6264947694886887540/6598459170948537627' onclick=''> 1 comment: </a> </span> <span class='post-icons'> <span class='item-action'> <a href='https://www.blogger.com/email-post.g?blogID=6264947694886887540&postID=6598459170948537627' title='Email Post'> <img alt='' class='icon-action' height='13' src='http://img1.blogblog.com/img/icon18_email.gif' width='18'/> </a> </span> <span class='item-control blog-admin pid-1138732533'> <a href='https://www.blogger.com/post-edit.g?blogID=6264947694886887540&postID=6598459170948537627&from=pencil' title='Edit Post'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> <span class='post-backlinks post-comment-link'> </span> <div class='post-share-buttons goog-inline-block'> <a class='goog-inline-block share-button sb-email' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=6598459170948537627&target=email' target='_blank' title='Email This'><span class='share-button-link-text'>Email This</span></a><a class='goog-inline-block share-button sb-blog' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=6598459170948537627&target=blog' onclick='window.open(this.href, "_blank", "height=270,width=475"); return false;' target='_blank' title='BlogThis!'><span class='share-button-link-text'>BlogThis!</span></a><a class='goog-inline-block share-button sb-twitter' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=6598459170948537627&target=twitter' target='_blank' title='Share to X'><span class='share-button-link-text'>Share to X</span></a><a class='goog-inline-block share-button sb-facebook' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=6598459170948537627&target=facebook' onclick='window.open(this.href, "_blank", "height=430,width=640"); return false;' target='_blank' title='Share to Facebook'><span class='share-button-link-text'>Share to Facebook</span></a><a class='goog-inline-block share-button sb-pinterest' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=6598459170948537627&target=pinterest' target='_blank' title='Share to Pinterest'><span class='share-button-link-text'>Share to Pinterest</span></a> </div> </div> <div class='post-footer-line post-footer-line-2'><span class='post-labels'> Labels: <a href='http://www.righto.com/search/label/arc' rel='tag'>arc</a>, <a href='http://www.righto.com/search/label/random' rel='tag'>random</a> </span> </div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> </div></div> <div class="date-outer"> <div class="date-posts"> <div class='post-outer'> <div class='post hentry' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='6264947694886887540' itemprop='blogId'/> <meta content='582267545183970341' itemprop='postId'/> <a name='582267545183970341'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='http://www.righto.com/2008/03/lots-more-documentation.html'>Lots more documentation</a> </h3> <div class='post-header'> <div class='post-header-line-1'></div> </div> <div class='post-body entry-content' id='post-body-582267545183970341' itemprop='description articleBody'> I've added lots more <a href="/doc">documentation</a> on the Arc language: filesystem manipulation, anaphoric operations, iteration, threading, time operations, queues, and trees. <div style='clear: both;'></div> </div> <div class='post-footer'> <div 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/6264947694886887540/582267545183970341' onclick=''> 1 comment: </a> </span> <span class='post-icons'> <span class='item-action'> <a href='https://www.blogger.com/email-post.g?blogID=6264947694886887540&postID=582267545183970341' title='Email Post'> <img alt='' class='icon-action' height='13' src='http://img1.blogblog.com/img/icon18_email.gif' width='18'/> </a> </span> <span class='item-control blog-admin pid-1138732533'> <a href='https://www.blogger.com/post-edit.g?blogID=6264947694886887540&postID=582267545183970341&from=pencil' title='Edit Post'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> <span class='post-backlinks post-comment-link'> </span> <div class='post-share-buttons goog-inline-block'> <a class='goog-inline-block share-button sb-email' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=582267545183970341&target=email' target='_blank' title='Email This'><span class='share-button-link-text'>Email This</span></a><a class='goog-inline-block share-button sb-blog' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=582267545183970341&target=blog' onclick='window.open(this.href, "_blank", "height=270,width=475"); return false;' target='_blank' title='BlogThis!'><span class='share-button-link-text'>BlogThis!</span></a><a class='goog-inline-block share-button sb-twitter' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=582267545183970341&target=twitter' target='_blank' title='Share to X'><span class='share-button-link-text'>Share to X</span></a><a class='goog-inline-block share-button sb-facebook' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=582267545183970341&target=facebook' onclick='window.open(this.href, "_blank", "height=430,width=640"); return false;' target='_blank' title='Share to Facebook'><span class='share-button-link-text'>Share to Facebook</span></a><a class='goog-inline-block share-button sb-pinterest' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=582267545183970341&target=pinterest' target='_blank' title='Share to Pinterest'><span class='share-button-link-text'>Share to Pinterest</span></a> </div> </div> <div class='post-footer-line post-footer-line-2'><span class='post-labels'> Labels: <a href='http://www.righto.com/search/label/arc' rel='tag'>arc</a> </span> </div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> </div></div> <div class="date-outer"> <div class="date-posts"> <div class='post-outer'> <div class='post hentry' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='6264947694886887540' itemprop='blogId'/> <meta content='8696542424548303601' itemprop='postId'/> <a name='8696542424548303601'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='http://www.righto.com/2008/03/io-in-arc-language.html'>I/O in the Arc language</a> </h3> <div class='post-header'> <div class='post-header-line-1'></div> </div> <div class='post-body entry-content' id='post-body-8696542424548303601' itemprop='description articleBody'> The Arc language provides many I/O operations. I have written an overview of them: <a href="http://www.righto.com/doc/io.html">I/O in the Arc language</a>. This covers file I/O, string I/O, and the many operations to perform reads and writes. The operations strike me as very non-orthogonal; it's unpredictable which ones take ports, have defaults, or specify an eof value. I try to bring some organization to them. <div style='clear: both;'></div> </div> <div class='post-footer'> <div 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/6264947694886887540/8696542424548303601' onclick=''> No comments: </a> </span> <span class='post-icons'> <span class='item-action'> <a href='https://www.blogger.com/email-post.g?blogID=6264947694886887540&postID=8696542424548303601' title='Email Post'> <img alt='' class='icon-action' height='13' src='http://img1.blogblog.com/img/icon18_email.gif' width='18'/> </a> </span> <span class='item-control blog-admin pid-1138732533'> <a href='https://www.blogger.com/post-edit.g?blogID=6264947694886887540&postID=8696542424548303601&from=pencil' title='Edit Post'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> <span class='post-backlinks post-comment-link'> </span> <div class='post-share-buttons goog-inline-block'> <a class='goog-inline-block share-button sb-email' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=8696542424548303601&target=email' target='_blank' title='Email This'><span class='share-button-link-text'>Email This</span></a><a class='goog-inline-block share-button sb-blog' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=8696542424548303601&target=blog' onclick='window.open(this.href, "_blank", "height=270,width=475"); return false;' target='_blank' title='BlogThis!'><span class='share-button-link-text'>BlogThis!</span></a><a class='goog-inline-block share-button sb-twitter' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=8696542424548303601&target=twitter' target='_blank' title='Share to X'><span class='share-button-link-text'>Share to X</span></a><a class='goog-inline-block share-button sb-facebook' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=8696542424548303601&target=facebook' onclick='window.open(this.href, "_blank", "height=430,width=640"); return false;' target='_blank' title='Share to Facebook'><span class='share-button-link-text'>Share to Facebook</span></a><a class='goog-inline-block share-button sb-pinterest' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=8696542424548303601&target=pinterest' target='_blank' title='Share to Pinterest'><span class='share-button-link-text'>Share to Pinterest</span></a> </div> </div> <div class='post-footer-line post-footer-line-2'><span class='post-labels'> Labels: <a href='http://www.righto.com/search/label/arc' rel='tag'>arc</a> </span> </div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> </div></div> <div class="date-outer"> <div class="date-posts"> <div class='post-outer'> <div class='post hentry' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='6264947694886887540' itemprop='blogId'/> <meta content='7106732843025455508' itemprop='postId'/> <a name='7106732843025455508'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='http://www.righto.com/2008/03/internals-of-places-and-setforms.html'>Internals of places and setforms</a> </h3> <div class='post-header'> <div class='post-header-line-1'></div> </div> <div class='post-body entry-content' id='post-body-7106732843025455508' itemprop='description articleBody'> The documentation continues with <a href="http://www.righto.com/doc/setforms.html">Internals of places and setforms</a>. This continues where the assignment and places documentation left off. If you want to know how to create your own places and generalized variables in Arc, you're in luck. <div style='clear: both;'></div> </div> <div class='post-footer'> <div 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/6264947694886887540/7106732843025455508' onclick=''> No comments: </a> </span> <span class='post-icons'> <span class='item-action'> <a href='https://www.blogger.com/email-post.g?blogID=6264947694886887540&postID=7106732843025455508' title='Email Post'> <img alt='' class='icon-action' height='13' src='http://img1.blogblog.com/img/icon18_email.gif' width='18'/> </a> </span> <span class='item-control blog-admin pid-1138732533'> <a href='https://www.blogger.com/post-edit.g?blogID=6264947694886887540&postID=7106732843025455508&from=pencil' title='Edit Post'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> <span class='post-backlinks post-comment-link'> </span> <div class='post-share-buttons goog-inline-block'> <a class='goog-inline-block share-button sb-email' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=7106732843025455508&target=email' target='_blank' title='Email This'><span class='share-button-link-text'>Email This</span></a><a class='goog-inline-block share-button sb-blog' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=7106732843025455508&target=blog' onclick='window.open(this.href, "_blank", "height=270,width=475"); return false;' target='_blank' title='BlogThis!'><span class='share-button-link-text'>BlogThis!</span></a><a class='goog-inline-block share-button sb-twitter' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=7106732843025455508&target=twitter' target='_blank' title='Share to X'><span class='share-button-link-text'>Share to X</span></a><a class='goog-inline-block share-button sb-facebook' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=7106732843025455508&target=facebook' onclick='window.open(this.href, "_blank", "height=430,width=640"); return false;' target='_blank' title='Share to Facebook'><span class='share-button-link-text'>Share to Facebook</span></a><a class='goog-inline-block share-button sb-pinterest' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=7106732843025455508&target=pinterest' target='_blank' title='Share to Pinterest'><span class='share-button-link-text'>Share to Pinterest</span></a> </div> </div> <div class='post-footer-line post-footer-line-2'><span class='post-labels'> Labels: <a href='http://www.righto.com/search/label/arc' rel='tag'>arc</a> </span> </div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> </div></div> <div class="date-outer"> <div class="date-posts"> <div class='post-outer'> <div class='post hentry' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='6264947694886887540' itemprop='blogId'/> <meta content='348414950140378745' itemprop='postId'/> <a name='348414950140378745'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='http://www.righto.com/2008/03/arc-documentation-table-of-contents.html'>Arc documentation table of contents</a> </h3> <div class='post-header'> <div class='post-header-line-1'></div> </div> <div class='post-body entry-content' id='post-body-348414950140378745' itemprop='description articleBody'> I've created a <a href="doc/index.html">table of contents</a> summarizing my documentation on the Arc language. (By request, it's now on the sidebar too.) <div style='clear: both;'></div> </div> <div class='post-footer'> <div 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/6264947694886887540/348414950140378745' onclick=''> 1 comment: </a> </span> <span class='post-icons'> <span class='item-action'> <a href='https://www.blogger.com/email-post.g?blogID=6264947694886887540&postID=348414950140378745' title='Email Post'> <img alt='' class='icon-action' height='13' src='http://img1.blogblog.com/img/icon18_email.gif' width='18'/> </a> </span> <span class='item-control blog-admin pid-1138732533'> <a href='https://www.blogger.com/post-edit.g?blogID=6264947694886887540&postID=348414950140378745&from=pencil' title='Edit Post'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> <span class='post-backlinks post-comment-link'> </span> <div class='post-share-buttons goog-inline-block'> <a class='goog-inline-block share-button sb-email' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=348414950140378745&target=email' target='_blank' title='Email This'><span class='share-button-link-text'>Email This</span></a><a class='goog-inline-block share-button sb-blog' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=348414950140378745&target=blog' onclick='window.open(this.href, "_blank", "height=270,width=475"); return false;' target='_blank' title='BlogThis!'><span class='share-button-link-text'>BlogThis!</span></a><a class='goog-inline-block share-button sb-twitter' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=348414950140378745&target=twitter' target='_blank' title='Share to X'><span class='share-button-link-text'>Share to X</span></a><a class='goog-inline-block share-button sb-facebook' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=348414950140378745&target=facebook' onclick='window.open(this.href, "_blank", "height=430,width=640"); return false;' target='_blank' title='Share to Facebook'><span class='share-button-link-text'>Share to Facebook</span></a><a class='goog-inline-block share-button sb-pinterest' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=348414950140378745&target=pinterest' target='_blank' title='Share to Pinterest'><span class='share-button-link-text'>Share to Pinterest</span></a> </div> </div> <div class='post-footer-line post-footer-line-2'><span class='post-labels'> Labels: <a href='http://www.righto.com/search/label/arc' rel='tag'>arc</a> </span> </div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> </div></div> <div class="date-outer"> <div class="date-posts"> <div class='post-outer'> <div class='post hentry' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='6264947694886887540' itemprop='blogId'/> <meta content='5499015644686398752' itemprop='postId'/> <a name='5499015644686398752'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='http://www.righto.com/2008/03/arc-assignment-and-places-documentation.html'>Arc assignment and places documentation</a> </h3> <div class='post-header'> <div class='post-header-line-1'></div> </div> <div class='post-body entry-content' id='post-body-5499015644686398752' itemprop='description articleBody'> As part of my Arc language documentation series. I've created a page on <a href="/doc/assignment.html">assignment and places in Arc</a> <div style='clear: both;'></div> </div> <div class='post-footer'> <div 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/6264947694886887540/5499015644686398752' onclick=''> 1 comment: </a> </span> <span class='post-icons'> <span class='item-action'> <a href='https://www.blogger.com/email-post.g?blogID=6264947694886887540&postID=5499015644686398752' title='Email Post'> <img alt='' class='icon-action' height='13' src='http://img1.blogblog.com/img/icon18_email.gif' width='18'/> </a> </span> <span class='item-control blog-admin pid-1138732533'> <a href='https://www.blogger.com/post-edit.g?blogID=6264947694886887540&postID=5499015644686398752&from=pencil' title='Edit Post'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> <span class='post-backlinks post-comment-link'> </span> <div class='post-share-buttons goog-inline-block'> <a class='goog-inline-block share-button sb-email' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=5499015644686398752&target=email' target='_blank' title='Email This'><span class='share-button-link-text'>Email This</span></a><a class='goog-inline-block share-button sb-blog' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=5499015644686398752&target=blog' onclick='window.open(this.href, "_blank", "height=270,width=475"); return false;' target='_blank' title='BlogThis!'><span class='share-button-link-text'>BlogThis!</span></a><a class='goog-inline-block share-button sb-twitter' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=5499015644686398752&target=twitter' target='_blank' title='Share to X'><span class='share-button-link-text'>Share to X</span></a><a class='goog-inline-block share-button sb-facebook' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=5499015644686398752&target=facebook' onclick='window.open(this.href, "_blank", "height=430,width=640"); return false;' target='_blank' title='Share to Facebook'><span class='share-button-link-text'>Share to Facebook</span></a><a class='goog-inline-block share-button sb-pinterest' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=5499015644686398752&target=pinterest' target='_blank' title='Share to Pinterest'><span class='share-button-link-text'>Share to Pinterest</span></a> </div> </div> <div class='post-footer-line post-footer-line-2'><span class='post-labels'> Labels: <a href='http://www.righto.com/search/label/arc' rel='tag'>arc</a> </span> </div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> </div></div> <div class="date-outer"> <div class="date-posts"> <div class='post-outer'> <div class='post hentry' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='6264947694886887540' itemprop='blogId'/> <meta content='3515610693993359758' itemprop='postId'/> <a name='3515610693993359758'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='http://www.righto.com/2008/02/arc-internals-part-2-macros.html'>Arc internals part 2: Macros</a> </h3> <div class='post-header'> <div class='post-header-line-1'></div> </div> <div class='post-body entry-content' id='post-body-3515610693993359758' itemprop='description articleBody'> I've written a document on the internals of <a href="http://www.righto.com/doc/macros.html">Arc's macro implementation</a>. It continues where <a href="http://www.righto.com/2008/02/arc-internals-part-1.html">Arc internals part 1</a> left off. <div style='clear: both;'></div> </div> <div class='post-footer'> <div 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/6264947694886887540/3515610693993359758' onclick=''> No comments: </a> </span> <span class='post-icons'> <span class='item-action'> <a href='https://www.blogger.com/email-post.g?blogID=6264947694886887540&postID=3515610693993359758' title='Email Post'> <img alt='' class='icon-action' height='13' src='http://img1.blogblog.com/img/icon18_email.gif' width='18'/> </a> </span> <span class='item-control blog-admin pid-1138732533'> <a href='https://www.blogger.com/post-edit.g?blogID=6264947694886887540&postID=3515610693993359758&from=pencil' title='Edit Post'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> <span class='post-backlinks post-comment-link'> </span> <div class='post-share-buttons goog-inline-block'> <a class='goog-inline-block share-button sb-email' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=3515610693993359758&target=email' target='_blank' title='Email This'><span class='share-button-link-text'>Email This</span></a><a class='goog-inline-block share-button sb-blog' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=3515610693993359758&target=blog' onclick='window.open(this.href, "_blank", "height=270,width=475"); return false;' target='_blank' title='BlogThis!'><span class='share-button-link-text'>BlogThis!</span></a><a class='goog-inline-block share-button sb-twitter' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=3515610693993359758&target=twitter' target='_blank' title='Share to X'><span class='share-button-link-text'>Share to X</span></a><a class='goog-inline-block share-button sb-facebook' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=3515610693993359758&target=facebook' onclick='window.open(this.href, "_blank", "height=430,width=640"); return false;' target='_blank' title='Share to Facebook'><span class='share-button-link-text'>Share to Facebook</span></a><a class='goog-inline-block share-button sb-pinterest' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=3515610693993359758&target=pinterest' target='_blank' title='Share to Pinterest'><span class='share-button-link-text'>Share to Pinterest</span></a> </div> </div> <div class='post-footer-line post-footer-line-2'><span class='post-labels'> Labels: <a href='http://www.righto.com/search/label/arc' rel='tag'>arc</a> </span> </div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> </div></div> <div class="date-outer"> <div class="date-posts"> <div class='post-outer'> <div class='post hentry' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='6264947694886887540' itemprop='blogId'/> <meta content='7133229858771497210' itemprop='postId'/> <a name='7133229858771497210'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='http://www.righto.com/2008/02/arc-template-documentation.html'>Arc template documentation</a> </h3> <div class='post-header'> <div class='post-header-line-1'></div> </div> <div class='post-body entry-content' id='post-body-7133229858771497210' itemprop='description articleBody'> I've created some documentation on <a href="http://www.righto.com/doc/template.html">Arc's template data structure</a>. <div style='clear: both;'></div> </div> <div class='post-footer'> <div 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/6264947694886887540/7133229858771497210' onclick=''> 1 comment: </a> </span> <span class='post-icons'> <span class='item-action'> <a href='https://www.blogger.com/email-post.g?blogID=6264947694886887540&postID=7133229858771497210' title='Email Post'> <img alt='' class='icon-action' height='13' src='http://img1.blogblog.com/img/icon18_email.gif' width='18'/> </a> </span> <span class='item-control blog-admin pid-1138732533'> <a href='https://www.blogger.com/post-edit.g?blogID=6264947694886887540&postID=7133229858771497210&from=pencil' title='Edit Post'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> <span class='post-backlinks post-comment-link'> </span> <div class='post-share-buttons goog-inline-block'> <a class='goog-inline-block share-button sb-email' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=7133229858771497210&target=email' target='_blank' title='Email This'><span class='share-button-link-text'>Email This</span></a><a class='goog-inline-block share-button sb-blog' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=7133229858771497210&target=blog' onclick='window.open(this.href, "_blank", "height=270,width=475"); return false;' target='_blank' title='BlogThis!'><span class='share-button-link-text'>BlogThis!</span></a><a class='goog-inline-block share-button sb-twitter' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=7133229858771497210&target=twitter' target='_blank' title='Share to X'><span class='share-button-link-text'>Share to X</span></a><a class='goog-inline-block share-button sb-facebook' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=7133229858771497210&target=facebook' onclick='window.open(this.href, "_blank", "height=430,width=640"); return false;' target='_blank' title='Share to Facebook'><span class='share-button-link-text'>Share to Facebook</span></a><a class='goog-inline-block share-button sb-pinterest' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=7133229858771497210&target=pinterest' target='_blank' title='Share to Pinterest'><span class='share-button-link-text'>Share to Pinterest</span></a> </div> </div> <div class='post-footer-line post-footer-line-2'><span class='post-labels'> Labels: <a href='http://www.righto.com/search/label/arc' rel='tag'>arc</a> </span> </div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> </div></div> <div class="date-outer"> <div class="date-posts"> <div class='post-outer'> <div class='post hentry' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='6264947694886887540' itemprop='blogId'/> <meta content='5674426443324232400' itemprop='postId'/> <a name='5674426443324232400'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='http://www.righto.com/2008/02/git-and-anarki-arc-repository-brief.html'>Git and the Anarki Arc repository: a brief guide</a> </h3> <div class='post-header'> <div class='post-header-line-1'></div> </div> <div class='post-body entry-content' id='post-body-5674426443324232400' itemprop='description articleBody'> The official releases of Arc are at <a href="http://arclanguage.org/install">arclanguage.org</a>. However, a group of enthusiasts has their own repository of Arc, called Anarki. This repository has versions of the Arc files with bug fixes, documentation, and extended functionality. The repository also contains additional features, documentation, applications, and Emacs tools. <p> The Anarki repository is stored in a source control system called <a href="http://git.or.cz">git</a>. The repository is open for access and updates by Arc users. Accessing the repository is straightforward, and will be described below. Submitting changes to the repository is not much harder, but is beyond the scope of this document; one source of information is on <a href="http://arclanguage.org/item?id=1387">arclanguage.org</a>. <p> The repository is promptly updated when a new version of Arc is released. Most of the changes in the repository haven't been migrated back to the official Arc releases, so there is considerable divergence between the official Arc version and the Anarki version. <h3>Installing git on Linux</h3> On Linux, git is in the "git-core" package. You can install this with "sudo apt-get git-core" on Ubuntu, or "sudo yum install git-core" on Red Hat. <h3>Installing git on Windows</h3> On Windows, one option is Git on MSys, which can be downloaded from the <a href="https://code.google.com/p/msysgit/">msysgit</a> site, under "Featured Downloads". <h3>Using git to fetch Anarki</h3> Once git is installed, fetching the repository is surprisingly easy. Run "git clone git://github.com/nex3/arc.git", which will create a directory "arc-wiki" containing a copy of the repository. To get updates from the repository, run "git pull". <h3>Browsing Anarki without git</h3> You can browse the repository directly by going to <a href="https://github.com/nex3/arc/tree/master">http://github.com/nex3/arc/tree/master</a>. To view a file, click on the filename. <p> Once you've downloaded Anarki, you can see the cutting edge of Arc modifications. One of the most interesting features of the Anarki version is docstrings: "(help map)" will display documentation on the map function, for instance. <h3>The stable Anarki branch</h3> A "stable" Anarki branch has also been created. This repository is close to the official Arc release, but with bug fixes and minimal new features. The stable repository lacks the experimental features and rapid changes of the regular repository. <p> To use the stable repository, check out Anarki as described above. Then run "git branch stable origin/stable" and "git checkout stable". All the experimental files and directories will disappear, and you will be left with the stable branch. For more information, see the <a href="http://arclanguage.org/item?id=3849">arclanguage forum</a>. <h3>The Arc-to-C compiler</h3> An Arc to C compiler is being developed in a separate repository: <code>git://github.com/sacado/arc2c.git</code>, which can be accessed on the web at <a href="https://github.com/sacado/arc2c/tree/master">http://github.com/sacado/arc2c/tree/master</a>. <div style='clear: both;'></div> </div> <div class='post-footer'> <div 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/6264947694886887540/5674426443324232400' onclick=''> 2 comments: </a> </span> <span class='post-icons'> <span class='item-action'> <a href='https://www.blogger.com/email-post.g?blogID=6264947694886887540&postID=5674426443324232400' title='Email Post'> <img alt='' class='icon-action' height='13' src='http://img1.blogblog.com/img/icon18_email.gif' width='18'/> </a> </span> <span class='item-control blog-admin pid-1138732533'> <a href='https://www.blogger.com/post-edit.g?blogID=6264947694886887540&postID=5674426443324232400&from=pencil' title='Edit Post'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> <span class='post-backlinks post-comment-link'> </span> <div class='post-share-buttons goog-inline-block'> <a class='goog-inline-block share-button sb-email' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=5674426443324232400&target=email' target='_blank' title='Email This'><span class='share-button-link-text'>Email This</span></a><a class='goog-inline-block share-button sb-blog' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=5674426443324232400&target=blog' onclick='window.open(this.href, "_blank", "height=270,width=475"); return false;' target='_blank' title='BlogThis!'><span class='share-button-link-text'>BlogThis!</span></a><a class='goog-inline-block share-button sb-twitter' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=5674426443324232400&target=twitter' target='_blank' title='Share to X'><span class='share-button-link-text'>Share to X</span></a><a class='goog-inline-block share-button sb-facebook' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=5674426443324232400&target=facebook' onclick='window.open(this.href, "_blank", "height=430,width=640"); return false;' target='_blank' title='Share to Facebook'><span class='share-button-link-text'>Share to Facebook</span></a><a class='goog-inline-block share-button sb-pinterest' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=5674426443324232400&target=pinterest' target='_blank' title='Share to Pinterest'><span class='share-button-link-text'>Share to Pinterest</span></a> </div> </div> <div class='post-footer-line post-footer-line-2'><span class='post-labels'> Labels: <a href='http://www.righto.com/search/label/arc' rel='tag'>arc</a> </span> </div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> </div></div> <div class="date-outer"> <div class="date-posts"> <div class='post-outer'> <div class='post hentry' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='6264947694886887540' itemprop='blogId'/> <meta content='8907727528910092398' itemprop='postId'/> <a name='8907727528910092398'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='http://www.righto.com/2008/02/whats-new-in-arc2.html'>What's new in arc2</a> </h3> <div class='post-header'> <div class='post-header-line-1'></div> </div> <div class='post-body entry-content' id='post-body-8907727528910092398' itemprop='description articleBody'> I took a look at the new version of arc that has been <a href="http://arclanguage.org/item?id=3426">released</a>. The following are my unofficial notes on the differences between arc1 and arc2. <h3>News.YC release</h3> The key difference is the release of the News.YC source in news.arc. This 1769-line file apparently provides the full implementation of <a href="http://news.ycombinator.com">news.ycombinator.com</a>. One interesting thing is that stories are ranked according to (score-1) / (age-in-hours ^ gravity), where gravity is 1.4 by default. <p> There are also some gifs to support the site. The following is a list of the new files in arc2: <ul><li>news.arc: the source for news.ycombinator.com. <li>grayarrow.gif: gray uparrow <li>graydown.gif: gray downarrow <li>s.gif: 1x1 transparent spacer <li>y18.gif: 1x1 spacer (same as s.gif) </ul> Other files have minor changes: <h3>ac.scm</h3> <ul><li>arc-list? fix for '() <li>write, disp cleanup </ul> <h3>app.arc</h3> <ul><li>Renamed when-usermatch to when-umatch, when-usermatchr to when-umatch/r, matchform to uform. <li>Removed pw from good-login record. </ul> <h3>arc.arc</h3> <ul><li>(firstn nil xs) now returns xs <li>(nthcdr nil xs) now returns xs <li>trav renamed to treewise <li>New function union on sequences. <li>New function addtem to create a template. <li>New functions hours-since and days-since. <li>ensure-dir fix. <li>Function only is now entirely different. Wraps a function to only call it if given args. <li>Function plural moved to strings.arc. Now if w/bars were moved too... <li>New function trav: takes an object and functions. Applies the functions to the object. <li>New function defhook and hook to register and execute functions? </ul> <h3>html.arc</h3> <ul><li>Added orange as a color. <li>para now takes arguments. <li>Removed image-url and local-images* <li>spacetable renamed to sptab. <li>Added single-input and cdata. </ul> <h3>libs.arc</h3> <ul><li>Added news.arc. </ul> <h3>srv.arc</h3> <ul><li>Remove "frug" default account. <li>Excludes .arc as a static filetype, to hide source. </ul> <h3>strings.arc</h3> <ul><li>plural function moved here from arc.arc. </ul> <div style='clear: both;'></div> </div> <div class='post-footer'> <div 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/6264947694886887540/8907727528910092398' onclick=''> No comments: </a> </span> <span class='post-icons'> <span class='item-action'> <a href='https://www.blogger.com/email-post.g?blogID=6264947694886887540&postID=8907727528910092398' title='Email Post'> <img alt='' class='icon-action' height='13' src='http://img1.blogblog.com/img/icon18_email.gif' width='18'/> </a> </span> <span class='item-control blog-admin pid-1138732533'> <a href='https://www.blogger.com/post-edit.g?blogID=6264947694886887540&postID=8907727528910092398&from=pencil' title='Edit Post'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> <span class='post-backlinks post-comment-link'> </span> <div class='post-share-buttons goog-inline-block'> <a class='goog-inline-block share-button sb-email' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=8907727528910092398&target=email' target='_blank' title='Email This'><span class='share-button-link-text'>Email This</span></a><a class='goog-inline-block share-button sb-blog' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=8907727528910092398&target=blog' onclick='window.open(this.href, "_blank", "height=270,width=475"); return false;' target='_blank' title='BlogThis!'><span class='share-button-link-text'>BlogThis!</span></a><a class='goog-inline-block share-button sb-twitter' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=8907727528910092398&target=twitter' target='_blank' title='Share to X'><span class='share-button-link-text'>Share to X</span></a><a class='goog-inline-block share-button sb-facebook' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=8907727528910092398&target=facebook' onclick='window.open(this.href, "_blank", "height=430,width=640"); return false;' target='_blank' title='Share to Facebook'><span class='share-button-link-text'>Share to Facebook</span></a><a class='goog-inline-block share-button sb-pinterest' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=8907727528910092398&target=pinterest' target='_blank' title='Share to Pinterest'><span class='share-button-link-text'>Share to Pinterest</span></a> </div> </div> <div class='post-footer-line post-footer-line-2'><span class='post-labels'> Labels: <a href='http://www.righto.com/search/label/arc' rel='tag'>arc</a> </span> </div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> </div></div> <div class="date-outer"> <div class="date-posts"> <div class='post-outer'> <div class='post hentry' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='6264947694886887540' itemprop='blogId'/> <meta content='7590781741394121719' itemprop='postId'/> <a name='7590781741394121719'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='http://www.righto.com/2008/02/foundation-of-arc-documentation.html'>The foundation of Arc: Documentation</a> </h3> <div class='post-header'> <div class='post-header-line-1'></div> </div> <div class='post-body entry-content' id='post-body-7590781741394121719' itemprop='description articleBody'> The Arc language is implemented by a "foundation" of functionality implemented in Scheme. I have created <a href="http://www.righto.com/foundation-doc.html">detailed documentation</a> of the foundation functionality. <div style='clear: both;'></div> </div> <div class='post-footer'> <div 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/6264947694886887540/7590781741394121719' onclick=''> 3 comments: </a> </span> <span class='post-icons'> <span class='item-action'> <a href='https://www.blogger.com/email-post.g?blogID=6264947694886887540&postID=7590781741394121719' title='Email Post'> <img alt='' class='icon-action' height='13' src='http://img1.blogblog.com/img/icon18_email.gif' width='18'/> </a> </span> <span class='item-control blog-admin pid-1138732533'> <a href='https://www.blogger.com/post-edit.g?blogID=6264947694886887540&postID=7590781741394121719&from=pencil' title='Edit Post'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> <span class='post-backlinks post-comment-link'> </span> <div class='post-share-buttons goog-inline-block'> <a class='goog-inline-block share-button sb-email' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=7590781741394121719&target=email' target='_blank' title='Email This'><span class='share-button-link-text'>Email This</span></a><a class='goog-inline-block share-button sb-blog' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=7590781741394121719&target=blog' onclick='window.open(this.href, "_blank", "height=270,width=475"); return false;' target='_blank' title='BlogThis!'><span class='share-button-link-text'>BlogThis!</span></a><a class='goog-inline-block share-button sb-twitter' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=7590781741394121719&target=twitter' target='_blank' title='Share to X'><span class='share-button-link-text'>Share to X</span></a><a class='goog-inline-block share-button sb-facebook' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=7590781741394121719&target=facebook' onclick='window.open(this.href, "_blank", "height=430,width=640"); return false;' target='_blank' title='Share to Facebook'><span class='share-button-link-text'>Share to Facebook</span></a><a class='goog-inline-block share-button sb-pinterest' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=7590781741394121719&target=pinterest' target='_blank' title='Share to Pinterest'><span class='share-button-link-text'>Share to Pinterest</span></a> </div> </div> <div class='post-footer-line post-footer-line-2'><span class='post-labels'> Labels: <a href='http://www.righto.com/search/label/arc' rel='tag'>arc</a> </span> </div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> </div></div> <div class="date-outer"> <div class="date-posts"> <div class='post-outer'> <div class='post hentry' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='6264947694886887540' itemprop='blogId'/> <meta content='4798770215761013939' itemprop='postId'/> <a name='4798770215761013939'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='http://www.righto.com/2008/02/arc-internals-part-1.html'>Arc Internals, Part 1</a> </h3> <div class='post-header'> <div class='post-header-line-1'></div> </div> <div class='post-body entry-content' id='post-body-4798770215761013939' itemprop='description articleBody'> This article is the first part of a description of the implementation of the Arc language, based on my examination of the code. <p/> The core of Arc is implemented in Scheme (in ac.scm), and runs in the mzscheme interpreter. The remainder of the Arc language is implemented in Arc itself (arc.arc), and is loaded into the running Arc implementation. In addition, the Arc distribution includes libraries for a web server, string handling, and a few others. Arc runs a standard Read-Evaluate-Print Loop (REPL), allowing commands to be entered and executed interactively. <p/> In a bit more detail, when an Arc expression is input to the REPL, the Scheme reader reads and parses it. The Arc expression is converted to an analogous Scheme expression, and eval is applied to execute the Scheme code. The result is converted from the internal Scheme representation to a displayable form, and displayed as the output from the REPL. <p/> Interestingly, Arc's [ _ ] syntax is implemented entirely independently from the rest of Arc; the code in brackets.scm extends the <a href="http://docs.plt-scheme.org/reference/readtables.html">reader</a> so the bracket syntax is converted to standard syntax as the input is parsed. The bracket support could easily be run on Scheme without Arc, or Arc could be run without bracket support. <p/> Entering <code>:a</code> into the Arc REPL drops execution into Scheme, allowing easy examination of the internals: <pre class="repl">> (= x 3) 3 arc> (= y '(1 (2 3) 4)) (1 (2 3) 4) arc> (def z () (pr "hello")) #<procedure: z> arc> :a > _x 3 > _y (1 (2 3 . nil) 4 . nil) > _z #<procedure: z></pre> Arc's data and procedures are stored in the Scheme environment, with a few modifications. Arc symbols have an underscore prepended internally to avoid collisions with Scheme names. In the Arc language, the empty list is <code>nil</code>, while the Scheme empty list is (). Thus, Arc lists are stored in Scheme terminated by the (arbitrary) symbol 'nil, as can be seen by the dotted notation above. Arc macros are stored as a vector of the symbol 'tagged, the symbol 'mac, and the procedure. <h3>The REPL</h3> Arc runs from a Read-Evaluate-Print Loop (REPL), which is started by executing the simple procedure tl: <pre class="code"> (define (tl) (display "Use (quit) to quit, (tl) to return here after an interrupt.\n") (tl2)) </pre> Note that the REPL runs in Scheme, not in Arc. tl is a wrapper around tl2, which is the real REPL implementation: <pre class="code"> (define (tl2) (display "arc> ") (on-err (lambda (c) (set! last-condition* c) (display "Error: ") (write (exn-message c)) (newline) (tl2)) (lambda () (let ((expr (read))) (if (eqv? expr ':a) 'done (let ((val (arc-eval expr))) (write (ac-denil val)) (namespace-set-variable-value! '_that val) (namespace-set-variable-value! '_thatexpr expr) (newline) (tl2))))))) </pre> The arguments to on-err are an error procedure and the body procedure. The error procedure is executed if the main procedure encounters an exeception, similar to a try/catch block, but with the catch procedure first. The on-err procedure is implemented with continuations. If you're looking for the "mind-expanding" parts of Lisp, <a href="http://www.ccs.neu.edu/home/dorai/t-y-scheme/t-y-scheme-Z-H-15.html">continuations</a> will definitely interest you, but I will ignore on-err for now. <p/> The meat is the second lambda function. The Scheme read procedure reads the input and creates an object using the Scheme parser. The input is passed to arc-eval, which evaluates the input as an Arc form. The result is converted by arc-denil from the internal 'nil-terminated form to displayable form and written out. The tl2 procedure then calls itself; to the C programmer, this may look like a stack overflow waiting to happen. However, Scheme is tail-recursive so the stack doesn't grow, and the call acts like a simple loop. The Scheme variables _that and _thatexpr record the expression to help debugging. <h3>arc-eval and ac</h3> The arc-eval procedure is the main entry point for executing an Arc form. It calls ac to convert the Arc form to a quoted Scheme form, and then does an eval on the Scheme expression: <pre class="code"> (define (arc-eval expr) (eval (ac expr '()) (interaction-environment)))</pre> The arc-eval procedure can be executed directly from inside Scheme: <pre class="repl"> > (arc-eval '((fn (x) (+ x 1)) 42)) 43</pre> The ac procedure is the real meat of Arc, as it translates Arc to Scheme. Its second argument is the "environment", a list of symbols that are currently bound. At the REPL, this list is empty. <pre class="code"> (define (ac s env) (cond ((string? s) (string-copy s)) ; to avoid immutable strings ((literal? s) s) ((eqv? s 'nil) (list 'quote 'nil)) ((ssyntax? s) (ac (expand-ssyntax s) env)) ((symbol? s) (ac-var-ref s env)) ((ssyntax? (xcar s)) (ac (cons (expand-ssyntax (car s)) (cdr s)) env)) ((eq? (xcar s) 'quote) (list 'quote (ac-niltree (cadr s)))) ((eq? (xcar s) 'quasiquote) (ac-qq (cadr s) env)) ((eq? (xcar s) 'if) (ac-if (cdr s) env)) ((eq? (xcar s) 'fn) (ac-fn (cadr s) (cddr s) env)) ((eq? (xcar s) 'set) (ac-set (cdr s) env)) ((pair? s) (ac-call (car s) (cdr s) env)) (#t (err "Bad object in expression" s)))) </pre> Arc strings are copied to Scheme strings. Arc literals are unchanged. The Arc symbol 'nil is unchanged. Input with ssyntax (i.e. : or ~) is expanded and re-evaluated. Symbols are handled by ac-var-ref. Special operators quote, quasiquote, if, fn, and set are handled by separate procedures. Procedures are handled by ac-call. <h3>xdef</h3> Arc primitives are created with xdef, which enters a Scheme procedure into the namespace: <pre class="code"> (define (xdef a b) (namespace-set-variable-value! (ac-global-name a) b) b)</pre> For example, the Arc newstring procedure is just the Scheme make-string procedure: <pre class="code"> (xdef 'newstring make-string)</pre> Note that namespace-set-variable-value! is somewhat similar to define, except it takes a symbol such as 'a, rather than a variable such as a. <h3>Conclusion</h3> Many more interesting aspects of the Arc implementation remain, such as procedures, scoping, and macros. I hope to do more analysis later. Much of the above is based on discussions in the Arc forum. The code snippets from the Arc distribution are copyright Paul Graham and Robert Morris; the distribution is available at <a href="http://arclanguage.org/install">http://arclanguage.org/install</a>. <div style='clear: both;'></div> </div> <div class='post-footer'> <div 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/6264947694886887540/4798770215761013939' onclick=''> 1 comment: </a> </span> <span class='post-icons'> <span class='item-action'> <a href='https://www.blogger.com/email-post.g?blogID=6264947694886887540&postID=4798770215761013939' title='Email Post'> <img alt='' class='icon-action' height='13' src='http://img1.blogblog.com/img/icon18_email.gif' width='18'/> </a> </span> <span class='item-control blog-admin pid-1138732533'> <a href='https://www.blogger.com/post-edit.g?blogID=6264947694886887540&postID=4798770215761013939&from=pencil' title='Edit Post'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> <span class='post-backlinks post-comment-link'> </span> <div class='post-share-buttons goog-inline-block'> <a class='goog-inline-block share-button sb-email' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=4798770215761013939&target=email' target='_blank' title='Email This'><span class='share-button-link-text'>Email This</span></a><a class='goog-inline-block share-button sb-blog' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=4798770215761013939&target=blog' onclick='window.open(this.href, "_blank", "height=270,width=475"); return false;' target='_blank' title='BlogThis!'><span class='share-button-link-text'>BlogThis!</span></a><a class='goog-inline-block share-button sb-twitter' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=4798770215761013939&target=twitter' target='_blank' title='Share to X'><span class='share-button-link-text'>Share to X</span></a><a class='goog-inline-block share-button sb-facebook' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=4798770215761013939&target=facebook' onclick='window.open(this.href, "_blank", "height=430,width=640"); return false;' target='_blank' title='Share to Facebook'><span class='share-button-link-text'>Share to Facebook</span></a><a class='goog-inline-block share-button sb-pinterest' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=4798770215761013939&target=pinterest' target='_blank' title='Share to Pinterest'><span class='share-button-link-text'>Share to Pinterest</span></a> </div> </div> <div class='post-footer-line post-footer-line-2'><span class='post-labels'> Labels: <a href='http://www.righto.com/search/label/arc' rel='tag'>arc</a> </span> </div> <div class='post-footer-line post-footer-line-3'></div> </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='http://www.righto.com/search?updated-max=2009-06-05T22:06:00-07:00&max-results=7&reverse-paginate=true' id='Blog1_blog-pager-newer-link' title='Newer Posts'>Newer Posts</a> </span> <a class='home-link' href='http://www.righto.com/'>Home</a> </div> <div class='clear'></div> </div></div> </div> </div> <div class='column-left-outer'> <div class='column-left-inner'> <aside> </aside> </div> </div> <div class='column-right-outer'> <div class='column-right-inner'> <aside> <div class='sidebar section' id='sidebar-right-1'><div class='widget HTML' data-version='1' id='HTML2'> <div class='widget-content'> <style> @import url('https://fonts.googleapis.com/css?family=Montserrat:300,400,500,700'); .form-preview { display: flex; flex-direction: column; justify-content: center; margin-top: 30px; padding: clamp(17px, 5%, 40px) clamp(17px, 7%, 50px); max-width: 350px; min-height: 200px; border-radius: 6px; box-shadow: 0 5px 25px rgba(34, 60, 47, 0.25); } .form-preview, .form-preview *{ box-sizing: border-box; } .form-preview .preview-heading { width: 100%; } .form-preview .preview-heading h5{ margin-top: 0; margin-bottom: 0; } .form-preview .preview-input-field { margin-top: 20px; width: 100%; } .form-preview .preview-input-field input { width: 100%; height: 40px; border-radius: 6px; border: 2px solid #e9e8e8; background-color: #fff; outline: none; } .form-preview .preview-input-field input::placeholder, .form-preview .preview-input-field input { opacity: 0.5; color: #000; font-family: "Montserrat"; font-size: 14px; font-weight: 500; line-height: 20px; text-align: center; } .form-preview .preview-submit-button { margin-top: 10px; width: 100%; } .form-preview .preview-submit-button button { width: 100%; height: 40px; border: 0; border-radius: 6px; line-height: 0px; } .form-preview .preview-submit-button button:hover { cursor: pointer; } </style><form data-v-4c58e686="" action="https://api.follow.it/subscription-form/U3NBTmZKVkI1YVpCa000a0RCZHFiQ3FYMko1cWRTZTN6K3hJdWM2QWxJbE1uVXdXUHZZVzJVQzVLZGh5Y0RCVXB2d2JSTzBobGhuY0FsZnlHbVdFZ2VTN2Q4Vy84RnIxUTgzVlcrbXNIR0Y0aW93d3REM2J6VS9RL0gxWURnV1d8ZWN0YStwUWdWWUFiOTIyWDVGWjdYYVdGZEVNcC9qODZacjlwWXRIcEJQRT0=/8" method="post"><div data-v-4c58e686="" class="form-preview" style="background-color: rgb(255, 255, 255); border-style: solid; border-width: 1px; border-color: rgb(204, 204, 204); position: relative;"><div data-v-4c58e686="" class="preview-heading"><h5 data-v-4c58e686="" style="font-family: Montserrat; font-weight: bold; color: rgb(0, 0, 0); font-size: 12px; text-align: center;">Get new posts by email:</h5></div> <div data-v-4c58e686="" class="preview-input-field"><input data-v-4c58e686="" type="email" name="email" placeholder="Enter your email" spellcheck="false" /></div> <div data-v-4c58e686="" class="preview-submit-button"><button data-v-4c58e686="" type="submit" style="font-family: Montserrat; font-weight: bold; color: rgb(255, 255, 255); font-size: 12px; text-align: center; background-color: rgb(0, 0, 0);">Subscribe</button></div></div></form> </div> <div class='clear'></div> </div><div class='widget HTML' data-version='1' id='HTML3'> <h2 class='title'>About the site</h2> <div class='widget-content'> <a href="https://www.righto.com/p/index.html">Contact info and site index</a> </div> <div class='clear'></div> </div><div class='widget PopularPosts' data-version='1' id='PopularPosts1'> <h2>Popular Posts</h2> <div class='widget-content popular-posts'> <ul> <li> <div class='item-thumbnail-only'> <div class='item-thumbnail'> <a href='http://www.righto.com/2024/11/antenna-diodes-in-pentium-processor.html' target='_blank'> <img alt='' border='0' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_uzvidTDq2oMobyvjJo5ulkuCVreM-mgYnZ9tq0yJqpIUuUirbv9QShMlZNzxip0MSfA4HNU4_B_4vOQkqC3_5q_RB2MPctNp8jw6Ps84K7rE02cOtgwsg_-5LZCZMrHkcdF7Q=w72-h72-p-k-no-nu'/> </a> </div> <div class='item-title'><a href='http://www.righto.com/2024/11/antenna-diodes-in-pentium-processor.html'>Antenna diodes in the Pentium processor</a></div> </div> <div style='clear: both;'></div> </li> <li> <div class='item-thumbnail-only'> <div class='item-thumbnail'> <a href='http://www.righto.com/2012/05/apple-iphone-charger-teardown-quality.html' target='_blank'> <img alt='' border='0' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_vQF20K74MpkX8HABFgHSwOlHmf4rjb7PQW7Idb9sp_8Y77tNcj-30K1831alyiJrEbN7RTykFjkYXHtQ0X6SEHatSKuRt5vF1UhdlPbrqfd4uIwlKcDoucFB854BvN0aPQsFaTN3P5HI5H3A3dz8Tozd0=w72-h72-p-k-no-nu'/> </a> </div> <div class='item-title'><a href='http://www.righto.com/2012/05/apple-iphone-charger-teardown-quality.html'>Apple iPhone charger teardown: quality in a tiny expensive package</a></div> </div> <div style='clear: both;'></div> </li> <li> <div class='item-thumbnail-only'> <div class='item-thumbnail'> <a href='http://www.righto.com/2024/05/blog-post.html' target='_blank'> <img alt='' border='0' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_sBSOBTLxliYAZkYsTGSp425BpfQke1Lppz5cYkHyL5p-UYVGWu0X2hyecIIr710Q05Tj65nTEEMvo9sOmc_N1B8nhAXKSdN6ajV86kWcm9DKltplnqW0PH85dPQ4jdqr708x_b9oDb779x1up8E6-u=w72-h72-p-k-no-nu'/> </a> </div> <div class='item-title'><a href='http://www.righto.com/2024/05/blog-post.html'>Inside a vintage aerospace navigation computer of uncertain purpose</a></div> </div> <div style='clear: both;'></div> </li> <li> <div class='item-thumbnail-only'> <div class='item-thumbnail'> <a href='http://www.righto.com/2009/08/multi-protocol-infrared-remote-library.html' target='_blank'> <img alt='' border='0' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_vJRBtLXQNz6ZxWFcsxGxQjrvpZyL3KWBgZcgQdE-AOSk1OHpsBxwQcsQ79yjExz51C9d8hxkrrWs3BwDF5T6Z_WhtfIT6HWYt15RhI8X-3YDo=w72-h72-p-k-no-nu'/> </a> </div> <div class='item-title'><a href='http://www.righto.com/2009/08/multi-protocol-infrared-remote-library.html'>A Multi-Protocol Infrared Remote Library for the Arduino</a></div> </div> <div style='clear: both;'></div> </li> <li> <div class='item-thumbnail-only'> <div class='item-thumbnail'> <a href='http://www.righto.com/2014/09/mining-bitcoin-with-pencil-and-paper.html' target='_blank'> <img alt='' border='0' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_uXdBgiH24Qh1QdhYig3PYPWxdoADOVua5CT0epCOhoRJnAa6Pzd3XJ-qQY5xPQeYSjcUx4K5LNqKnl-hOuDw81VEFt0bo7V9u1dnzdSYqb0ME8DBE7lxnnY1chkRJdrQMw=w72-h72-p-k-no-nu'/> </a> </div> <div class='item-title'><a href='http://www.righto.com/2014/09/mining-bitcoin-with-pencil-and-paper.html'>Mining Bitcoin with pencil and paper: 0.67 hashes per day</a></div> </div> <div style='clear: both;'></div> </li> <li> <div class='item-thumbnail-only'> <div class='item-thumbnail'> <a href='http://www.righto.com/2024/08/pentium-navajo-fairchild-shiprock.html' target='_blank'> <img alt='' border='0' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_uw4fkGvTuYewUCV0kWPgf0C7sCc4safqDQ3zcPGxGHVJFzj9igyLqmqOaGsMgF9kKXtaabDaXKybxAXtQxDpZkZqEqrQ5fb4uo56HTlPVH6PVW8PSZ1QrkhKWpI0bHegZhFt2q=w72-h72-p-k-no-nu'/> </a> </div> <div class='item-title'><a href='http://www.righto.com/2024/08/pentium-navajo-fairchild-shiprock.html'>The Pentium as a Navajo weaving</a></div> </div> <div style='clear: both;'></div> </li> <li> <div class='item-thumbnail-only'> <div class='item-thumbnail'> <a href='http://www.righto.com/2013/06/teardown-and-exploration-of-magsafe.html' target='_blank'> <img alt='' border='0' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_vvVaH3FxmMRFp9U2uXFKfV6s4P_VLLoZlHsdU0rFyAx7ntHCJ3dyavNi1X6d6DJ_2JAgI0TQt1uDEhnTsg9zsIHSTGg6swhHAyjVaQRe6m3UZT6b5d3gQ9Kl_sfJH6ymydIwPAxfKS4YF2qXA=w72-h72-p-k-no-nu'/> </a> </div> <div class='item-title'><a href='http://www.righto.com/2013/06/teardown-and-exploration-of-magsafe.html'>Teardown and exploration of Apple's Magsafe connector</a></div> </div> <div style='clear: both;'></div> </li> <li> <div class='item-thumbnail-only'> <div class='item-thumbnail'> <a href='http://www.righto.com/2023/01/inside-globus-ink-mechanical-navigation.html' target='_blank'> <img alt='' border='0' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_ubkGvTunxnDXujpfuTSBTmCTBKvsYWVBtmhlWBWcP_Z_xYqIzSemAqVm_Izc6lP9PdiZ3lt_nI2I3GjnYZD2c2bd4S6NAzE_CErmve57HZJVVyLa5Nk3ynzCg3RM6PIOY1PZo=w72-h72-p-k-no-nu'/> </a> </div> <div class='item-title'><a href='http://www.righto.com/2023/01/inside-globus-ink-mechanical-navigation.html'>Inside the Globus INK: a mechanical navigation computer for Soviet spaceflight</a></div> </div> <div style='clear: both;'></div> </li> </ul> <div class='clear'></div> </div> </div><div class='widget BlogSearch' data-version='1' id='BlogSearch1'> <h2 class='title'>Search This Blog</h2> <div class='widget-content'> <div id='BlogSearch1_form'> <form action='http://www.righto.com/search' class='gsc-search-box' target='_top'> <table cellpadding='0' cellspacing='0' class='gsc-search-box'> <tbody> <tr> <td class='gsc-input'> <input autocomplete='off' class='gsc-input' name='q' size='10' title='search' type='text' value=''/> </td> <td class='gsc-search-button'> <input class='gsc-search-button' title='search' type='submit' value='Search'/> </td> </tr> </tbody> </table> </form> </div> </div> <div class='clear'></div> </div><div class='widget Label' data-version='1' id='Label1'> <h2>Labels</h2> <div class='widget-content cloud-label-widget-content'> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/386'>386</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/6502'>6502</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/8008'>8008</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/8085'>8085</a> </span> <span class='label-size label-size-4'> <a dir='ltr' href='http://www.righto.com/search/label/8086'>8086</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/8087'>8087</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/8088'>8088</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/aerospace'>aerospace</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/alto'>alto</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/analog'>analog</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/Apollo'>Apollo</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/apple'>apple</a> </span> <span class='label-size label-size-4'> <a dir='ltr' href='http://www.righto.com/search/label/arc'>arc</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/arduino'>arduino</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/arm'>arm</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/beaglebone'>beaglebone</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/bitcoin'>bitcoin</a> </span> <span class='label-size label-size-1'> <a dir='ltr' href='http://www.righto.com/search/label/c%23'>c#</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/cadc'>cadc</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/calculator'>calculator</a> </span> <span class='label-size label-size-4'> <a dir='ltr' href='http://www.righto.com/search/label/chips'>chips</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/css'>css</a> </span> <span class='label-size label-size-1'> <a dir='ltr' href='http://www.righto.com/search/label/datapoint'>datapoint</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/dx7'>dx7</a> </span> <span class='label-size label-size-5'> <a dir='ltr' href='http://www.righto.com/search/label/electronics'>electronics</a> </span> <span class='label-size label-size-1'> <a dir='ltr' href='http://www.righto.com/search/label/f%23'>f#</a> </span> <span class='label-size label-size-1'> <a dir='ltr' href='http://www.righto.com/search/label/fairchild'>fairchild</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/fpga'>fpga</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/fractals'>fractals</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/genome'>genome</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/globus'>globus</a> </span> <span class='label-size label-size-1'> <a dir='ltr' href='http://www.righto.com/search/label/haskell'>haskell</a> </span> <span class='label-size label-size-1'> <a dir='ltr' href='http://www.righto.com/search/label/HP'>HP</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/html5'>html5</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/ibm'>ibm</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/ibm1401'>ibm1401</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/ibm360'>ibm360</a> </span> <span class='label-size label-size-4'> <a dir='ltr' href='http://www.righto.com/search/label/intel'>intel</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/ipv6'>ipv6</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/ir'>ir</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/java'>java</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/javascript'>javascript</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/math'>math</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/microcode'>microcode</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/oscilloscope'>oscilloscope</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/Pentium'>Pentium</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/photo'>photo</a> </span> <span class='label-size label-size-4'> <a dir='ltr' href='http://www.righto.com/search/label/power%20supply'>power supply</a> </span> <span class='label-size label-size-4'> <a dir='ltr' href='http://www.righto.com/search/label/random'>random</a> </span> <span class='label-size label-size-5'> <a dir='ltr' href='http://www.righto.com/search/label/reverse-engineering'>reverse-engineering</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/sheevaplug'>sheevaplug</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/snark'>snark</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/space'>space</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/spanish'>spanish</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/synth'>synth</a> </span> <span class='label-size label-size-4'> <a dir='ltr' href='http://www.righto.com/search/label/teardown'>teardown</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/theory'>theory</a> </span> <span class='label-size label-size-1'> <a dir='ltr' href='http://www.righto.com/search/label/unicode'>unicode</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/Z-80'>Z-80</a> </span> <div class='clear'></div> </div> </div><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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/'> 2024 </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/09/'> September </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/08/'> August </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/07/'> July </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/06/'> June </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/05/'> May </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/03/'> March </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/02/'> February </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/01/'> January </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/'> 2023 </a> <span class='post-count' dir='ltr'>(35)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/11/'> November </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/09/'> September </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/08/'> August </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/07/'> July </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/05/'> May </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/04/'> April </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/02/'> February </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/01/'> January </a> <span class='post-count' dir='ltr'>(8)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2022/'> 2022 </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2022/11/'> November </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2022/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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2022/07/'> July </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2022/06/'> June </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2022/05/'> May </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2022/04/'> April </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2022/03/'> March </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2022/02/'> February </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2022/01/'> January </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/'> 2021 </a> <span class='post-count' dir='ltr'>(26)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/11/'> November </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/09/'> September </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/07/'> July </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/06/'> June </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/05/'> May </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/04/'> April </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/02/'> February </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/01/'> January </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/'> 2020 </a> <span class='post-count' dir='ltr'>(33)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/11/'> November </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/10/'> October </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/09/'> September </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/08/'> August </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/07/'> July </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/06/'> June </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/05/'> May </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/04/'> April </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/03/'> March </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/01/'> January </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2019/'> 2019 </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2019/11/'> November </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2019/10/'> October </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2019/09/'> September </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2019/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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2019/07/'> July </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2019/04/'> April </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2019/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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2019/01/'> January </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2018/'> 2018 </a> <span class='post-count' dir='ltr'>(17)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2018/12/'> December </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2018/09/'> September </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2018/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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2018/06/'> June </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2018/05/'> May </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2018/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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2018/03/'> March </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2018/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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2018/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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2017/'> 2017 </a> <span class='post-count' dir='ltr'>(21)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2017/12/'> December </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2017/11/'> November </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2017/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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2017/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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2017/07/'> July </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2017/06/'> June </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2017/04/'> April </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2017/03/'> March </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2017/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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2017/01/'> January </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/'> 2016 </a> <span class='post-count' dir='ltr'>(34)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/10/'> October </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/09/'> September </a> <span class='post-count' dir='ltr'>(8)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/08/'> August </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/07/'> July </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/06/'> June </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/05/'> May </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/02/'> February </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/01/'> January </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2015/'> 2015 </a> <span class='post-count' dir='ltr'>(12)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2015/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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2015/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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2015/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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2015/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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2015/05/'> May </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2015/03/'> March </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2015/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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2014/'> 2014 </a> <span class='post-count' dir='ltr'>(13)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2014/12/'> December </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2014/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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2014/09/'> September </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2014/05/'> May </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2014/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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2014/02/'> February </a> <span class='post-count' dir='ltr'>(5)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2013/'> 2013 </a> <span class='post-count' dir='ltr'>(24)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2013/11/'> November </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2013/09/'> September </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2013/08/'> August </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2013/07/'> July </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2013/06/'> June </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2013/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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2013/03/'> March </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2013/02/'> February </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2013/01/'> January </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2012/'> 2012 </a> <span class='post-count' dir='ltr'>(10)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2012/12/'> December </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2012/11/'> November </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2012/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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2012/05/'> May </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2012/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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2012/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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2011/'> 2011 </a> <span class='post-count' dir='ltr'>(11)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2011/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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2011/07/'> July </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2011/05/'> May </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2011/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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2011/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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2011/02/'> February </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2010/'> 2010 </a> <span class='post-count' dir='ltr'>(22)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2010/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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2010/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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2010/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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2010/06/'> June </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2010/05/'> May </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2010/04/'> April </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2010/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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2010/01/'> January </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2009/'> 2009 </a> <span class='post-count' dir='ltr'>(22)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2009/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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2009/11/'> November </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2009/09/'> September </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2009/08/'> August </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2009/07/'> July </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2009/06/'> June </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2009/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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2009/03/'> March </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2009/02/'> February </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'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2009/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'> ▼  </span> </a> <a class='post-count-link' href='http://www.righto.com/2008/'> 2008 </a> <span class='post-count' dir='ltr'>(27)</span> <ul class='hierarchy'> <li class='archivedate expanded'> <a class='toggle' href='javascript:void(0)'> <span class='zippy toggle-open'> ▼  </span> </a> <a class='post-count-link' href='http://www.righto.com/2008/07/'> July </a> <span class='post-count' dir='ltr'>(3)</span> <ul class='posts'> <li><a href='http://www.righto.com/2008/07/rise-of-scripting-languages-and-fall-of.html'>The rise of scripting languages and the fall of Java</a></li> <li><a href='http://www.righto.com/2008/07/why-your-favorite-language-is-unpopular.html'>Why your favorite language is unpopular</a></li> <li><a href='http://www.righto.com/2008/07/maxwells-equations-of-software-examined.html'>"Maxwell's equations of software" examined</a></li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2008/06/'> June </a> <span class='post-count' dir='ltr'>(1)</span> <ul class='posts'> <li><a href='http://www.righto.com/2008/06/why-arc-is-good-for-video-games.html'>Why Arc is good for video games</a></li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2008/05/'> May </a> <span class='post-count' dir='ltr'>(3)</span> <ul class='posts'> <li><a href='http://www.righto.com/2008/05/using-opengl-with-arc.html'>Using OpenGL with Arc</a></li> <li><a href='http://www.righto.com/2008/05/why-arc-is-bad-for-exploratory.html'>Why Arc is bad for exploratory programming</a></li> <li><a href='http://www.righto.com/2008/05/importance-of-software-testing.html'>The importance of software testing</a></li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2008/04/'> April </a> <span class='post-count' dir='ltr'>(4)</span> <ul class='posts'> <li><a href='http://www.righto.com/2008/04/idioms-and-patterns-in-arc.html'>Idioms for programming in Arc</a></li> <li><a href='http://www.righto.com/2008/04/many-arc-compilers-and-interpreters.html'>Many Arc compilers and interpreters</a></li> <li><a href='http://www.righto.com/2008/04/ajax-and-arc.html'>Ajax and Arc</a></li> <li><a href='http://www.righto.com/2008/04/documentation-of-html-generation-in-arc.html'>Documentation of HTML generation in the Arc language</a></li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2008/03/'> March </a> <span class='post-count' dir='ltr'>(10)</span> <ul class='posts'> <li><a href='http://www.righto.com/2008/03/continuations-made-difficult.html'>Continuations made difficult</a></li> <li><a href='http://www.righto.com/2008/03/documentation-for-almost-all-of-arc.html'>Documentation for (almost) all of Arc</a></li> <li><a href='http://www.righto.com/2008/03/arc-popular-since-2004.html'>Arc: popular since 2004!</a></li> <li><a href='http://www.righto.com/2008/03/what-does-even-tried-multi-mean.html'>"Even tried multi" error explained</a></li> <li><a href='http://www.righto.com/2008/03/arc-continuation-puzzle.html'>Arc continuation puzzle</a></li> <li><a href='http://www.righto.com/2008/03/lots-more-documentation.html'>Lots more documentation</a></li> <li><a href='http://www.righto.com/2008/03/io-in-arc-language.html'>I/O in the Arc language</a></li> <li><a href='http://www.righto.com/2008/03/internals-of-places-and-setforms.html'>Internals of places and setforms</a></li> <li><a href='http://www.righto.com/2008/03/arc-documentation-table-of-contents.html'>Arc documentation table of contents</a></li> <li><a href='http://www.righto.com/2008/03/arc-assignment-and-places-documentation.html'>Arc assignment and places documentation</a></li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2008/02/'> February </a> <span class='post-count' dir='ltr'>(6)</span> <ul class='posts'> <li><a href='http://www.righto.com/2008/02/arc-internals-part-2-macros.html'>Arc internals part 2: Macros</a></li> <li><a href='http://www.righto.com/2008/02/arc-template-documentation.html'>Arc template documentation</a></li> <li><a href='http://www.righto.com/2008/02/git-and-anarki-arc-repository-brief.html'>Git and the Anarki Arc repository: a brief guide</a></li> <li><a href='http://www.righto.com/2008/02/whats-new-in-arc2.html'>What's new in arc2</a></li> <li><a href='http://www.righto.com/2008/02/foundation-of-arc-documentation.html'>The foundation of Arc: Documentation</a></li> <li><a href='http://www.righto.com/2008/02/arc-internals-part-1.html'>Arc Internals, Part 1</a></li> </ul> </li> </ul> </li> </ul> </div> </div> <div class='clear'></div> </div> </div></div> </aside> </div> </div> </div> <div style='clear: both'></div> <!-- columns --> </div> <!-- main --> </div> </div> <div class='main-cap-bottom cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> <footer> <div class='footer-outer'> <div class='footer-cap-top cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left footer-fauxborder-left'> <div class='fauxborder-right footer-fauxborder-right'></div> <div class='region-inner footer-inner'> <div class='foot no-items section' id='footer-1'></div> <table border='0' cellpadding='0' cellspacing='0' class='section-columns columns-2'> <tbody> <tr> <td class='first columns-cell'> <div class='foot no-items section' id='footer-2-1'></div> </td> <td class='columns-cell'> <div class='foot no-items section' id='footer-2-2'></div> </td> </tr> </tbody> </table> <!-- outside of the include in order to lock Attribution widget --> <div class='foot section' id='footer-3'><div class='widget Attribution' data-version='1' id='Attribution1'> <div class='widget-content' style='text-align: center;'> Powered by <a href='https://www.blogger.com' target='_blank'>Blogger</a>. </div> <div class='clear'></div> </div></div> </div> </div> <div class='footer-cap-bottom cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> </footer> <!-- content --> </div> </div> <div class='content-cap-bottom cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> </div> <script type='text/javascript'> window.setTimeout(function() { document.body.className = document.body.className.replace('loading', ''); }, 10); </script> <script type="text/javascript" src="https://www.blogger.com/static/v1/widgets/984859869-widgets.js"></script> <script type='text/javascript'> window['__wavt'] = 'AOuZoY6zotA09jcWBrEdB2Ei92kY_wJmxw:1732790418847';_WidgetManager._Init('//www.blogger.com/rearrange?blogID\x3d6264947694886887540','//www.righto.com/2008/','6264947694886887540'); _WidgetManager._SetDataContext([{'name': 'blog', 'data': {'blogId': '6264947694886887540', 'title': 'Ken Shirriff\x27s blog', 'url': 'http://www.righto.com/2008/', 'canonicalUrl': 'http://www.righto.com/2008/', 'homepageUrl': 'http://www.righto.com/', 'searchUrl': 'http://www.righto.com/search', 'canonicalHomepageUrl': 'http://www.righto.com/', 'blogspotFaviconUrl': 'http://www.righto.com/favicon.ico', 'bloggerUrl': 'https://www.blogger.com', 'hasCustomDomain': true, 'httpsEnabled': false, 'enabledCommentProfileImages': true, 'gPlusViewType': 'FILTERED_POSTMOD', 'adultContent': false, 'analyticsAccountNumber': 'UA-3782444-1', 'encoding': 'UTF-8', 'locale': 'en', 'localeUnderscoreDelimited': 'en', 'languageDirection': 'ltr', 'isPrivate': false, 'isMobile': false, 'isMobileRequest': false, 'mobileClass': '', 'isPrivateBlog': false, 'isDynamicViewsAvailable': true, 'feedLinks': '\x3clink rel\x3d\x22alternate\x22 type\x3d\x22application/atom+xml\x22 title\x3d\x22Ken Shirriff\x26#39;s blog - Atom\x22 href\x3d\x22http://www.righto.com/feeds/posts/default\x22 /\x3e\n\x3clink rel\x3d\x22alternate\x22 type\x3d\x22application/rss+xml\x22 title\x3d\x22Ken Shirriff\x26#39;s blog - RSS\x22 href\x3d\x22http://www.righto.com/feeds/posts/default?alt\x3drss\x22 /\x3e\n\x3clink rel\x3d\x22service.post\x22 type\x3d\x22application/atom+xml\x22 title\x3d\x22Ken Shirriff\x26#39;s blog - Atom\x22 href\x3d\x22https://www.blogger.com/feeds/6264947694886887540/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': '2008', 'pageTitle': 'Ken Shirriff\x27s blog: 2008'}}, {'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': 'Ken Shirriff\x27s blog', 'description': 'Computer history, restoring vintage computers, IC reverse engineering, and whatever', 'url': 'http://www.righto.com/2008/', 'type': 'feed', 'isSingleItem': false, 'isMultipleItems': true, 'isError': false, 'isPage': false, 'isPost': false, 'isHomepage': false, 'isArchive': true, 'isLabelSearch': false, 'archive': {'year': 2008, 'rangeMessage': 'Showing posts from 2008'}}}]); _WidgetManager._RegisterWidget('_HeaderView', new _WidgetInfo('Header1', 'header', document.getElementById('Header1'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_BlogView', new _WidgetInfo('Blog1', 'main', document.getElementById('Blog1'), {'cmtInteractionsEnabled': false}, 'displayModeFull')); _WidgetManager._RegisterWidget('_HTMLView', new _WidgetInfo('HTML2', 'sidebar-right-1', document.getElementById('HTML2'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_HTMLView', new _WidgetInfo('HTML3', 'sidebar-right-1', document.getElementById('HTML3'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_PopularPostsView', new _WidgetInfo('PopularPosts1', 'sidebar-right-1', document.getElementById('PopularPosts1'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_BlogSearchView', new _WidgetInfo('BlogSearch1', 'sidebar-right-1', document.getElementById('BlogSearch1'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_LabelView', new _WidgetInfo('Label1', 'sidebar-right-1', document.getElementById('Label1'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_BlogArchiveView', new _WidgetInfo('BlogArchive1', 'sidebar-right-1', document.getElementById('BlogArchive1'), {'languageDirection': 'ltr', 'loadingMessage': 'Loading\x26hellip;'}, 'displayModeFull')); _WidgetManager._RegisterWidget('_AttributionView', new _WidgetInfo('Attribution1', 'footer-3', document.getElementById('Attribution1'), {}, 'displayModeFull')); </script> </body> </html>