<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Drinkable Chicken &#187; s1</title>
	<atom:link href="http://4.flowsnake.org/archives/tag/s1/feed" rel="self" type="application/rss+xml" />
	<link>http://4.flowsnake.org</link>
	<description>A Pythoneer&#039;s adventures with Scheme, etc.</description>
	<lastBuildDate>Fri, 15 Jul 2011 08:53:43 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>Macro trial balloons</title>
		<link>http://4.flowsnake.org/archives/66</link>
		<comments>http://4.flowsnake.org/archives/66#comments</comments>
		<pubDate>Sat, 16 Feb 2008 04:36:20 +0000</pubDate>
		<dc:creator>Hans Nowak</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[awk]]></category>
		<category><![CDATA[chicken]]></category>
		<category><![CDATA[macros]]></category>
		<category><![CDATA[s1]]></category>
		<category><![CDATA[scheme]]></category>

		<guid isPermaLink="false">http://4.flowsnake.org/archives/66</guid>
		<description><![CDATA[I&#8217;ve been hacking on and off on s1, my vaporware Awk-like tool that uses Scheme for scripting. The &#8220;language&#8221; defined by s1 includes a few macros. Strictly speaking, these are redundant, but they do make things shorter, which is important for writing one-liners. Anyway, I am still kind of new to macros&#8230; so I&#8217;m wondering [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been hacking on and off on <a href="/archives/58">s1</a>, my <s>vaporware</s> Awk-like tool that uses Scheme for scripting.  The &#8220;language&#8221; defined by <em>s1</em> includes a few macros. Strictly speaking, these are redundant, but they do make things shorter, which is important for writing one-liners.</p>
<p>Anyway, I am still kind of new to macros&#8230; so I&#8217;m wondering if the code I wrote is sound. I&#8217;m offering the definitions here for review. (Comments from experienced Schemers are welcome.)</p>
<p>1. <em>inc!</em> is used to easily increase variables. It can take any number of arguments; if none are given, 1 is added by default. For example:</p>
<ul>
<li><em>(inc! x)</em> adds 1 to <em>x</em></li>
<li><em>(inc! x 33)</em> adds 33 to <em>x</em></li>
<li><em>(inc! x 1 2 3 4 5)</em> adds <em>(+ 1 2 3 4 5)</em> to <em>x</em></li>
</ul>
<p>As the exclamation mark indicates, <em>inc!</em> changes the variable in-place. Here&#8217;s its current definition:</p>
<pre>(define-macro (inc! name . args)
  (let ((total (gensym)))
    `(let ((,total
             (if (null? (list ,@args))
                 1
                 (apply + (list ,@args)))))
       (set! ,name (+ ,name ,total)))))</pre>
<p>2. Defining multiple variables does not mix well with one-liners. So I added a macro <em>def</em> that allows one to define them quickly and concisely. Like <em>inc!</em>, <em>def</em> takes any number of arguments. If an argument is a list <em>(name value)</em>, then a variable is created with the given name and value. If an argument is a symbol, then a variable is created with that name and a value of 0. (Awk is often used to add numbers, so zero seems the most sensible default, IMHO.)</p>
<p>Examples:</p>
<ul>
<li><em>(def x)</em> &#8212; same as <em>(define x 0)</em></li>
<li><em>(def x y)</em> &#8212; same as <em>(define x 0) (define y 0)</em></li>
<li><em>(def (a 1) (b &#8220;hello&#8221;))</em> &#8212; same as <em>(define a 1) (define b &#8220;hello&#8221;)</em></li>
<li><em>(def q (w 3))</em> &#8212; same as <em>(define q 0) (define w 3) </em></li>
</ul>
<p>Here&#8217;s the current definition:</p>
<pre>(define-macro (def . args)
  (if (null? args)
      #f
      (let* ((a (car args))
             (rest-args (cdr args))
             (name (if (list? a) (car a) a))
             (value (if (list? a) (cadr a) 0)))
        `(begin
           (define ,name ,value)
           (def ,@rest-args)))))</pre>
<p>(I&#8217;m not sure about the <em>#f</em>; it&#8217;s not supposed to return a value anyway.)</p>
<p>In any case, <em>s1</em>&#8216;s auxiliary functions and macros allow for concise code. (Some of it is sloppy, but useful for &#8220;scripting&#8221;, especially one-liners. Naturally, it&#8217;s always possible to write longer scripts using &#8220;cleaner&#8221; code.)</p>
<p>For example, here&#8217;s a one-liner that takes the last words on the given lines and adds them up (assuming they are numbers):</p>
<pre>s1 '(B (def s)) (inc! s &amp;$nf) (A (out s))'</pre>
<p>(I&#8217;m not sure about the <em>&amp;</em> syntax yet; it&#8217;s used here as a shortcut for the <em>as-number</em> function, which attempts to convert a string to a number, returning 0 by default.)</p>
<p><em>B</em> and <em>A</em> are shorthands for <em>BEFORE</em> and <em>AFTER</em>, blocks that are executed before and after the main code (which is executed for each line in the given text). The actual order in which these appear doesn&#8217;t matter, but it&#8217;s probably more intuitive to do before-main-after.</p>
<p>Print the number of lines, words and characters (like <em>wc</em>):</p>
<pre>s1 '(B (def c w)) (inc! w nf) (inc! c (len $0) 1) (A (out nl w c))'</pre>
<p>Print names starting with &#8220;Ga&#8221;:</p>
<pre>s1 '(if (~ #/^Ga/) (print $0))' /usr/share/dict/propernames</pre>
<p>(I&#8217;m using <a href="http://chicken.wiki.br/regex-literals">regex literals</a>, and <em>~</em> is the same as <em>string-search</em>, except it matches against <em>$0</em> (the whole line) by default.)</p>
<p>These are just teasers. Actual code is subject to change. I will release this when the &#8220;API&#8221; is somewhat stable. It&#8217;s still mostly a toy, though&#8230; :-)</p>
]]></content:encoded>
			<wfw:commentRss>http://4.flowsnake.org/archives/66/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Making s1 code shorter</title>
		<link>http://4.flowsnake.org/archives/59</link>
		<comments>http://4.flowsnake.org/archives/59#comments</comments>
		<pubDate>Thu, 07 Feb 2008 17:58:13 +0000</pubDate>
		<dc:creator>Hans Nowak</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[chicken]]></category>
		<category><![CDATA[s1]]></category>
		<category><![CDATA[scheme]]></category>

		<guid isPermaLink="false">http://4.flowsnake.org/archives/59</guid>
		<description><![CDATA[More efforts to make s1 code shorter&#8230; I added/changed the following: slice function (this will come in handy for string manipulation, although (slice s a b) is still longer than s[a:b] nf variable (indicates the number of fields in a line) $ now accepts any expression, not just a number literal (so we can say [...]]]></description>
			<content:encoded><![CDATA[<p>More efforts to make <a href="/archives/58"><em>s1</em></a> code shorter&#8230;</p>
<p>I added/changed the following:</p>
<ul>
<li><em>slice</em> function (this will come in handy for string manipulation, although <em>(slice s a b)</em> is still longer than <em>s[a:b]</em></li>
<li><em>nf</em> variable (indicates the number of fields in a line)</li>
<li><em>$</em> now accepts any expression, not just a number literal (so we can say <em>$nf </em>or <em>$(- x 1)</em> or whatever)</li>
<li><em>-f</em> command line option to quickly set the field separator</li>
<li>created an alias <em>s1</em> for &#8216;csi -ss /path/to/s1.scm&#8217; (OK, this is not a change to the tool proper, but it helps&#8230; nobody wants to type <em>csi -ss</em> with the full path, all the time)</li>
</ul>
<p>None of this is particularly original (as it&#8217;s all borrowed from Awk and Python), but it does help to make code much shorter. I can now write a one-liner like this:</p>
<pre>find "${1-.}" -type d | s1 -f/ '(print "   |" (make-string nf #\-) $nf)'</pre>
<p>&#8230;which produces almost the same tree as described <a href="http://www.centerkey.com/tree/">here</a>. Almost, because it uses one &#8220;-&#8221; for each directory rather than two. We can fix that by making the example somewhat longer (and less readable to non-Schemers, although admittedly the Awk example isn&#8217;t very readable to non-Awkers either):</p>
<pre>find "${1-.}" -type d | s1 -f/ '(print "   |" (make-string (* (- nf 1) 2) #\-) $nf)'</pre>
<p>Next up: regular expressions&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://4.flowsnake.org/archives/59/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>I can has scripting?</title>
		<link>http://4.flowsnake.org/archives/58</link>
		<comments>http://4.flowsnake.org/archives/58#comments</comments>
		<pubDate>Thu, 07 Feb 2008 04:58:28 +0000</pubDate>
		<dc:creator>Hans Nowak</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[chicken]]></category>
		<category><![CDATA[s1]]></category>
		<category><![CDATA[scheme]]></category>
		<category><![CDATA[unix]]></category>

		<guid isPermaLink="false">http://4.flowsnake.org/archives/58</guid>
		<description><![CDATA[Brainstorming a bit here&#8230; So I saw this cool one-liner script. It displays a directory tree: ls -R &#124; grep ":$" &#124; sed -e 's/:$//' -e 's/[^-][^\/]*\//--/g' -e 's/^/ /' -e 's/-/&#124;/' I have been hacking (on and off) on an Awk-like tool that uses Chicken for scripting. Its working title is s1, and so [...]]]></description>
			<content:encoded><![CDATA[<p>Brainstorming a bit here&#8230;</p>
<p>So I saw this cool <a href="http://www.centerkey.com/tree/">one-liner script</a>. It displays a directory tree:</p>
<pre>
ls -R | grep ":$" | sed -e 's/:$//' -e 's/[^-][^\/]*\//--/g' -e 's/^/   /' -e 's/-/|/'</pre>
<p>I have been hacking (on and off) on an <a href="/archives/48">Awk-like tool</a> that uses Chicken for scripting. Its working title is <strong>s1</strong>, and so far it supports begin/main/end blocks like Awk, and <em>$N</em>-notation for quick access to fields.</p>
<p>The real problem is not, adding Awk-like functionality as Scheme functions, but rather, making the Scheme concise enough that it can be used for one-liners. For example, the following works, but is still too verbose:</p>
<pre>ls -l | csi -ss s1.scm '(before (set! total 0)) (set! total (+ total (as-number $5))) (after (print total))'</pre>
<p>(It shows the total size of files in the current directory, in case it wasn&#8217;t obvious. :-)</p>
<p>It gets even worse when we try to emulate the ls/grep/sed script mentioned above. Writing this as a one-line just isn&#8217;t feasible at this point; rather, I have to use a script:</p>
<pre>;; tree.s1
;; Call with: ls -aR | csi -ss s1.scm -s tree.s1

(define (branch parts)
  (let* ((parts (reverse parts))
         (dirname (string-trim-right (first parts) #\:))
         (line (apply conc (map (lambda (s) "--") (cdr parts)))))
    (conc "|" line dirname)))

(when (string-suffix? ":" $0)
  (let* ((parts (string-split $0 "/")))
    (print "   " (branch parts))))</pre>
<p>Much of the work goes into processing strings and lists, but even without that the code probably still would not fit on one line.</p>
<p>Granted, it&#8217;s hard to beat the conciseness of regular expressions (as used by <em>grep</em> and <em>sed</em>), but if I want <em>s1</em> to be useful, it needs to support (much) shorter code. (Maybe I should rewrite it in Arc? ;-)</p>
<p>Here are some thoughts about making this shorter:</p>
<p>1. I dearly miss slicing. In Python, I would have used <em>s[:-1]</em> to chop off the trailing colon. Adding a <em>slice</em> function to the toolbox would probably be useful.</p>
<p>2. I could leverage some of the Awk-like features. This <a href="http://reddit.com/r/programming/info/67wfw/comments/c0342kz">Reddit comment</a> does just that:</p>
<pre><code>find "${1-.}" -type d | awk -F/ '{printf "  |%*s%s\n",(NF-1)*2,"",$NF}'</code></pre>
<p>It takes advantage of the following features:</p>
<ul>
<li>using &#8220;/&#8221; as a field separator (effectively splitting the path with no extra code)</li>
<li>using <em>NF</em> (indicating the number of fields in a line) to compute the indentation level</li>
<li>using <em>$NF</em> to display the last field (i.e. the directory name we want to see)</li>
</ul>
<p>As it happens, <em>s1</em> can do all these things as well, but it won&#8217;t be quite as concise. This is something to work on. Maybe there could be a special variable (or symbol) that translates to <em>(length *fields*)</em>. I would have to hack the current <a href="/archives/49">$-literal</a> to accept any expression, not just a number literal.</p>
<p>The tricky part is to make things concise while still keeping the spirit of Scheme. :-/ <em>s1</em> will never automagically coerce numbers to strings (or vice versa), for example. I can, however, make it easy to convert them explicitly. (This is also the Pythoneer in me speaking&#8230; explicit is better than implicit, and all that good stuff.)</p>
<p>Anyway, there was really no point to this post, except letting the world know that I am tinkering with a new toy. :-) If it ever actually becomes useful, I&#8217;ll release it&#8230; Until then, I might talk more about it here.</p>
]]></content:encoded>
			<wfw:commentRss>http://4.flowsnake.org/archives/58/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

