
<?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>brewster's linnet . com &#187; factor</title>
	<atom:link href="http://www.brewsterslinnet.com/category/projects/factor/feed" rel="self" type="application/rss+xml" />
	<link>http://www.brewsterslinnet.com</link>
	<description>nature and stuff</description>
	<lastBuildDate>Wed, 01 Feb 2012 01:48:18 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.3</generator>
		<item>
		<title>Roman Numeral Fun</title>
		<link>http://www.brewsterslinnet.com/projects/factor/2007/03/08/roman-numeral-fun.html</link>
		<comments>http://www.brewsterslinnet.com/projects/factor/2007/03/08/roman-numeral-fun.html#comments</comments>
		<pubDate>Fri, 09 Mar 2007 03:26:00 +0000</pubDate>
		<dc:creator>jason</dc:creator>
				<category><![CDATA[factor]]></category>

		<guid isPermaLink="false">http://www.brewsterslinnet.com/http:/www.brewsterslinnet.com/category/post-name/</guid>
		<description><![CDATA[In my waiting-for-people-to-leave-so-I-can-get-into-classrooms time at work I wrote a roman numeral translator in Factor. It&#8217;s a bit different from your normal implementation as Factor&#8217;s parser actually does almost all the work: USING: strings parser kernel words sequences math ; : NUMERAL: CREATE dup reset-generic dup t "parsing" set-word-prop parse-definition \ parsed add define-compound ; parsing [...]]]></description>
			<content:encoded><![CDATA[<p>In my waiting-for-people-to-leave-so-I-can-get-into-classrooms time at work I wrote a roman numeral translator in Factor. It&#8217;s a bit different from your normal implementation as Factor&#8217;s parser actually does almost all the work:</p>
<pre><code>USING: strings parser kernel words sequences math ;

: NUMERAL: CREATE dup reset-generic dup t "parsing" set-word-prop parse-definition \ parsed add define-compound ; parsing

NUMERAL: I 1 ;
NUMERAL: IV 4 ;
NUMERAL: V 5 ;
NUMERAL: IX 9 ;
NUMERAL: X 10 ;
NUMERAL: XL 40 ;
NUMERAL: L 50 ;
NUMERAL: XC 90 ;
NUMERAL: C 100 ;
NUMERAL: CD 400 ;
NUMERAL: D 500 ;
NUMERAL: CM 900 ;
NUMERAL: M 1000 ;

: separate ( str -- str )
    "" swap [ " " append ] [ add ] interleave ;

: join-special ( str str -- str )
    dup &gt;r split1 [ 1 r&gt; remove-nth swap 3append ] [ r&gt; drop ] if* ;

: merge-specials ( str -- str )
    [ "I V" "I X" "X L" "X C" "C D" "C M" ] [ join-special ] each ;

: convert-numerals ( string -- arr )
    separate merge-specials parse ;

: all-numerals? ( str -- ? )
    [ "IVXLCDM" member? ] all? ;

: roman&gt;number ( roman -- number )
    &gt;upper dup all-numerals? [ convert-numerals sum ] [ drop "Not a roman numeral" ] if ;
</code></pre>
<p>Instead of grabbing characters and keeping a running tally, I defined a bunch of parsing words using <code>NUMERAL:</code> to hold the values. I then took the string and split it into individual characters (&#8220;XIV&#8221; becomes &#8220;X I V&#8221;). The 4&#8242;s and 9&#8242;s are then rejoined (so we get &#8220;X IV&#8221;). I then simply parse the string, which gives a list of numbers and sum that up. It&#8217;s not perfect as it allows any pattern of numerals (&#8220;IVIVIVIV&#8221; parsed to 22), but good enough.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.brewsterslinnet.com/projects/factor/2007/03/08/roman-numeral-fun.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Checklist</title>
		<link>http://www.brewsterslinnet.com/projects/factor/2007/02/25/checklist.html</link>
		<comments>http://www.brewsterslinnet.com/projects/factor/2007/02/25/checklist.html#comments</comments>
		<pubDate>Mon, 26 Feb 2007 02:15:00 +0000</pubDate>
		<dc:creator>jason</dc:creator>
				<category><![CDATA[factor]]></category>

		<guid isPermaLink="false">http://www.brewsterslinnet.com/http:/www.brewsterslinnet.com/category/post-name/</guid>
		<description><![CDATA[The code for generating the checklist is written in Factor. Factor is rather outside the mainstream, but it works beautifully for my purposes. I store the checklist data in a text file that looks like the following: CHECKLIST: FAMILY: Wrens SPECIES: Carolina Wren STATUS: Fairly common year-round. Can be found almost anywhere. There's too many [...]]]></description>
			<content:encoded><![CDATA[<p>The code for generating the <a href="/nature/birding/WalthamChecklist.html">checklist</a> is written in <a href="http://www.factorcode.org/">Factor</a>. Factor is rather outside the mainstream, but it works beautifully for my purposes.</p>
<p>I store the checklist data in a text file that looks like the following:</p>
<pre><code>CHECKLIST:
    FAMILY: Wrens
        SPECIES: Carolina Wren
            STATUS: Fairly common year-round. Can be found almost anywhere. There's too many around to not be breeding, but I have yet to find a nest.
            PB
        END

        SPECIES: House Wren
            STATUS: Regular in spring and summer. Possible almost anywhere. Young at Paine Estate imply breeding.
            CB
        END

        SPECIES: Winter Wren
            STATUS: Probably a rare visitor, possible at all seasons?
            RECORD: M. Emmons, 5/14/1997, ? , 2
            RECORD: R. Haaseth/D. Finch, 2/6/2004, near Prospect Hill, 1
            RECORD: R. Haaseth/D. Finch, 10/2005, ?, 1
            PERSONAL: 11/25/2006, Met State, 1
        END

        SPECIES: Marsh Wren
            STATUS: Likely a regular migrant and possibly a breeder at Waverly Oaks Marsh.
            RECORD: M. Rines, 4/20/2006, Waverly Oaks Marsh, 1
        END
    END

    HYPOTHETICAL: White-winged Crossbill | irruptive species
    HYPOTHETICAL: Hoary Redpoll | irruptive species

    HISTORICAL: Black Vulture | coming soon
    HISTORICAL: Boreal Chickadee | coming soon
    HISTORICAL: Louisiana Waterthrush | coming soon
</code></pre>
<p>This is a nice clean structure that is easy to parse. In fact, the code to parse it is <code>"USE: checklist\n" swap dup file-length swap &lt;file-reader&gt; stream-read append parse call ;</code> Yep, the checklist is actually code that parses itself.</p>
<p>To do this, I defined a few tuples:</p>
<ul>
<li><code>TUPLE: checklist confirmed hypotheticals historicals</code></li>
<li><code>TUPLE: family name species</code></li>
<li><code>TUPLE: species name status breeding records</code></li>
<li><code>TUPLE: record observer date place quantity</code></li>
<li><code>TUPLE: historical name details</code></li>
<li><code>TUPLE: hypothetical name reason</code></li>
</ul>
<p>Each one simply contains the data and stores anything below it in a vector. I then defined a bunch of words that handle the parsing.</p>
<ul>
<li><code>CHECKLIST:</code> creates a new checklist</li>
<li><code>FAMILY:</code> creates a new family and gives it the name of whatever is on the line</li>
<li><code>SPECIES:</code> does the same for species</li>
<li><code>STATUS:</code> stores the status</li>
<li><code>PB</code> and <code>CB</code> store the breeding</li>
<li><code>RECORD:</code> and <code>PERSONAL:</code> create and store records (<code>PERSONAL:</code> creates a record with observer &#8220;me&#8221;)</li>
<li><code>END</code> is a generic word that adds the species or family to the family or checklist respectively (I&#8217;d like to define it for the checklist as well, but the stack effects don&#8217;t match so it doesn&#8217;t work)</li>
<li><code>HISTORICAL:</code> and <code>HYPOTHETICAL:</code> do the obvious</li>
</ul>
<p>For the most part, defining those was straightforward. The trickiest part was dealing with status, as I had to be able to call a word for the next object on the stack after reading the status in. I ended up with the ugly</p>
<pre><code>: STATUS: rest-of-line swap ?push \ swap swap ?push \ set-species-status V{ } clone [ push ] keep &gt;quotation swap ?push \ keep swap ?push ; parsing
</code></pre>
<p>mess. I&#8217;m sure there&#8217;s a better way but that took a couple days to get and I haven&#8217;t fiddled with it since.</p>
<p>Getting from the checklist tuple to the output was pretty easy, just doing lots of formatting with <code>make</code> and working down.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.brewsterslinnet.com/projects/factor/2007/02/25/checklist.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

