<?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>gnu &#8211; CS@Worcester</title>
	<atom:link href="https://cs.worcester.edu/category/gnu/feed/" rel="self" type="application/rss+xml" />
	<link>https://cs.worcester.edu</link>
	<description>Worcester State University Computer Science Department</description>
	<lastBuildDate>Mon, 14 Sep 2015 19:00:00 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9</generator>
<site xmlns="com-wordpress:feed-additions:1">236835116</site>	<item>
		<title>Web Development with Guile Scheme</title>
		<link>http://dthompson.us/web-development-with-guile-scheme.html</link>
		
		<dc:creator><![CDATA[David Thompson]]></dc:creator>
		<pubDate>Mon, 14 Sep 2015 19:00:00 +0000</pubDate>
				<category><![CDATA[gnu]]></category>
		<category><![CDATA[guile]]></category>
		<category><![CDATA[scheme]]></category>
		<category><![CDATA[WSU]]></category>
		<guid isPermaLink="false">http://cs.worcester.edu/blog/?guid=bd8bad2c40f69e609486ac76bd04cde4</guid>

					<description><![CDATA[<p>Guile Scheme is a wonderful general-purpose programming language.  I
use it for simple scripting, systems programming, game programming,
and of course, web programming.  I think that, despite not having the
wealth of libraries available in Ruby/Java/etc., Guile provides an
excellent environment for web programming thanks to its advanced
features: First-class and higher-order functions, hygienic macros,
pattern matching, quasiquote, and REPL server.</p>
<p>Guile ships with a nice, small set of HTTP modules in the <tt>(web)</tt>
namespace that expose data types for URIs, HTTP requests, and HTTP
responses.  Guile also provides an HTTP client and server.  What makes
Guile's web modules stand out from a lot of other languages is that
they use <a href="https://www.gnu.org/software/guile/manual/html_node/Types-and-the-Web.html">expressive data types</a> to represent URIs and HTTP headers
rather than treating them as strings.  This eliminates an entire class
of bugs and security vulnerabilities caused by mishandling "stringly
typed" data, such as header injection.  Using expressive data types
will be a common theme amongst all components of the web programming
tools I will describe below.  Now, let's see how to write a web
application with Guile!</p>
<div>
<h2>Handling Requests</h2>
<p>WRITEME: Status quo: String-based routes</p>
<p>WRITEME: Guile: Pattern Matching</p>
</div>
<div>
<h2>Rendering Responses</h2>
<p>WRITEME: Status quo: String-based templating</p>
<p><a href="http://www.more-magic.net/posts/structurally-fixing-injection-bugs.html">injection bugs</a></p>
<p>WRITEME: Guile: SXML and SJSON</p>
</div>
<div>
<h2>Iterative Development</h2>
<p>WRITEME: Status quo: Auto-reloading changed files</p>
<p>WRITEME: Guile: REPL server</p>
</div>]]></description>
										<content:encoded><![CDATA[<p>Guile Scheme is a wonderful general-purpose programming language.  I<br />
use it for simple scripting, systems programming, game programming,<br />
and of course, web programming.  I think that, despite not having the<br />
wealth of libraries available in Ruby/Java/etc., Guile provides an<br />
excellent environment for web programming thanks to its advanced<br />
features: First-class and higher-order functions, hygienic macros,<br />
pattern matching, quasiquote, and REPL server.</p>
<p>Guile ships with a nice, small set of HTTP modules in the <tt class="docutils literal">(web)</tt><br />
namespace that expose data types for URIs, HTTP requests, and HTTP<br />
responses.  Guile also provides an HTTP client and server.  What makes<br />
Guile&#8217;s web modules stand out from a lot of other languages is that<br />
they use <a class="reference external" href="https://www.gnu.org/software/guile/manual/html_node/Types-and-the-Web.html">expressive data types</a> to represent URIs and HTTP headers<br />
rather than treating them as strings.  This eliminates an entire class<br />
of bugs and security vulnerabilities caused by mishandling &quot;stringly<br />
typed&quot; data, such as header injection.  Using expressive data types<br />
will be a common theme amongst all components of the web programming<br />
tools I will describe below.  Now, let&#8217;s see how to write a web<br />
application with Guile!</p>
<div class="section" id="handling-requests">
<h2>Handling Requests</h2>
<p>WRITEME: Status quo: String-based routes</p>
<p>WRITEME: Guile: Pattern Matching</p>
</div>
<div class="section" id="rendering-responses">
<h2>Rendering Responses</h2>
<p>WRITEME: Status quo: String-based templating</p>
<p><a class="reference external" href="http://www.more-magic.net/posts/structurally-fixing-injection-bugs.html">injection bugs</a></p>
<p>WRITEME: Guile: SXML and SJSON</p>
</div>
<div class="section" id="iterative-development">
<h2>Iterative Development</h2>
<p>WRITEME: Status quo: Auto-reloading changed files</p>
<p>WRITEME: Guile: REPL server</p>
</div>

<p class="syndicated-attribution"><em>From the blog <a href="http://dthompson.us/">dthompson</a> by <a href="https://cs.worcester.edu/author/0/" title="Read other posts by David Thompson">David Thompson</a></em> and used with permission of the author. All other rights reserved by the author.</p>]]></content:encoded>
					
		
		<enclosure url="" length="0" type="" />

		<post-id xmlns="com-wordpress:feed-additions:1">3977</post-id>	</item>
		<item>
		<title>call-with-container: Linux containers for GNU Guix</title>
		<link>http://dthompson.us/call-with-container-linux-containers-for-gnu-guix.html</link>
		
		<dc:creator><![CDATA[David Thompson]]></dc:creator>
		<pubDate>Mon, 14 Sep 2015 19:00:00 +0000</pubDate>
				<category><![CDATA[gnu]]></category>
		<category><![CDATA[guile]]></category>
		<category><![CDATA[guix]]></category>
		<category><![CDATA[scheme]]></category>
		<category><![CDATA[WSU]]></category>
		<guid isPermaLink="false">http://cs.worcester.edu/blog/?guid=944ef7cbb36b377282fdda8bff4618d6</guid>

					<description><![CDATA[<p>Containers have become a hot topic.  Docker, LXC, Rkt, systemd-nspawn,
etc. are popular and make a lot headlines on technology news websites.
There are even <a href="http://events.linuxfoundation.org/events/containercon">entire conferences</a> dedicated to "containerization."
The next release of <a href="https://gnu.org/s/guix">GNU Guix</a>, a purely functional package manager,
will feature basic support for Linux containers, dubbed
<tt><span>call-with-container</span></tt>.  GNU Guix is written in the Guile Scheme
programming language.  Thus, in typical Scheme fashion, we have used
the <tt><span>call-with-*</span></tt> naming convention (like our old friend
<tt><span>call-with-current-continuation</span></tt>, for example) to refer to the
container implementation, which allows the user to apply an arbitrary
Scheme procedure in a new, containerized process.  For those familiar
with Guile, it's like a fancier version of <tt><span>primitive-fork</span></tt>.  In
addition to forking via <tt>clone(2)</tt>, <tt><span>call-with-container</span></tt> unshares
resources such as the network, mount, and user namespaces from the
host system and creates a temporary file system in a chroot (though we
actually use <tt>pivot_root</tt> instead), among other things.</p>
<p>So, given the fast-paced world of Linux container development and the
companies investing huge sums of money into the aformentioned tools,
why add another implementation to the mix?  What's wrong with the
status quo?  What can Guix possibly add?  Let's dive into the
motivation behind Guix containers, how they differ from the status
quo, and how they solve issues that other implementations cannot.</p>
<div>
<h2>The Trouble with Disk Images</h2>
<p>The term "container" has in practice come to mean a disk image whose
binaries are run in a lightweight virtualization with kernel
namespaces.  Docker and friends work with raw disk images, or layers
of them, as their fundamental data unit.  There are several issues
with this approach.  This presents issues with regards to disk and
memory usage and file system complexity.  Containers typically include
the minimal core software of a GNU/Linux distribution within them,
plus the extra software that is application-specific.</p>
<p>WRITEME: Deduplicating software amongst containers via
content-addressable storage (/gnu/store) and full dependency graph</p>
</div>
<div>
<h2>Imperative vs. Functional - The Dockerfile Problem</h2>
<p>WRITEME: Functional &#62; Imperative.  Mention issues with imperative
Dockerfiles and how the order of operations influences how well the
cache is utilized.  Docker cannot possibly know the details that Guix
knows because Docker defers to other package managers to do things
that are opaque to it.</p>
</div>
<div>
<h2>Guix and GuixSD Containers</h2>
<p>WRITEME: Simple, unprivileged containers with 'guix environment'.  Add
example for sharing file systems from the host.</p>
<p>WRITEME: GuixSD containers with 'guix system container'.  Mention the
use of a real init system (dmd) and the full-system configuration
language.</p>
<p>WRITEME: An arbitrary Scheme script that launches a container, showing
that (guix build linux-container) is a generic library to be re-used as
you wish.</p>
</div>
<div>
<h2>Future Work</h2>
<p>WRITEME: The future: cgroups, networking, orchestration.  Reach out
for contributors.</p>
<p>As an aside, before I bid you farewell, dear reader: I live in the
Boston area and I'm looking for local meetups and conferences that
would welcome a technical presentation about GNU Guix and the benefits
of the functional package and configuration management paradigm.  If
you have the connections and I have piqued your interest, please send
an email to davet at gnu dot org.</p>
</div>]]></description>
										<content:encoded><![CDATA[<p>Containers have become a hot topic.  Docker, LXC, Rkt, systemd-nspawn,<br />
etc. are popular and make a lot headlines on technology news websites.<br />
There are even <a class="reference external" href="http://events.linuxfoundation.org/events/containercon">entire conferences</a> dedicated to &quot;containerization.&quot;<br />
The next release of <a class="reference external" href="https://gnu.org/s/guix">GNU Guix</a>, a purely functional package manager,<br />
will feature basic support for Linux containers, dubbed<br />
<tt class="docutils literal"><span class="pre">call-with-container</span></tt>.  GNU Guix is written in the Guile Scheme<br />
programming language.  Thus, in typical Scheme fashion, we have used<br />
the <tt class="docutils literal"><span class="pre">call-with-*</span></tt> naming convention (like our old friend<br />
<tt class="docutils literal"><span class="pre">call-with-current-continuation</span></tt>, for example) to refer to the<br />
container implementation, which allows the user to apply an arbitrary<br />
Scheme procedure in a new, containerized process.  For those familiar<br />
with Guile, it&#8217;s like a fancier version of <tt class="docutils literal"><span class="pre">primitive-fork</span></tt>.  In<br />
addition to forking via <tt class="docutils literal">clone(2)</tt>, <tt class="docutils literal"><span class="pre">call-with-container</span></tt> unshares<br />
resources such as the network, mount, and user namespaces from the<br />
host system and creates a temporary file system in a chroot (though we<br />
actually use <tt class="docutils literal">pivot_root</tt> instead), among other things.</p>
<p>So, given the fast-paced world of Linux container development and the<br />
companies investing huge sums of money into the aformentioned tools,<br />
why add another implementation to the mix?  What&#8217;s wrong with the<br />
status quo?  What can Guix possibly add?  Let&#8217;s dive into the<br />
motivation behind Guix containers, how they differ from the status<br />
quo, and how they solve issues that other implementations cannot.</p>
<div class="section" id="the-trouble-with-disk-images">
<h2>The Trouble with Disk Images</h2>
<p>The term &quot;container&quot; has in practice come to mean a disk image whose<br />
binaries are run in a lightweight virtualization with kernel<br />
namespaces.  Docker and friends work with raw disk images, or layers<br />
of them, as their fundamental data unit.  There are several issues<br />
with this approach.  This presents issues with regards to disk and<br />
memory usage and file system complexity.  Containers typically include<br />
the minimal core software of a GNU/Linux distribution within them,<br />
plus the extra software that is application-specific.</p>
<p>WRITEME: Deduplicating software amongst containers via<br />
content-addressable storage (/gnu/store) and full dependency graph</p>
</div>
<div class="section" id="imperative-vs-functional-the-dockerfile-problem">
<h2>Imperative vs. Functional &#8211; The Dockerfile Problem</h2>
<p>WRITEME: Functional &gt; Imperative.  Mention issues with imperative<br />
Dockerfiles and how the order of operations influences how well the<br />
cache is utilized.  Docker cannot possibly know the details that Guix<br />
knows because Docker defers to other package managers to do things<br />
that are opaque to it.</p>
</div>
<div class="section" id="guix-and-guixsd-containers">
<h2>Guix and GuixSD Containers</h2>
<p>WRITEME: Simple, unprivileged containers with &#8216;guix environment&#8217;.  Add<br />
example for sharing file systems from the host.</p>
<p>WRITEME: GuixSD containers with &#8216;guix system container&#8217;.  Mention the<br />
use of a real init system (dmd) and the full-system configuration<br />
language.</p>
<p>WRITEME: An arbitrary Scheme script that launches a container, showing<br />
that (guix build linux-container) is a generic library to be re-used as<br />
you wish.</p>
</div>
<div class="section" id="future-work">
<h2>Future Work</h2>
<p>WRITEME: The future: cgroups, networking, orchestration.  Reach out<br />
for contributors.</p>
<p>As an aside, before I bid you farewell, dear reader: I live in the<br />
Boston area and I&#8217;m looking for local meetups and conferences that<br />
would welcome a technical presentation about GNU Guix and the benefits<br />
of the functional package and configuration management paradigm.  If<br />
you have the connections and I have piqued your interest, please send<br />
an email to davet at gnu dot org.</p>
</div>

<p class="syndicated-attribution"><em>From the blog <a href="http://dthompson.us/">dthompson</a> by <a href="https://cs.worcester.edu/author/0/" title="Read other posts by David Thompson">David Thompson</a></em> and used with permission of the author. All other rights reserved by the author.</p>]]></content:encoded>
					
		
		<enclosure url="" length="0" type="" />

		<post-id xmlns="com-wordpress:feed-additions:1">3975</post-id>	</item>
		<item>
		<title>Ruby on Guix</title>
		<link>http://dthompson.us/ruby-on-guix.html</link>
		
		<dc:creator><![CDATA[David Thompson]]></dc:creator>
		<pubDate>Sun, 30 Aug 2015 19:00:00 +0000</pubDate>
				<category><![CDATA[gnu]]></category>
		<category><![CDATA[guile]]></category>
		<category><![CDATA[guix]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[scheme]]></category>
		<category><![CDATA[WSU]]></category>
		<guid isPermaLink="false">http://cs.worcester.edu/blog/?guid=cd8a17791ee842681e7b97c007621b14</guid>

					<description><![CDATA[<p>I've been working with Ruby professionally for over 3 years now and
I've grown frustrated with two of its most popular development tools:
RVM and Bundler.  For those that may not know, RVM is the Ruby version
manager and it allows unprivileged users to download, compile,
install, and manage many versions of Ruby instead of being stuck with
the one that is installed globally by your distro's package manager.
Bundler is the tool that allows developers to keep a version
controlled "Gemfile" that specifies all of the project's dependencies
and provides utilities to install and update those gems.  These tools
are crucial because Ruby developers often work with many applications
that use different versions of Ruby and/or different versions of gems
such as Rails.  Traditional GNU/Linux distributions install packages
to the global <tt>/usr</tt> directory, limiting users to a single version
of Ruby and associated gems, if they are packaged at all.  Traditional
package management fails to meet the needs of a lot of users, so many
niche package managers have been developed to supplement them.</p>
<p>Taking a step back, it becomes apparent that dependency isolation is a
general problem that isn't confined to software written in Ruby: Node
has npm and nvm, Python has pip and virtualenv, and so on.  A big
limitation of all these language-specific package managers is that
they cannot control what is outside of their language domain.  In
order to use RVM to successfully compile a version of Ruby, you need
to make sure you have the GCC toolchain, OpenSSL, readline, libffi,
etc. installed using the system package manager (note: I've seen RVM
try to build prerequisites like OpenSSL before, which I then disabled
to avoid duplication and security issues and I recommend you do the
same.)  In order to use Bundler to install Nokogiri, you need to make
sure libxml2 has been installed using the system package manager.  If
you work with more than a single language, the number of different
package management tools needed to get work done is staggering.  For
web applications, it's not uncommon to use RVM, Bundler, NPM, Bower,
and the system package manager simultaneously to get all of the
necessary programs and libraries.  Large web applications are
notoriously difficult to deploy, and companies hire a bunch of
operations folk like me to try to wrangle it all.</p>
<p>Anyway, let's forget about Node, Python, etc. and just focus on Ruby.
Have you or someone you work with encountered hard to debug issues and
Git merge conflicts due to a problem with <tt>Gemfile.lock</tt>?  Bundler's
fast and loose versioning in the <tt>Gemfile</tt> (e.g. <tt>rails &#62;= 4.0</tt>)
causes headaches when different users update different gems at
different times and check the resulting auto-generated
<tt>Gemfile.lock</tt> into the repository.  Have you ever been frustrated
that it's difficult to deduplicate gems that are shared between
multiple bundled gem sets?  Have you looked at the <a href="https://rvm.io/">RVM home page</a>
and been frustrated that they recommend you to <tt>curl &#124; bash</tt> to
install their software?  Have you been annoyed by RVM's strange system
of overriding shell built-ins in order to work its magic?  I'm not
sure how you feel, dear reader, but my Ruby environments feel like one
giant, brittle hack, and I'm often enough involved in fixing issues
with them on my own workstation, that of my colleagues, and on
production servers.</p>
<p>So, if you're still with me, what do we do about this?  How can we
work to improve upon the status quo?  Just use Docker?  Docker is
helpful, and certainly much better than no isolation at all, but it
hides the flaws of package management inside an opaque disk image and
restricts the environments in which your application is built to
function.  The general problem of dependency isolation is orthogonal
to the runtime environment, be it container, virtual machine, or "bare
metal."  Enter functional package management.  What does it mean for a
package manager to be functional?  GNU Guix, the functional package
manager that I contribute to and recommend, has this to say:</p>
<blockquote>
<p>GNU Guix is a functional package management tool for the GNU
system.  Package management consists of all activities that relate
to building packages from sources, honoring their build-time and
run-time dependencies, installing packages in user environments,
upgrading installed packages to new versions or rolling back to a
previous set, removing unused software packages, etc.</p>
<p>The term functional refers to a specific package management
discipline.  In Guix, the package build and installation process
is seen as a function, in the mathematical sense.  That function
takes inputs, such as build scripts, a compiler, and libraries,
and returns an installed package.</p>
</blockquote>
<p>Guix has a rich set of features, some of which you may find in other
package managers, but not all of them (unless you use another
functional package manager such as Nix.)  Gem/Bundler can do
unprivileged gem installation, but it cannot do transactional upgrades
and rollbacks or install non-Ruby dependencies.  Dpkg/yum/pacman can
install all build-time and rumtime dependencies, but it cannot do
unprivileged package installation to isolated user environments.  And
none of them can precisely describe the <em>full</em> dependency graph (all
the way down to the C compiler's compiler) but <em>Guix can</em>.</p>
<p>Guix is written in Guile, an implementation of the Scheme programming
language.  The upcoming release of Guix will feature a Ruby build
system that captures the process of installing gems from <tt>.gem</tt>
archives and a RubyGems import utility to make it easier to write Guix
packages by using the metadata available on <a href="https://rubygems.org/">https://rubygems.org</a>.
Ruby developers interested in functional package management are
encouraged to try packaging their gems (and dependencies) for Guix.</p>
<p>Now, how exactly can Guix replace RVM and Bundler?  Guix uses an
abstraction called a "profile" that represents a user-defined set of
packages that should work together.  Think of it as having many
<tt>/usr</tt> file system trees that can be used in isolation from the
others (without invoking virtualization technologies such as virtual
machines or containers.)  To install multiple versions of Ruby and
various gems, the user need only create a separate profile for them:</p>
<div><pre>guix package --profile=project-1 --install ruby-2.2 ruby-rspec-3
# Hypothetical packages:
guix package --profile=project-2 --install ruby-1.9 ruby-rspec-2
</pre></div>
<p>A profile is a "symlink forest" that is the union of all the packages
it includes, and files are deduplicated among all of them.  To
actually use the profile, the relevant environment variables must be
configured.  Guix is aware of such variables, and can tell you what to
set by running the following:</p>
<div><pre>guix package --search-paths --profile=project-1
</pre></div>
<p>Additionally, you can also create ad-hoc development environments with
the <tt>guix environment</tt> tool.  This tool will spawn a sub-shell (or
another program of your choice) in an environment in which a set of
specified packages are available.  This is my preferred method as it
automagically sets all of the environment variables for me and Guix is
free to garbage collect the packages when I close the sub-shell:</p>
<div><pre># Launch a Ruby REPL with ActiveSupport available.
guix environment --ad-hoc ruby ruby-activesupport -E irb
</pre></div>
<p>In order to make this environment reproducible for others, I recommend
keeping a <tt>package.scm</tt> file in version control that describes the
complete dependency graph for your project, as well as metadata such
as the license, version, and description:</p>
<div><pre><span>(</span><span>use-modules</span> <span>(</span><span>guix</span> <span>packages</span><span>)</span>
             <span>(</span><span>guix</span> <span>licenses</span><span>)</span>
             <span>(</span><span>guix</span> <span>build-system</span> <span>ruby</span><span>)</span>
             <span>(</span><span>gnu</span> <span>packages</span><span>)</span>
             <span>(</span><span>gnu</span> <span>packages</span> <span>version-control</span><span>)</span>
             <span>(</span><span>gnu</span> <span>packages</span> <span>ssh</span><span>)</span>
             <span>(</span><span>gnu</span> <span>packages</span> <span>ruby</span><span>))</span>

<span>(</span><span>package</span>
  <span>(</span><span>name</span> <span>"cool-ruby-project"</span><span>)</span>
  <span>(</span><span>version</span> <span>"1.0"</span><span>)</span>
  <span>(</span><span>source</span> <span>#f</span><span>)</span> <span>; not needed just to create dev environment</span>
  <span>(</span><span>build-system</span> <span>ruby-build-system</span><span>)</span>
  <span>;; These correspond roughly to "development" dependencies.</span>
  <span>(</span><span>native-inputs</span>
   <span>`</span><span>((</span><span>"git"</span> <span>,</span><span>git</span><span>)</span>
     <span>(</span><span>"openssh"</span> <span>,</span><span>openssh</span><span>)</span>
     <span>(</span><span>"ruby-rspec"</span> <span>,</span><span>ruby-rspec</span><span>)))</span>
  <span>(</span><span>propagated-inputs</span>
   <span>`</span><span>((</span><span>"ruby-pg"</span> <span>,</span><span>ruby-pg</span><span>)</span>
     <span>(</span><span>"ruby-nokogiri"</span> <span>,</span><span>ruby-nokogiri</span><span>)</span>
     <span>(</span><span>"ruby-i18n"</span> <span>,</span><span>ruby-i18n</span><span>)</span>
     <span>(</span><span>"ruby-rails"</span> <span>,</span><span>ruby-rails</span><span>)))</span>
  <span>(</span><span>synopsis</span> <span>"A cool Ruby project"</span><span>)</span>
  <span>(</span><span>description</span> <span>"This software does some cool stuff, trust me."</span><span>)</span>
  <span>(</span><span>home-page</span> <span>"https://example.com"</span><span>)</span>
  <span>(</span><span>license</span> <span>expat</span><span>))</span>
</pre></div>
<p>With this package file, it is simple to an instantiate a development
environment:</p>
<div><pre>guix environment -l package.scm
</pre></div>
<p>I'm not covering it in this post, but properly filling out the blank
<tt>source</tt> field above would allow for building development snapshots,
including running the test suite, in an isolated build container using
the <tt>guix build</tt> utility.  This is a very useful when composed with
a continuous integration system.  Guix itself uses <a href="https://nixos.org/hydra/">Hydra</a> as its CI
system to perform all package builds.</p>
<p>As mentioned earlier, one of the big advantages of writing Guix
package recipes is that the full dependency graph can be captured,
including non-Ruby components.  The pg gem provides a good example:</p>
<div><pre><span>(</span><span>define-public</span> <span>ruby-pg</span>
  <span>(</span><span>package</span>
    <span>(</span><span>name</span> <span>"ruby-pg"</span><span>)</span>
    <span>(</span><span>version</span> <span>"0.18.2"</span><span>)</span>
    <span>(</span><span>source</span>
     <span>(</span><span>origin</span>
       <span>(</span><span>method</span> <span>url-fetch</span><span>)</span>
       <span>(</span><span>uri</span> <span>(</span><span>rubygems-uri</span> <span>"pg"</span> <span>version</span><span>))</span>
       <span>(</span><span>sha256</span>
        <span>(</span><span>base32</span>
         <span>"1axxbf6ij1iqi3i1r3asvjc80b0py5bz0m2wy5kdi5xkrpr82kpf"</span><span>))))</span>
    <span>(</span><span>build-system</span> <span>ruby-build-system</span><span>)</span>
    <span>(</span><span>arguments</span>
     <span>'</span><span>(</span><span>#</span><span>:test-target</span> <span>"spec"</span><span>))</span>
    <span>;; Native inputs are used only at build and test time.</span>
    <span>(</span><span>native-inputs</span>
     <span>`</span><span>((</span><span>"ruby-rake-compiler"</span> <span>,</span><span>ruby-rake-compiler</span><span>)</span>
       <span>(</span><span>"ruby-hoe"</span> <span>,</span><span>ruby-hoe</span><span>)</span>
       <span>(</span><span>"ruby-rspec"</span> <span>,</span><span>ruby-rspec</span><span>)))</span>
    <span>;; Native extension links against PostgreSQL shared library.</span>
    <span>(</span><span>inputs</span>
     <span>`</span><span>((</span><span>"postgresql"</span> <span>,</span><span>postgresql</span><span>)))</span>
    <span>(</span><span>synopsis</span> <span>"Ruby interface to PostgreSQL"</span><span>)</span>
    <span>(</span><span>description</span> <span>"Pg is the Ruby interface to the PostgreSQL RDBMS.  It works</span>
<span>with PostgreSQL 8.4 and later."</span><span>)</span>
    <span>(</span><span>home-page</span> <span>"https://bitbucket.org/ged/ruby-pg"</span><span>)</span>
    <span>(</span><span>license</span> <span>license:ruby</span><span>)))</span>
</pre></div>
<p>Note how the recipe specifies the PostgreSQL dependency.  Below is the
dependency graph for ruby-pg as produced by <tt>guix graph</tt>, excluding
the GCC compiler toolchain and other low-level tools for brevity.
Pretty neat, eh?</p>
<img alt="" src="http://dthompson.us/images/guix/ruby-pg-graph.png"><p>Given that Guix doesn't yet have many gems packaged (help wanted), it
can still be advantageous to use it for getting more up-to-date
packages than many distros provide, but in conjuction with Bundler for
fetching Ruby gems.  This gets RVM out of your hair whilst creating a
migration path away from Bundler at a later time once the required
gems have been packaged:</p>
<div><pre>cd my-project/
guix environment --ad-hoc ruby bundler libxml2 libxslt # etc.
# A small bash script can be used to make these gem sets.
mkdir .gems
export GEM_HOME=$PWD/.gems
export GEM_PATH=$GEM_HOME:$GEM_PATH
export PATH=$GEM_HOME/bin:$PATH
bundle install
</pre></div>
<p>As you've seen in the above package snippets, Guix package definitions
are typically very short and rather easy to write yourself.  The
<tt>guix import gem</tt> tool was made to lower the barrier even more by
generating most of the boilerplate code.  For example:</p>
<div><pre>guix import gem pry
</pre></div>
<p>Produces this Scheme code:</p>
<div><pre><span>(</span><span>package</span>
  <span>(</span><span>name</span> <span>"ruby-pry"</span><span>)</span>
  <span>(</span><span>version</span> <span>"0.10.1"</span><span>)</span>
  <span>(</span><span>source</span>
    <span>(</span><span>origin</span>
      <span>(</span><span>method</span> <span>url-fetch</span><span>)</span>
      <span>(</span><span>uri</span> <span>(</span><span>rubygems-uri</span> <span>"pry"</span> <span>version</span><span>))</span>
      <span>(</span><span>sha256</span>
        <span>(</span><span>base32</span>
          <span>"1j0r5fm0wvdwzbh6d6apnp7c0n150hpm9zxpm5xvcgfqr36jaj8z"</span><span>))))</span>
  <span>(</span><span>build-system</span> <span>ruby-build-system</span><span>)</span>
  <span>(</span><span>propagated-inputs</span>
    <span>`</span><span>((</span><span>"ruby-coderay"</span> <span>,</span><span>ruby-coderay</span><span>)</span>
      <span>(</span><span>"ruby-method-source"</span> <span>,</span><span>ruby-method-source</span><span>)</span>
      <span>(</span><span>"ruby-slop"</span> <span>,</span><span>ruby-slop</span><span>)))</span>
  <span>(</span><span>synopsis</span>
    <span>"An IRB alternative and runtime developer console"</span><span>)</span>
  <span>(</span><span>description</span>
    <span>"An IRB alternative and runtime developer console"</span><span>)</span>
  <span>(</span><span>home-page</span> <span>"http://pryrepl.org"</span><span>)</span>
  <span>(</span><span>license</span> <span>expat</span><span>))</span>
</pre></div>
<p>One still has to package the propagated inputs if they aren't yet
available, add the necessary inputs for building native extensions if
needed, and fiddle with the native inputs needed to run the test
suite, but for most pure Ruby gems this gets you close to a working
package quickly.</p>
<p>In conclusion, while support for Ruby in Guix is still in its early
days, I hope that you have seen the benefits that using a
general-purpose, functional package manager can bring to your Ruby
environments (and all other environments, too.)  For more information
about Guix concepts, installation instructions, programming interface,
and tools, please refer to the <a href="https://gnu.org/software/guix/manual/">official manual</a>.  Check out the
<a href="https://gnu.org/software/guix/help/">help</a> page for ways to contact the development team for help or to
report bugs.  If you are interested in getting your hands dirty,
please <a href="https://gnu.org/software/guix/contribute/">contribute</a>.  Besides contributions of code, art, and docs,
we also need <a href="https://gnu.org/software/guix/donate/">hardware donations</a> to grow our build farm to meet the
needs of all our users.  Happy hacking!</p>]]></description>
										<content:encoded><![CDATA[<p>I&#8217;ve been working with Ruby professionally for over 3 years now and<br />
I&#8217;ve grown frustrated with two of its most popular development tools:<br />
RVM and Bundler.  For those that may not know, RVM is the Ruby version<br />
manager and it allows unprivileged users to download, compile,<br />
install, and manage many versions of Ruby instead of being stuck with<br />
the one that is installed globally by your distro&#8217;s package manager.<br />
Bundler is the tool that allows developers to keep a version<br />
controlled &quot;Gemfile&quot; that specifies all of the project&#8217;s dependencies<br />
and provides utilities to install and update those gems.  These tools<br />
are crucial because Ruby developers often work with many applications<br />
that use different versions of Ruby and/or different versions of gems<br />
such as Rails.  Traditional GNU/Linux distributions install packages<br />
to the global <tt class="docutils literal">/usr</tt> directory, limiting users to a single version<br />
of Ruby and associated gems, if they are packaged at all.  Traditional<br />
package management fails to meet the needs of a lot of users, so many<br />
niche package managers have been developed to supplement them.</p>
<p>Taking a step back, it becomes apparent that dependency isolation is a<br />
general problem that isn&#8217;t confined to software written in Ruby: Node<br />
has npm and nvm, Python has pip and virtualenv, and so on.  A big<br />
limitation of all these language-specific package managers is that<br />
they cannot control what is outside of their language domain.  In<br />
order to use RVM to successfully compile a version of Ruby, you need<br />
to make sure you have the GCC toolchain, OpenSSL, readline, libffi,<br />
etc. installed using the system package manager (note: I&#8217;ve seen RVM<br />
try to build prerequisites like OpenSSL before, which I then disabled<br />
to avoid duplication and security issues and I recommend you do the<br />
same.)  In order to use Bundler to install Nokogiri, you need to make<br />
sure libxml2 has been installed using the system package manager.  If<br />
you work with more than a single language, the number of different<br />
package management tools needed to get work done is staggering.  For<br />
web applications, it&#8217;s not uncommon to use RVM, Bundler, NPM, Bower,<br />
and the system package manager simultaneously to get all of the<br />
necessary programs and libraries.  Large web applications are<br />
notoriously difficult to deploy, and companies hire a bunch of<br />
operations folk like me to try to wrangle it all.</p>
<p>Anyway, let&#8217;s forget about Node, Python, etc. and just focus on Ruby.<br />
Have you or someone you work with encountered hard to debug issues and<br />
Git merge conflicts due to a problem with <tt class="docutils literal">Gemfile.lock</tt>?  Bundler&#8217;s<br />
fast and loose versioning in the <tt class="docutils literal">Gemfile</tt> (e.g. <tt class="docutils literal">rails &gt;= 4.0</tt>)<br />
causes headaches when different users update different gems at<br />
different times and check the resulting auto-generated<br />
<tt class="docutils literal">Gemfile.lock</tt> into the repository.  Have you ever been frustrated<br />
that it&#8217;s difficult to deduplicate gems that are shared between<br />
multiple bundled gem sets?  Have you looked at the <a class="reference external" href="https://rvm.io/">RVM home page</a><br />
and been frustrated that they recommend you to <tt class="docutils literal">curl | bash</tt> to<br />
install their software?  Have you been annoyed by RVM&#8217;s strange system<br />
of overriding shell built-ins in order to work its magic?  I&#8217;m not<br />
sure how you feel, dear reader, but my Ruby environments feel like one<br />
giant, brittle hack, and I&#8217;m often enough involved in fixing issues<br />
with them on my own workstation, that of my colleagues, and on<br />
production servers.</p>
<p>So, if you&#8217;re still with me, what do we do about this?  How can we<br />
work to improve upon the status quo?  Just use Docker?  Docker is<br />
helpful, and certainly much better than no isolation at all, but it<br />
hides the flaws of package management inside an opaque disk image and<br />
restricts the environments in which your application is built to<br />
function.  The general problem of dependency isolation is orthogonal<br />
to the runtime environment, be it container, virtual machine, or &quot;bare<br />
metal.&quot;  Enter functional package management.  What does it mean for a<br />
package manager to be functional?  GNU Guix, the functional package<br />
manager that I contribute to and recommend, has this to say:</p>
<blockquote>
<p>GNU Guix is a functional package management tool for the GNU<br />
system.  Package management consists of all activities that relate<br />
to building packages from sources, honoring their build-time and<br />
run-time dependencies, installing packages in user environments,<br />
upgrading installed packages to new versions or rolling back to a<br />
previous set, removing unused software packages, etc.</p>
<p>The term functional refers to a specific package management<br />
discipline.  In Guix, the package build and installation process<br />
is seen as a function, in the mathematical sense.  That function<br />
takes inputs, such as build scripts, a compiler, and libraries,<br />
and returns an installed package.</p>
</blockquote>
<p>Guix has a rich set of features, some of which you may find in other<br />
package managers, but not all of them (unless you use another<br />
functional package manager such as Nix.)  Gem/Bundler can do<br />
unprivileged gem installation, but it cannot do transactional upgrades<br />
and rollbacks or install non-Ruby dependencies.  Dpkg/yum/pacman can<br />
install all build-time and rumtime dependencies, but it cannot do<br />
unprivileged package installation to isolated user environments.  And<br />
none of them can precisely describe the <em>full</em> dependency graph (all<br />
the way down to the C compiler&#8217;s compiler) but <em>Guix can</em>.</p>
<p>Guix is written in Guile, an implementation of the Scheme programming<br />
language.  The upcoming release of Guix will feature a Ruby build<br />
system that captures the process of installing gems from <tt class="docutils literal">.gem</tt><br />
archives and a RubyGems import utility to make it easier to write Guix<br />
packages by using the metadata available on <a class="reference external" href="https://rubygems.org/">https://rubygems.org</a>.<br />
Ruby developers interested in functional package management are<br />
encouraged to try packaging their gems (and dependencies) for Guix.</p>
<p>Now, how exactly can Guix replace RVM and Bundler?  Guix uses an<br />
abstraction called a &quot;profile&quot; that represents a user-defined set of<br />
packages that should work together.  Think of it as having many<br />
<tt class="docutils literal">/usr</tt> file system trees that can be used in isolation from the<br />
others (without invoking virtualization technologies such as virtual<br />
machines or containers.)  To install multiple versions of Ruby and<br />
various gems, the user need only create a separate profile for them:</p>
<div class="highlight">
<pre>guix package --profile=project-1 --install ruby-2.2 ruby-rspec-3
# Hypothetical packages:
guix package --profile=project-2 --install ruby-1.9 ruby-rspec-2
</pre>
</div>
<p>A profile is a &quot;symlink forest&quot; that is the union of all the packages<br />
it includes, and files are deduplicated among all of them.  To<br />
actually use the profile, the relevant environment variables must be<br />
configured.  Guix is aware of such variables, and can tell you what to<br />
set by running the following:</p>
<div class="highlight">
<pre>guix package --search-paths --profile=project-1
</pre>
</div>
<p>Additionally, you can also create ad-hoc development environments with<br />
the <tt class="docutils literal">guix environment</tt> tool.  This tool will spawn a sub-shell (or<br />
another program of your choice) in an environment in which a set of<br />
specified packages are available.  This is my preferred method as it<br />
automagically sets all of the environment variables for me and Guix is<br />
free to garbage collect the packages when I close the sub-shell:</p>
<div class="highlight">
<pre># Launch a Ruby REPL with ActiveSupport available.
guix environment --ad-hoc ruby ruby-activesupport -E irb
</pre>
</div>
<p>In order to make this environment reproducible for others, I recommend<br />
keeping a <tt class="docutils literal">package.scm</tt> file in version control that describes the<br />
complete dependency graph for your project, as well as metadata such<br />
as the license, version, and description:</p>
<div class="highlight">
<pre><span class="p">(</span><span class="nf">use-modules</span> <span class="p">(</span><span class="nf">guix</span> <span class="nv">packages</span><span class="p">)</span>
             <span class="p">(</span><span class="nf">guix</span> <span class="nv">licenses</span><span class="p">)</span>
             <span class="p">(</span><span class="nf">guix</span> <span class="nv">build-system</span> <span class="nv">ruby</span><span class="p">)</span>
             <span class="p">(</span><span class="nf">gnu</span> <span class="nv">packages</span><span class="p">)</span>
             <span class="p">(</span><span class="nf">gnu</span> <span class="nv">packages</span> <span class="nv">version-control</span><span class="p">)</span>
             <span class="p">(</span><span class="nf">gnu</span> <span class="nv">packages</span> <span class="nv">ssh</span><span class="p">)</span>
             <span class="p">(</span><span class="nf">gnu</span> <span class="nv">packages</span> <span class="nv">ruby</span><span class="p">))</span>

<span class="p">(</span><span class="nf">package</span>
  <span class="p">(</span><span class="nf">name</span> <span class="s">&quot;cool-ruby-project&quot;</span><span class="p">)</span>
  <span class="p">(</span><span class="nf">version</span> <span class="s">&quot;1.0&quot;</span><span class="p">)</span>
  <span class="p">(</span><span class="nf">source</span> <span class="no">#f</span><span class="p">)</span> <span class="c1">; not needed just to create dev environment</span>
  <span class="p">(</span><span class="nf">build-system</span> <span class="nv">ruby-build-system</span><span class="p">)</span>
  <span class="c1">;; These correspond roughly to &quot;development&quot; dependencies.</span>
  <span class="p">(</span><span class="nf">native-inputs</span>
   <span class="o">`</span><span class="p">((</span><span class="s">&quot;git&quot;</span> <span class="o">,</span><span class="nv">git</span><span class="p">)</span>
     <span class="p">(</span><span class="s">&quot;openssh&quot;</span> <span class="o">,</span><span class="nv">openssh</span><span class="p">)</span>
     <span class="p">(</span><span class="s">&quot;ruby-rspec&quot;</span> <span class="o">,</span><span class="nv">ruby-rspec</span><span class="p">)))</span>
  <span class="p">(</span><span class="nf">propagated-inputs</span>
   <span class="o">`</span><span class="p">((</span><span class="s">&quot;ruby-pg&quot;</span> <span class="o">,</span><span class="nv">ruby-pg</span><span class="p">)</span>
     <span class="p">(</span><span class="s">&quot;ruby-nokogiri&quot;</span> <span class="o">,</span><span class="nv">ruby-nokogiri</span><span class="p">)</span>
     <span class="p">(</span><span class="s">&quot;ruby-i18n&quot;</span> <span class="o">,</span><span class="nv">ruby-i18n</span><span class="p">)</span>
     <span class="p">(</span><span class="s">&quot;ruby-rails&quot;</span> <span class="o">,</span><span class="nv">ruby-rails</span><span class="p">)))</span>
  <span class="p">(</span><span class="nf">synopsis</span> <span class="s">&quot;A cool Ruby project&quot;</span><span class="p">)</span>
  <span class="p">(</span><span class="nf">description</span> <span class="s">&quot;This software does some cool stuff, trust me.&quot;</span><span class="p">)</span>
  <span class="p">(</span><span class="nf">home-page</span> <span class="s">&quot;https://example.com&quot;</span><span class="p">)</span>
  <span class="p">(</span><span class="nf">license</span> <span class="nv">expat</span><span class="p">))</span>
</pre>
</div>
<p>With this package file, it is simple to an instantiate a development<br />
environment:</p>
<div class="highlight">
<pre>guix environment -l package.scm
</pre>
</div>
<p>I&#8217;m not covering it in this post, but properly filling out the blank<br />
<tt class="docutils literal">source</tt> field above would allow for building development snapshots,<br />
including running the test suite, in an isolated build container using<br />
the <tt class="docutils literal">guix build</tt> utility.  This is a very useful when composed with<br />
a continuous integration system.  Guix itself uses <a class="reference external" href="https://nixos.org/hydra/">Hydra</a> as its CI<br />
system to perform all package builds.</p>
<p>As mentioned earlier, one of the big advantages of writing Guix<br />
package recipes is that the full dependency graph can be captured,<br />
including non-Ruby components.  The pg gem provides a good example:</p>
<div class="highlight">
<pre><span class="p">(</span><span class="nf">define-public</span> <span class="nv">ruby-pg</span>
  <span class="p">(</span><span class="nf">package</span>
    <span class="p">(</span><span class="nf">name</span> <span class="s">&quot;ruby-pg&quot;</span><span class="p">)</span>
    <span class="p">(</span><span class="nf">version</span> <span class="s">&quot;0.18.2&quot;</span><span class="p">)</span>
    <span class="p">(</span><span class="nf">source</span>
     <span class="p">(</span><span class="nf">origin</span>
       <span class="p">(</span><span class="nf">method</span> <span class="nv">url-fetch</span><span class="p">)</span>
       <span class="p">(</span><span class="nf">uri</span> <span class="p">(</span><span class="nf">rubygems-uri</span> <span class="s">&quot;pg&quot;</span> <span class="nv">version</span><span class="p">))</span>
       <span class="p">(</span><span class="nf">sha256</span>
        <span class="p">(</span><span class="nf">base32</span>
         <span class="s">&quot;1axxbf6ij1iqi3i1r3asvjc80b0py5bz0m2wy5kdi5xkrpr82kpf&quot;</span><span class="p">))))</span>
    <span class="p">(</span><span class="nf">build-system</span> <span class="nv">ruby-build-system</span><span class="p">)</span>
    <span class="p">(</span><span class="nf">arguments</span>
     <span class="o">&#39;</span><span class="p">(</span><span class="o">#</span><span class="nv">:test-target</span> <span class="s">&quot;spec&quot;</span><span class="p">))</span>
    <span class="c1">;; Native inputs are used only at build and test time.</span>
    <span class="p">(</span><span class="nf">native-inputs</span>
     <span class="o">`</span><span class="p">((</span><span class="s">&quot;ruby-rake-compiler&quot;</span> <span class="o">,</span><span class="nv">ruby-rake-compiler</span><span class="p">)</span>
       <span class="p">(</span><span class="s">&quot;ruby-hoe&quot;</span> <span class="o">,</span><span class="nv">ruby-hoe</span><span class="p">)</span>
       <span class="p">(</span><span class="s">&quot;ruby-rspec&quot;</span> <span class="o">,</span><span class="nv">ruby-rspec</span><span class="p">)))</span>
    <span class="c1">;; Native extension links against PostgreSQL shared library.</span>
    <span class="p">(</span><span class="nf">inputs</span>
     <span class="o">`</span><span class="p">((</span><span class="s">&quot;postgresql&quot;</span> <span class="o">,</span><span class="nv">postgresql</span><span class="p">)))</span>
    <span class="p">(</span><span class="nf">synopsis</span> <span class="s">&quot;Ruby interface to PostgreSQL&quot;</span><span class="p">)</span>
    <span class="p">(</span><span class="nf">description</span> <span class="s">&quot;Pg is the Ruby interface to the PostgreSQL RDBMS.  It works</span>
<span class="s">with PostgreSQL 8.4 and later.&quot;</span><span class="p">)</span>
    <span class="p">(</span><span class="nf">home-page</span> <span class="s">&quot;https://bitbucket.org/ged/ruby-pg&quot;</span><span class="p">)</span>
    <span class="p">(</span><span class="nf">license</span> <span class="nv">license:ruby</span><span class="p">)))</span>
</pre>
</div>
<p>Note how the recipe specifies the PostgreSQL dependency.  Below is the<br />
dependency graph for ruby-pg as produced by <tt class="docutils literal">guix graph</tt>, excluding<br />
the GCC compiler toolchain and other low-level tools for brevity.<br />
Pretty neat, eh?</p>
<p><img data-recalc-dims="1" decoding="async" alt="" src="https://i0.wp.com/dthompson.us/images/guix/ruby-pg-graph.png?w=625" /></p>
<p>Given that Guix doesn&#8217;t yet have many gems packaged (help wanted), it<br />
can still be advantageous to use it for getting more up-to-date<br />
packages than many distros provide, but in conjuction with Bundler for<br />
fetching Ruby gems.  This gets RVM out of your hair whilst creating a<br />
migration path away from Bundler at a later time once the required<br />
gems have been packaged:</p>
<div class="highlight">
<pre>cd my-project/
guix environment --ad-hoc ruby bundler libxml2 libxslt # etc.
# A small bash script can be used to make these gem sets.
mkdir .gems
export GEM_HOME=$PWD/.gems
export GEM_PATH=$GEM_HOME:$GEM_PATH
export PATH=$GEM_HOME/bin:$PATH
bundle install
</pre>
</div>
<p>As you&#8217;ve seen in the above package snippets, Guix package definitions<br />
are typically very short and rather easy to write yourself.  The<br />
<tt class="docutils literal">guix import gem</tt> tool was made to lower the barrier even more by<br />
generating most of the boilerplate code.  For example:</p>
<div class="highlight">
<pre>guix import gem pry
</pre>
</div>
<p>Produces this Scheme code:</p>
<div class="highlight">
<pre><span class="p">(</span><span class="nf">package</span>
  <span class="p">(</span><span class="nf">name</span> <span class="s">&quot;ruby-pry&quot;</span><span class="p">)</span>
  <span class="p">(</span><span class="nf">version</span> <span class="s">&quot;0.10.1&quot;</span><span class="p">)</span>
  <span class="p">(</span><span class="nf">source</span>
    <span class="p">(</span><span class="nf">origin</span>
      <span class="p">(</span><span class="nf">method</span> <span class="nv">url-fetch</span><span class="p">)</span>
      <span class="p">(</span><span class="nf">uri</span> <span class="p">(</span><span class="nf">rubygems-uri</span> <span class="s">&quot;pry&quot;</span> <span class="nv">version</span><span class="p">))</span>
      <span class="p">(</span><span class="nf">sha256</span>
        <span class="p">(</span><span class="nf">base32</span>
          <span class="s">&quot;1j0r5fm0wvdwzbh6d6apnp7c0n150hpm9zxpm5xvcgfqr36jaj8z&quot;</span><span class="p">))))</span>
  <span class="p">(</span><span class="nf">build-system</span> <span class="nv">ruby-build-system</span><span class="p">)</span>
  <span class="p">(</span><span class="nf">propagated-inputs</span>
    <span class="o">`</span><span class="p">((</span><span class="s">&quot;ruby-coderay&quot;</span> <span class="o">,</span><span class="nv">ruby-coderay</span><span class="p">)</span>
      <span class="p">(</span><span class="s">&quot;ruby-method-source&quot;</span> <span class="o">,</span><span class="nv">ruby-method-source</span><span class="p">)</span>
      <span class="p">(</span><span class="s">&quot;ruby-slop&quot;</span> <span class="o">,</span><span class="nv">ruby-slop</span><span class="p">)))</span>
  <span class="p">(</span><span class="nf">synopsis</span>
    <span class="s">&quot;An IRB alternative and runtime developer console&quot;</span><span class="p">)</span>
  <span class="p">(</span><span class="nf">description</span>
    <span class="s">&quot;An IRB alternative and runtime developer console&quot;</span><span class="p">)</span>
  <span class="p">(</span><span class="nf">home-page</span> <span class="s">&quot;http://pryrepl.org&quot;</span><span class="p">)</span>
  <span class="p">(</span><span class="nf">license</span> <span class="nv">expat</span><span class="p">))</span>
</pre>
</div>
<p>One still has to package the propagated inputs if they aren&#8217;t yet<br />
available, add the necessary inputs for building native extensions if<br />
needed, and fiddle with the native inputs needed to run the test<br />
suite, but for most pure Ruby gems this gets you close to a working<br />
package quickly.</p>
<p>In conclusion, while support for Ruby in Guix is still in its early<br />
days, I hope that you have seen the benefits that using a<br />
general-purpose, functional package manager can bring to your Ruby<br />
environments (and all other environments, too.)  For more information<br />
about Guix concepts, installation instructions, programming interface,<br />
and tools, please refer to the <a class="reference external" href="https://gnu.org/software/guix/manual/">official manual</a>.  Check out the<br />
<a class="reference external" href="https://gnu.org/software/guix/help/">help</a> page for ways to contact the development team for help or to<br />
report bugs.  If you are interested in getting your hands dirty,<br />
please <a class="reference external" href="https://gnu.org/software/guix/contribute/">contribute</a>.  Besides contributions of code, art, and docs,<br />
we also need <a class="reference external" href="https://gnu.org/software/guix/donate/">hardware donations</a> to grow our build farm to meet the<br />
needs of all our users.  Happy hacking!</p>

<p class="syndicated-attribution"><em>From the blog <a href="http://dthompson.us/">dthompson</a> by <a href="https://cs.worcester.edu/author/0/" title="Read other posts by David Thompson">David Thompson</a></em> and used with permission of the author. All other rights reserved by the author.</p>]]></content:encoded>
					
		
		<enclosure url="" length="0" type="" />

		<post-id xmlns="com-wordpress:feed-additions:1">3972</post-id>	</item>
		<item>
		<title>Rendering HTML with SXML and GNU Guile</title>
		<link>http://dthompson.us/rendering-html-with-sxml-and-gnu-guile.html</link>
		
		<dc:creator><![CDATA[David Thompson]]></dc:creator>
		<pubDate>Fri, 10 Apr 2015 22:00:00 +0000</pubDate>
				<category><![CDATA[gnu]]></category>
		<category><![CDATA[guile]]></category>
		<category><![CDATA[WSU]]></category>
		<guid isPermaLink="false">http://cs.worcester.edu/blog/?guid=d42b50980e7b9f24b4601d30b229e13d</guid>

					<description><![CDATA[<p>GNU Guile provides modules for working with XML documents called SXML.
SXML provides an elegant way of writing XML documents as s-expressions
that can be easily manipulated in Scheme.  Here's an example:</p>
<div><pre><span>(</span><span>sxml-&#62;xml</span> <span>'</span><span>(</span><span>foo</span> <span>(</span><span>bar</span> <span>(</span><span>@</span> <span>(</span><span>attr</span> <span>"something"</span><span>)))))</span>
</pre></div>
<div><pre><span>&#60;foo&#62;&#60;bar</span> <span>attr=</span><span>"something"</span> <span>/&#62;&#60;/foo&#62;</span>
</pre></div>
<p>I don't know about you, but I work with HTML documents much more often
than XML.  Since HTML is very similar to XML, we should be able to
represent it with SXML, too!</p>
<div><pre><span>(</span><span>sxml-&#62;xml</span> <span>'</span><span>(</span><span>html</span>
             <span>(</span><span>head</span>
              <span>(</span><span>title</span> <span>"Hello, world!"</span><span>)</span>
              <span>(</span><span>script</span> <span>(</span><span>@</span> <span>(</span><span>src</span> <span>"foo.js"</span><span>))))</span>
             <span>(</span><span>body</span>
              <span>(</span><span>h1</span> <span>"Hello!"</span><span>))))</span>
</pre></div>
<div><pre><span>&#60;html&#62;</span>
  <span>&#60;head&#62;</span>
    <span>&#60;title&#62;</span>Hello, world!<span>&#60;/title&#62;</span>
    <span>&#60;script </span><span>src=</span><span>"foo.js"</span> <span>/&#62;</span><span> &#60;!-- what? --&#62;</span>
  <span>&#60;/head&#62;</span>
  <span>&#60;body&#62;</span>
    <span>&#60;h1&#62;</span>Hello!<span>&#60;/h1&#62;</span>
  <span>&#60;/body&#62;</span>
<span>&#60;/html&#62;</span>
</pre></div>
<p>That <tt>&#60;script&#62;</tt> tag doesn't look right!  Script tags don't close
themselves like that.  Well, we could hack around it:</p>
<div><pre><span>(</span><span>sxml-&#62;xml</span> <span>'</span><span>(</span><span>html</span>
             <span>(</span><span>head</span>
              <span>(</span><span>title</span> <span>"Hello, world!"</span><span>)</span>
              <span>(</span><span>script</span> <span>(</span><span>@</span> <span>(</span><span>src</span> <span>"foo.js"</span><span>))</span> <span>""</span><span>))</span>
             <span>(</span><span>body</span>
              <span>(</span><span>h1</span> <span>"Hello!"</span><span>))))</span>
</pre></div>
<div><pre><span>&#60;html&#62;</span>
  <span>&#60;head&#62;</span>
    <span>&#60;title&#62;</span>Hello, world!<span>&#60;/title&#62;</span>
    <span>&#60;script </span><span>src=</span><span>"foo.js"</span><span>&#62;&#60;/script&#62;</span>
  <span>&#60;/head&#62;</span>
  <span>&#60;body&#62;</span>
    <span>&#60;h1&#62;</span>Hello!<span>&#60;/h1&#62;</span>
  <span>&#60;/body&#62;</span>
<span>&#60;/html&#62;</span>
</pre></div>
<p>Note the use of the empty string in <tt>(script (@ (src <span>"foo.js"))</span>
"")</tt>.  The output looks correct now, great!  But what about the other
void elements?  We'll have to remember to use the empty string hack
each time we use one.  That doesn't sound very elegant.</p>
<p>Furthermore, text isn't even escaped properly!</p>
<div><pre><span>(</span><span>sxml-&#62;xml</span> <span>"Copyright &#169; 2015  David Thompson &#60;davet@gnu.org&#62;"</span><span>)</span>
</pre></div>
<div><pre>Copyright &#169; 2015  David Thompson <span>&#38;lt;</span>davet@gnu.org<span>&#38;gt;</span>
</pre></div>
<p>The <tt>&#60;</tt> and <tt>&#62;</tt> braces were escaped, but <tt>&#169;</tt> should've been
rendered as <tt>&#38;copy;</tt>.  Why does this fail, too?  Is there a bug in
SXML?</p>
<p>There's no bug.  The improper rendering happens because HTML, while
similar to XML, has a bunch of different syntax rules.  Instead of
using <tt><span>sxml-&#62;xml</span></tt>, a new procedure that is tailored to the HTML
syntax is needed.  Introducing <tt><span>sxml-&#62;html</span></tt>:</p>
<div><pre><span>(</span><span>define*</span> <span>(</span><span>sxml-&#62;html</span> <span>tree</span> <span>#</span><span>:optional</span> <span>(</span><span>port</span> <span>(</span><span>current-output-port</span><span>)))</span>
  <span>"Write the serialized HTML form of TREE to PORT."</span>
  <span>(</span><span>match</span> <span>tree</span>
    <span>(()</span> <span>*unspecified*</span><span>)</span>
    <span>((</span><span>'doctype</span> <span>type</span><span>)</span>
     <span>(</span><span>doctype-&#62;html</span> <span>type</span> <span>port</span><span>))</span>
    <span>;; Unescaped, raw HTML output</span>
    <span>((</span><span>'raw</span> <span>html</span><span>)</span>
     <span>(</span><span>display </span><span>html</span> <span>port</span><span>))</span>
    <span>(((</span><span>?</span> <span>symbol?</span> <span>tag</span><span>)</span> <span>(</span><span>'@</span> <span>attrs</span> <span>...</span><span>)</span> <span>body</span> <span>...</span><span>)</span>
     <span>(</span><span>element-&#62;html</span> <span>tag</span> <span>attrs</span> <span>body</span> <span>port</span><span>))</span>
    <span>(((</span><span>?</span> <span>symbol?</span> <span>tag</span><span>)</span> <span>body</span> <span>...</span><span>)</span>
     <span>(</span><span>element-&#62;html</span> <span>tag</span> <span>'</span><span>()</span> <span>body</span> <span>port</span><span>))</span>
    <span>((</span><span>nodes</span> <span>...</span><span>)</span>
     <span>(</span><span>for-each </span><span>(</span><span>cut</span> <span>sxml-&#62;html</span> <span>&#60;&#62;</span> <span>port</span><span>)</span> <span>nodes</span><span>))</span>
    <span>((</span><span>?</span> <span>string?</span> <span>text</span><span>)</span>
     <span>(</span><span>string-&#62;escaped-html</span> <span>text</span> <span>port</span><span>))</span>
    <span>;; Render arbitrary Scheme objects, too.</span>
    <span>(</span><span>obj</span> <span>(</span><span>object-&#62;escaped-html</span> <span>obj</span> <span>port</span><span>))))</span>
</pre></div>
<p>In addition to being aware of void elements and escape characters, it
can also render <tt>'(doctype "html")</tt> as <tt>&#60;!DOCTYPE html&#62;</tt>, or
render an unescaped HTML string using <tt>'(raw "frog &#38;amp; toad")</tt>.</p>
<p>Here's the full version of my <tt>(sxml html)</tt> module.  It's quite
brief, if you don't count the ~250 lines of escape codes!  This code
requires Guile 2.0.11 or greater.</p>
<p>Happy hacking!</p>
<div><pre><span>(</span><span>define-module</span> <span>(</span><span>sxml</span> <span>html</span><span>)</span>
  <span>#</span><span>:use-module</span> <span>(</span><span>sxml</span> <span>simple</span><span>)</span>
  <span>#</span><span>:use-module</span> <span>(</span><span>srfi</span> <span>srfi-26</span><span>)</span>
  <span>#</span><span>:use-module</span> <span>(</span><span>ice-9</span> <span>match</span><span>)</span>
  <span>#</span><span>:use-module</span> <span>(</span><span>ice-9</span> <span>format</span><span>)</span>
  <span>#</span><span>:use-module</span> <span>(</span><span>ice-9</span> <span>hash-table</span><span>)</span>
  <span>#</span><span>:export</span> <span>(</span><span>sxml-&#62;html</span><span>))</span>

<span>(</span><span>define </span><span>%void-elements</span>
  <span>'</span><span>(</span><span>area</span>
    <span>base</span>
    <span>br</span>
    <span>col</span>
    <span>command</span>
    <span>embed</span>
    <span>hr</span>
    <span>img</span>
    <span>input</span>
    <span>keygen</span>
    <span>link</span>
    <span>meta</span>
    <span>param</span>
    <span>source</span>
    <span>track</span>
    <span>wbr</span><span>))</span>

<span>(</span><span>define </span><span>(</span><span>void-element?</span> <span>tag</span><span>)</span>
  <span>"Return #t if TAG is a void element."</span>
  <span>(</span><span>pair? </span><span>(</span><span>memq </span><span>tag</span> <span>%void-elements</span><span>)))</span>

<span>(</span><span>define </span><span>%escape-chars</span>
  <span>(</span><span>alist-&#62;hash-table</span>
   <span>'</span><span>((</span><span>#"</span> <span>.</span> <span>"quot"</span><span>)</span>
     <span>(</span><span>#&#38;</span> <span>.</span> <span>"amp"</span><span>)</span>
     <span>(</span><span>#'</span> <span>.</span> <span>"apos"</span><span>)</span>
     <span>(</span><span>#</span><span></span><span>&#60;</span> <span>.</span> <span>"lt"</span><span>)</span>
     <span>(</span><span>#</span><span></span><span>&#62;</span> <span>.</span> <span>"gt"</span><span>)</span>
     <span>(</span><span>#</span><span>&#161;</span> <span>.</span> <span>"iexcl"</span><span>)</span>
     <span>(</span><span>#</span><span>&#162;</span> <span>.</span> <span>"cent"</span><span>)</span>
     <span>(</span><span>#</span><span>&#163;</span> <span>.</span> <span>"pound"</span><span>)</span>
     <span>(</span><span>#</span><span>&#164;</span> <span>.</span> <span>"curren"</span><span>)</span>
     <span>(</span><span>#</span><span>&#165;</span> <span>.</span> <span>"yen"</span><span>)</span>
     <span>(</span><span>#</span><span>&#166;</span> <span>.</span> <span>"brvbar"</span><span>)</span>
     <span>(</span><span>#&#167;</span> <span>.</span> <span>"sect"</span><span>)</span>
     <span>(</span><span>#</span><span>&#168;</span> <span>.</span> <span>"uml"</span><span>)</span>
     <span>(</span><span>#</span><span>&#169;</span> <span>.</span> <span>"copy"</span><span>)</span>
     <span>(</span><span>#</span><span>&#170;</span> <span>.</span> <span>"ordf"</span><span>)</span>
     <span>(</span><span>#</span><span>&#171;</span> <span>.</span> <span>"laquo"</span><span>)</span>
     <span>(</span><span>#</span><span>&#172;</span> <span>.</span> <span>"not"</span><span>)</span>
     <span>(</span><span>#</span><span>&#174;</span> <span>.</span> <span>"reg"</span><span>)</span>
     <span>(</span><span>#</span><span>&#175;</span> <span>.</span> <span>"macr"</span><span>)</span>
     <span>(</span><span>#</span><span>&#176;</span> <span>.</span> <span>"deg"</span><span>)</span>
     <span>(</span><span>#</span><span>&#177;</span> <span>.</span> <span>"plusmn"</span><span>)</span>
     <span>(</span><span>#</span><span>&#178;</span> <span>.</span> <span>"sup2"</span><span>)</span>
     <span>(</span><span>#</span><span>&#179;</span> <span>.</span> <span>"sup3"</span><span>)</span>
     <span>(</span><span>#</span><span>&#180;</span> <span>.</span> <span>"acute"</span><span>)</span>
     <span>(</span><span>#</span><span>&#181;</span> <span>.</span> <span>"micro"</span><span>)</span>
     <span>(</span><span>#</span><span>&#182;</span> <span>.</span> <span>"para"</span><span>)</span>
     <span>(</span><span>#</span><span>&#183;</span> <span>.</span> <span>"middot"</span><span>)</span>
     <span>(</span><span>#</span><span>&#184;</span> <span>.</span> <span>"cedil"</span><span>)</span>
     <span>(</span><span>#</span><span>&#185;</span> <span>.</span> <span>"sup1"</span><span>)</span>
     <span>(</span><span>#</span><span>&#186;</span> <span>.</span> <span>"ordm"</span><span>)</span>
     <span>(</span><span>#</span><span>&#187;</span> <span>.</span> <span>"raquo"</span><span>)</span>
     <span>(</span><span>#</span><span>&#188;</span> <span>.</span> <span>"frac14"</span><span>)</span>
     <span>(</span><span>#</span><span>&#189;</span> <span>.</span> <span>"frac12"</span><span>)</span>
     <span>(</span><span>#</span><span>&#190;</span> <span>.</span> <span>"frac34"</span><span>)</span>
     <span>(</span><span>#</span><span>&#191;</span> <span>.</span> <span>"iquest"</span><span>)</span>
     <span>(</span><span>#</span><span>&#192;</span> <span>.</span> <span>"Agrave"</span><span>)</span>
     <span>(</span><span>#</span><span>&#193;</span> <span>.</span> <span>"Aacute"</span><span>)</span>
     <span>(</span><span>#&#194;</span> <span>.</span> <span>"Acirc"</span><span>)</span>
     <span>(</span><span>#</span><span>&#195;</span> <span>.</span> <span>"Atilde"</span><span>)</span>
     <span>(</span><span>#</span><span>&#196;</span> <span>.</span> <span>"Auml"</span><span>)</span>
     <span>(</span><span>#</span><span>&#197;</span> <span>.</span> <span>"Aring"</span><span>)</span>
     <span>(</span><span>#</span><span>&#198;</span> <span>.</span> <span>"AElig"</span><span>)</span>
     <span>(</span><span>#</span><span>&#199;</span> <span>.</span> <span>"Ccedil"</span><span>)</span>
     <span>(</span><span>#</span><span>&#200;</span> <span>.</span> <span>"Egrave"</span><span>)</span>
     <span>(</span><span>#</span><span>&#201;</span> <span>.</span> <span>"Eacute"</span><span>)</span>
     <span>(</span><span>#</span><span>&#202;</span> <span>.</span> <span>"Ecirc"</span><span>)</span>
     <span>(</span><span>#</span><span>&#203;</span> <span>.</span> <span>"Euml"</span><span>)</span>
     <span>(</span><span>#</span><span>&#204;</span> <span>.</span> <span>"Igrave"</span><span>)</span>
     <span>(</span><span>#</span><span>&#205;</span> <span>.</span> <span>"Iacute"</span><span>)</span>
     <span>(</span><span>#</span><span>&#206;</span> <span>.</span> <span>"Icirc"</span><span>)</span>
     <span>(</span><span>#</span><span>&#207;</span> <span>.</span> <span>"Iuml"</span><span>)</span>
     <span>(</span><span>#</span><span>&#208;</span> <span>.</span> <span>"ETH"</span><span>)</span>
     <span>(</span><span>#</span><span>&#209;</span> <span>.</span> <span>"Ntilde"</span><span>)</span>
     <span>(</span><span>#</span><span>&#210;</span> <span>.</span> <span>"Ograve"</span><span>)</span>
     <span>(</span><span>#</span><span>&#211;</span> <span>.</span> <span>"Oacute"</span><span>)</span>
     <span>(</span><span>#</span><span>&#212;</span> <span>.</span> <span>"Ocirc"</span><span>)</span>
     <span>(</span><span>#</span><span>&#213;</span> <span>.</span> <span>"Otilde"</span><span>)</span>
     <span>(</span><span>#</span><span>&#214;</span> <span>.</span> <span>"Ouml"</span><span>)</span>
     <span>(</span><span>#</span><span>&#215;</span> <span>.</span> <span>"times"</span><span>)</span>
     <span>(</span><span>#</span><span>&#216;</span> <span>.</span> <span>"Oslash"</span><span>)</span>
     <span>(</span><span>#</span><span>&#217;</span> <span>.</span> <span>"Ugrave"</span><span>)</span>
     <span>(</span><span>#</span><span>&#218;</span> <span>.</span> <span>"Uacute"</span><span>)</span>
     <span>(</span><span>#</span><span>&#219;</span> <span>.</span> <span>"Ucirc"</span><span>)</span>
     <span>(</span><span>#</span><span>&#220;</span> <span>.</span> <span>"Uuml"</span><span>)</span>
     <span>(</span><span>#</span><span>&#221;</span> <span>.</span> <span>"Yacute"</span><span>)</span>
     <span>(</span><span>#</span><span>&#222;</span> <span>.</span> <span>"THORN"</span><span>)</span>
     <span>(</span><span>#</span><span>&#223;</span> <span>.</span> <span>"szlig"</span><span>)</span>
     <span>(</span><span>#</span><span>&#224;</span> <span>.</span> <span>"agrave"</span><span>)</span>
     <span>(</span><span>#</span><span>&#225;</span> <span>.</span> <span>"aacute"</span><span>)</span>
     <span>(</span><span>#</span><span>&#226;</span> <span>.</span> <span>"acirc"</span><span>)</span>
     <span>(</span><span>#</span><span>&#227;</span> <span>.</span> <span>"atilde"</span><span>)</span>
     <span>(</span><span>#</span><span>&#228;</span> <span>.</span> <span>"auml"</span><span>)</span>
     <span>(</span><span>#</span><span>&#229;</span> <span>.</span> <span>"aring"</span><span>)</span>
     <span>(</span><span>#</span><span>&#230;</span> <span>.</span> <span>"aelig"</span><span>)</span>
     <span>(</span><span>#</span><span>&#231;</span> <span>.</span> <span>"ccedil"</span><span>)</span>
     <span>(</span><span>#</span><span>&#232;</span> <span>.</span> <span>"egrave"</span><span>)</span>
     <span>(</span><span>#</span><span>&#233;</span> <span>.</span> <span>"eacute"</span><span>)</span>
     <span>(</span><span>#</span><span>&#234;</span> <span>.</span> <span>"ecirc"</span><span>)</span>
     <span>(</span><span>#</span><span>&#235;</span> <span>.</span> <span>"euml"</span><span>)</span>
     <span>(</span><span>#</span><span>&#236;</span> <span>.</span> <span>"igrave"</span><span>)</span>
     <span>(</span><span>#</span><span>&#237;</span> <span>.</span> <span>"iacute"</span><span>)</span>
     <span>(</span><span>#</span><span>&#238;</span> <span>.</span> <span>"icirc"</span><span>)</span>
     <span>(</span><span>#</span><span>&#239;</span> <span>.</span> <span>"iuml"</span><span>)</span>
     <span>(</span><span>#</span><span>&#240;</span> <span>.</span> <span>"eth"</span><span>)</span>
     <span>(</span><span>#</span><span>&#241;</span> <span>.</span> <span>"ntilde"</span><span>)</span>
     <span>(</span><span>#</span><span>&#242;</span> <span>.</span> <span>"ograve"</span><span>)</span>
     <span>(</span><span>#</span><span>&#243;</span> <span>.</span> <span>"oacute"</span><span>)</span>
     <span>(</span><span>#</span><span>&#244;</span> <span>.</span> <span>"ocirc"</span><span>)</span>
     <span>(</span><span>#</span><span>&#245;</span> <span>.</span> <span>"otilde"</span><span>)</span>
     <span>(</span><span>#</span><span>&#246;</span> <span>.</span> <span>"ouml"</span><span>)</span>
     <span>(</span><span>#</span><span>&#247;</span> <span>.</span> <span>"divide"</span><span>)</span>
     <span>(</span><span>#</span><span>&#248;</span> <span>.</span> <span>"oslash"</span><span>)</span>
     <span>(</span><span>#</span><span>&#249;</span> <span>.</span> <span>"ugrave"</span><span>)</span>
     <span>(</span><span>#</span><span>&#250;</span> <span>.</span> <span>"uacute"</span><span>)</span>
     <span>(</span><span>#</span><span>&#251;</span> <span>.</span> <span>"ucirc"</span><span>)</span>
     <span>(</span><span>#</span><span>&#252;</span> <span>.</span> <span>"uuml"</span><span>)</span>
     <span>(</span><span>#</span><span>&#253;</span> <span>.</span> <span>"yacute"</span><span>)</span>
     <span>(</span><span>#</span><span>&#254;</span> <span>.</span> <span>"thorn"</span><span>)</span>
     <span>(</span><span>#</span><span>&#255;</span> <span>.</span> <span>"yuml"</span><span>)</span>
     <span>(</span><span>#</span><span>&#338;</span> <span>.</span> <span>"OElig"</span><span>)</span>
     <span>(</span><span>#</span><span>&#339;</span> <span>.</span> <span>"oelig"</span><span>)</span>
     <span>(</span><span>#</span><span>&#352;</span> <span>.</span> <span>"Scaron"</span><span>)</span>
     <span>(</span><span>#</span><span>&#353;</span> <span>.</span> <span>"scaron"</span><span>)</span>
     <span>(</span><span>#</span><span>&#376;</span> <span>.</span> <span>"Yuml"</span><span>)</span>
     <span>(</span><span>#</span><span>&#402;</span> <span>.</span> <span>"fnof"</span><span>)</span>
     <span>(</span><span>#</span><span>&#710;</span> <span>.</span> <span>"circ"</span><span>)</span>
     <span>(</span><span>#</span><span>&#732;</span> <span>.</span> <span>"tilde"</span><span>)</span>
     <span>(</span><span>#</span><span>&#913;</span> <span>.</span> <span>"Alpha"</span><span>)</span>
     <span>(</span><span>#</span><span>&#914;</span> <span>.</span> <span>"Beta"</span><span>)</span>
     <span>(</span><span>#</span><span>&#915;</span> <span>.</span> <span>"Gamma"</span><span>)</span>
     <span>(</span><span>#</span><span>&#916;</span> <span>.</span> <span>"Delta"</span><span>)</span>
     <span>(</span><span>#</span><span>&#917;</span> <span>.</span> <span>"Epsilon"</span><span>)</span>
     <span>(</span><span>#</span><span>&#918;</span> <span>.</span> <span>"Zeta"</span><span>)</span>
     <span>(</span><span>#</span><span>&#919;</span> <span>.</span> <span>"Eta"</span><span>)</span>
     <span>(</span><span>#</span><span>&#920;</span> <span>.</span> <span>"Theta"</span><span>)</span>
     <span>(</span><span>#</span><span>&#921;</span> <span>.</span> <span>"Iota"</span><span>)</span>
     <span>(</span><span>#</span><span>&#922;</span> <span>.</span> <span>"Kappa"</span><span>)</span>
     <span>(</span><span>#</span><span>&#923;</span> <span>.</span> <span>"Lambda"</span><span>)</span>
     <span>(</span><span>#</span><span>&#924;</span> <span>.</span> <span>"Mu"</span><span>)</span>
     <span>(</span><span>#</span><span>&#925;</span> <span>.</span> <span>"Nu"</span><span>)</span>
     <span>(</span><span>#</span><span>&#926;</span> <span>.</span> <span>"Xi"</span><span>)</span>
     <span>(</span><span>#</span><span>&#927;</span> <span>.</span> <span>"Omicron"</span><span>)</span>
     <span>(</span><span>#</span><span>&#928;</span> <span>.</span> <span>"Pi"</span><span>)</span>
     <span>(</span><span>#</span><span>&#929;</span> <span>.</span> <span>"Rho"</span><span>)</span>
     <span>(</span><span>#</span><span>&#931;</span> <span>.</span> <span>"Sigma"</span><span>)</span>
     <span>(</span><span>#</span><span>&#932;</span> <span>.</span> <span>"Tau"</span><span>)</span>
     <span>(</span><span>#</span><span>&#933;</span> <span>.</span> <span>"Upsilon"</span><span>)</span>
     <span>(</span><span>#</span><span>&#934;</span> <span>.</span> <span>"Phi"</span><span>)</span>
     <span>(</span><span>#</span><span>&#935;</span> <span>.</span> <span>"Chi"</span><span>)</span>
     <span>(</span><span>#</span><span>&#936;</span> <span>.</span> <span>"Psi"</span><span>)</span>
     <span>(</span><span>#</span><span>&#937;</span> <span>.</span> <span>"Omega"</span><span>)</span>
     <span>(</span><span>#</span><span>&#945;</span> <span>.</span> <span>"alpha"</span><span>)</span>
     <span>(</span><span>#</span><span>&#946;</span> <span>.</span> <span>"beta"</span><span>)</span>
     <span>(</span><span>#</span><span>&#947;</span> <span>.</span> <span>"gamma"</span><span>)</span>
     <span>(</span><span>#</span><span>&#948;</span> <span>.</span> <span>"delta"</span><span>)</span>
     <span>(</span><span>#</span><span>&#949;</span> <span>.</span> <span>"epsilon"</span><span>)</span>
     <span>(</span><span>#</span><span>&#950;</span> <span>.</span> <span>"zeta"</span><span>)</span>
     <span>(</span><span>#</span><span>&#951;</span> <span>.</span> <span>"eta"</span><span>)</span>
     <span>(</span><span>#</span><span>&#952;</span> <span>.</span> <span>"theta"</span><span>)</span>
     <span>(</span><span>#</span><span>&#953;</span> <span>.</span> <span>"iota"</span><span>)</span>
     <span>(</span><span>#</span><span>&#954;</span> <span>.</span> <span>"kappa"</span><span>)</span>
     <span>(</span><span>#</span><span>&#955;</span> <span>.</span> <span>"lambda"</span><span>)</span>
     <span>(</span><span>#</span><span>&#956;</span> <span>.</span> <span>"mu"</span><span>)</span>
     <span>(</span><span>#</span><span>&#957;</span> <span>.</span> <span>"nu"</span><span>)</span>
     <span>(</span><span>#</span><span>&#958;</span> <span>.</span> <span>"xi"</span><span>)</span>
     <span>(</span><span>#</span><span>&#959;</span> <span>.</span> <span>"omicron"</span><span>)</span>
     <span>(</span><span>#</span><span>&#960;</span> <span>.</span> <span>"pi"</span><span>)</span>
     <span>(</span><span>#</span><span>&#961;</span> <span>.</span> <span>"rho"</span><span>)</span>
     <span>(</span><span>#</span><span>&#962;</span> <span>.</span> <span>"sigmaf"</span><span>)</span>
     <span>(</span><span>#</span><span>&#963;</span> <span>.</span> <span>"sigma"</span><span>)</span>
     <span>(</span><span>#</span><span>&#964;</span> <span>.</span> <span>"tau"</span><span>)</span>
     <span>(</span><span>#</span><span>&#965;</span> <span>.</span> <span>"upsilon"</span><span>)</span>
     <span>(</span><span>#</span><span>&#966;</span> <span>.</span> <span>"phi"</span><span>)</span>
     <span>(</span><span>#</span><span>&#967;</span> <span>.</span> <span>"chi"</span><span>)</span>
     <span>(</span><span>#</span><span>&#968;</span> <span>.</span> <span>"psi"</span><span>)</span>
     <span>(</span><span>#</span><span>&#969;</span> <span>.</span> <span>"omega"</span><span>)</span>
     <span>(</span><span>#</span><span>&#977;</span> <span>.</span> <span>"thetasym"</span><span>)</span>
     <span>(</span><span>#</span><span>&#978;</span> <span>.</span> <span>"upsih"</span><span>)</span>
     <span>(</span><span>#</span><span>&#982;</span> <span>.</span> <span>"piv"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8194;</span> <span>.</span> <span>"ensp"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8195;</span> <span>.</span> <span>"emsp"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8201;</span> <span>.</span> <span>"thinsp"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8211;</span> <span>.</span> <span>"ndash"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8212;</span> <span>.</span> <span>"mdash"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8216;</span> <span>.</span> <span>"lsquo"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8217;</span> <span>.</span> <span>"rsquo"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8218;</span> <span>.</span> <span>"sbquo"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8220;</span> <span>.</span> <span>"ldquo"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8221;</span> <span>.</span> <span>"rdquo"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8222;</span> <span>.</span> <span>"bdquo"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8224;</span> <span>.</span> <span>"dagger"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8225;</span> <span>.</span> <span>"Dagger"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8226;</span> <span>.</span> <span>"bull"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8230;</span> <span>.</span> <span>"hellip"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8240;</span> <span>.</span> <span>"permil"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8242;</span> <span>.</span> <span>"prime"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8243;</span> <span>.</span> <span>"Prime"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8249;</span> <span>.</span> <span>"lsaquo"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8250;</span> <span>.</span> <span>"rsaquo"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8254;</span> <span>.</span> <span>"oline"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8260;</span> <span>.</span> <span>"frasl"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8364;</span> <span>.</span> <span>"euro"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8465;</span> <span>.</span> <span>"image"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8472;</span> <span>.</span> <span>"weierp"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8476;</span> <span>.</span> <span>"real"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8482;</span> <span>.</span> <span>"trade"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8501;</span> <span>.</span> <span>"alefsym"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8592;</span> <span>.</span> <span>"larr"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8593;</span> <span>.</span> <span>"uarr"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8594;</span> <span>.</span> <span>"rarr"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8595;</span> <span>.</span> <span>"darr"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8596;</span> <span>.</span> <span>"harr"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8629;</span> <span>.</span> <span>"crarr"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8656;</span> <span>.</span> <span>"lArr"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8657;</span> <span>.</span> <span>"uArr"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8658;</span> <span>.</span> <span>"rArr"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8659;</span> <span>.</span> <span>"dArr"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8660;</span> <span>.</span> <span>"hArr"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8704;</span> <span>.</span> <span>"forall"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8706;</span> <span>.</span> <span>"part"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8707;</span> <span>.</span> <span>"exist"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8709;</span> <span>.</span> <span>"empty"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8711;</span> <span>.</span> <span>"nabla"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8712;</span> <span>.</span> <span>"isin"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8713;</span> <span>.</span> <span>"notin"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8715;</span> <span>.</span> <span>"ni"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8719;</span> <span>.</span> <span>"prod"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8721;</span> <span>.</span> <span>"sum"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8722;</span> <span>.</span> <span>"minus"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8727;</span> <span>.</span> <span>"lowast"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8730;</span> <span>.</span> <span>"radic"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8733;</span> <span>.</span> <span>"prop"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8734;</span> <span>.</span> <span>"infin"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8736;</span> <span>.</span> <span>"ang"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8743;</span> <span>.</span> <span>"and"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8744;</span> <span>.</span> <span>"or"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8745;</span> <span>.</span> <span>"cap"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8746;</span> <span>.</span> <span>"cup"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8747;</span> <span>.</span> <span>"int"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8756;</span> <span>.</span> <span>"there4"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8764;</span> <span>.</span> <span>"sim"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8773;</span> <span>.</span> <span>"cong"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8776;</span> <span>.</span> <span>"asymp"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8800;</span> <span>.</span> <span>"ne"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8801;</span> <span>.</span> <span>"equiv"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8804;</span> <span>.</span> <span>"le"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8805;</span> <span>.</span> <span>"ge"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8834;</span> <span>.</span> <span>"sub"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8835;</span> <span>.</span> <span>"sup"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8836;</span> <span>.</span> <span>"nsub"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8838;</span> <span>.</span> <span>"sube"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8839;</span> <span>.</span> <span>"supe"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8853;</span> <span>.</span> <span>"oplus"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8855;</span> <span>.</span> <span>"otimes"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8869;</span> <span>.</span> <span>"perp"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8901;</span> <span>.</span> <span>"sdot"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8942;</span> <span>.</span> <span>"vellip"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8968;</span> <span>.</span> <span>"lceil"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8969;</span> <span>.</span> <span>"rceil"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8970;</span> <span>.</span> <span>"lfloor"</span><span>)</span>
     <span>(</span><span>#</span><span>&#8971;</span> <span>.</span> <span>"rfloor"</span><span>)</span>
     <span>(</span><span>#</span><span>&#9001;</span> <span>.</span> <span>"lang"</span><span>)</span>
     <span>(</span><span>#</span><span>&#9002;</span> <span>.</span> <span>"rang"</span><span>)</span>
     <span>(</span><span>#</span><span>&#9674;</span> <span>.</span> <span>"loz"</span><span>)</span>
     <span>(</span><span>#</span><span>&#9824;</span> <span>.</span> <span>"spades"</span><span>)</span>
     <span>(</span><span>#</span><span>&#9827;</span> <span>.</span> <span>"clubs"</span><span>)</span>
     <span>(</span><span>#</span><span>&#9829;</span> <span>.</span> <span>"hearts"</span><span>)</span>
     <span>(</span><span>#</span><span>&#9830;</span> <span>.</span> <span>"diams"</span><span>))))</span>

<span>(</span><span>define </span><span>(</span><span>string-&#62;escaped-html</span> <span>s</span> <span>port</span><span>)</span>
  <span>"Write the HTML escaped form of S to PORT."</span>
  <span>(</span><span>define </span><span>(</span><span>escape</span> <span>c</span><span>)</span>
    <span>(</span><span>let </span><span>((</span><span>escaped</span> <span>(</span><span>hash-ref</span> <span>%escape-chars</span> <span>c</span><span>)))</span>
      <span>(</span><span>if </span><span>escaped</span>
          <span>(</span><span>format</span> <span>port</span> <span>"&#38;~a;"</span> <span>escaped</span><span>)</span>
          <span>(</span><span>display </span><span>c</span> <span>port</span><span>))))</span>
  <span>(</span><span>string-for-each</span> <span>escape</span> <span>s</span><span>))</span>

<span>(</span><span>define </span><span>(</span><span>object-&#62;escaped-html</span> <span>obj</span> <span>port</span><span>)</span>
  <span>"Write the HTML escaped form of OBJ to PORT."</span>
  <span>(</span><span>string-&#62;escaped-html</span>
   <span>(</span><span>call-with-output-string</span> <span>(</span><span>cut</span> <span>display</span> <span>obj</span> <span>&#60;&#62;</span><span>))</span>
   <span>port</span><span>))</span>

<span>(</span><span>define </span><span>(</span><span>attribute-value-&#62;html</span> <span>value</span> <span>port</span><span>)</span>
  <span>"Write the HTML escaped form of VALUE to PORT."</span>
  <span>(</span><span>if </span><span>(</span><span>string? </span><span>value</span><span>)</span>
      <span>(</span><span>string-&#62;escaped-html</span> <span>value</span> <span>port</span><span>)</span>
      <span>(</span><span>object-&#62;escaped-html</span> <span>value</span> <span>port</span><span>)))</span>

<span>(</span><span>define </span><span>(</span><span>attribute-&#62;html</span> <span>attr</span> <span>value</span> <span>port</span><span>)</span>
  <span>"Write ATTR and VALUE to PORT."</span>
  <span>(</span><span>format</span> <span>port</span> <span>"~a=""</span> <span>attr</span><span>)</span>
  <span>(</span><span>attribute-value-&#62;html</span> <span>value</span> <span>port</span><span>)</span>
  <span>(</span><span>display </span><span>#"</span> <span>port</span><span>))</span>

<span>(</span><span>define </span><span>(</span><span>element-&#62;html</span> <span>tag</span> <span>attrs</span> <span>body</span> <span>port</span><span>)</span>
  <span>"Write the HTML TAG to PORT, where TAG has the attributes in the</span>
<span>list ATTRS and the child nodes in BODY."</span>
  <span>(</span><span>format</span> <span>port</span> <span>"&#60;~a"</span> <span>tag</span><span>)</span>
  <span>(</span><span>for-each </span><span>(</span><span>match-lambda</span>
             <span>((</span><span>attr</span> <span>value</span><span>)</span>
              <span>(</span><span>display </span><span>#space</span> <span>port</span><span>)</span>
              <span>(</span><span>attribute-&#62;html</span> <span>attr</span> <span>value</span> <span>port</span><span>)))</span>
            <span>attrs</span><span>)</span>
  <span>(</span><span>if </span><span>(</span><span>and </span><span>(</span><span>null? </span><span>body</span><span>)</span> <span>(</span><span>void-element?</span> <span>tag</span><span>))</span>
      <span>(</span><span>display </span><span>" /&#62;"</span> <span>port</span><span>)</span>
      <span>(</span><span>begin</span>
        <span>(</span><span>display </span><span>#</span><span></span><span>&#62;</span> <span>port</span><span>)</span>
        <span>(</span><span>for-each </span><span>(</span><span>cut</span> <span>sxml-&#62;html</span> <span>&#60;&#62;</span> <span>port</span><span>)</span> <span>body</span><span>)</span>
        <span>(</span><span>format</span> <span>port</span> <span>"&#60;/~a&#62;"</span> <span>tag</span><span>))))</span>

<span>(</span><span>define </span><span>(</span><span>doctype-&#62;html</span> <span>doctype</span> <span>port</span><span>)</span>
  <span>(</span><span>format</span> <span>port</span> <span>"&#60;!DOCTYPE ~a&#62;"</span> <span>doctype</span><span>))</span>

<span>(</span><span>define*</span> <span>(</span><span>sxml-&#62;html</span> <span>tree</span> <span>#</span><span>:optional</span> <span>(</span><span>port</span> <span>(</span><span>current-output-port</span><span>)))</span>
  <span>"Write the serialized HTML form of TREE to PORT."</span>
  <span>(</span><span>match</span> <span>tree</span>
    <span>(()</span> <span>*unspecified*</span><span>)</span>
    <span>((</span><span>'doctype</span> <span>type</span><span>)</span>
     <span>(</span><span>doctype-&#62;html</span> <span>type</span> <span>port</span><span>))</span>
    <span>;; Unescaped, raw HTML output</span>
    <span>((</span><span>'raw</span> <span>html</span><span>)</span>
     <span>(</span><span>display </span><span>html</span> <span>port</span><span>))</span>
    <span>(((</span><span>?</span> <span>symbol?</span> <span>tag</span><span>)</span> <span>(</span><span>'@</span> <span>attrs</span> <span>...</span><span>)</span> <span>body</span> <span>...</span><span>)</span>
     <span>(</span><span>element-&#62;html</span> <span>tag</span> <span>attrs</span> <span>body</span> <span>port</span><span>))</span>
    <span>(((</span><span>?</span> <span>symbol?</span> <span>tag</span><span>)</span> <span>body</span> <span>...</span><span>)</span>
     <span>(</span><span>element-&#62;html</span> <span>tag</span> <span>'</span><span>()</span> <span>body</span> <span>port</span><span>))</span>
    <span>((</span><span>nodes</span> <span>...</span><span>)</span>
     <span>(</span><span>for-each </span><span>(</span><span>cut</span> <span>sxml-&#62;html</span> <span>&#60;&#62;</span> <span>port</span><span>)</span> <span>nodes</span><span>))</span>
    <span>((</span><span>?</span> <span>string?</span> <span>text</span><span>)</span>
     <span>(</span><span>string-&#62;escaped-html</span> <span>text</span> <span>port</span><span>))</span>
    <span>;; Render arbitrary Scheme objects, too.</span>
    <span>(</span><span>obj</span> <span>(</span><span>object-&#62;escaped-html</span> <span>obj</span> <span>port</span><span>))))</span>
</pre></div>]]></description>
										<content:encoded><![CDATA[<p>GNU Guile provides modules for working with XML documents called SXML.<br />
SXML provides an elegant way of writing XML documents as s-expressions<br />
that can be easily manipulated in Scheme.  Here&#8217;s an example:</p>
<div class="highlight">
<pre><span class="p">(</span><span class="nf">sxml-&gt;xml</span> <span class="o">&#39;</span><span class="p">(</span><span class="nv">foo</span> <span class="p">(</span><span class="nf">bar</span> <span class="p">(</span><span class="nf">@</span> <span class="p">(</span><span class="nf">attr</span> <span class="s">&quot;something&quot;</span><span class="p">)))))</span>
</pre>
</div>
<div class="highlight">
<pre><span class="nt">&lt;foo&gt;&lt;bar</span> <span class="na">attr=</span><span class="s">&quot;something&quot;</span> <span class="nt">/&gt;&lt;/foo&gt;</span>
</pre>
</div>
<p>I don&#8217;t know about you, but I work with HTML documents much more often<br />
than XML.  Since HTML is very similar to XML, we should be able to<br />
represent it with SXML, too!</p>
<div class="highlight">
<pre><span class="p">(</span><span class="nf">sxml-&gt;xml</span> <span class="o">&#39;</span><span class="p">(</span><span class="nv">html</span>
             <span class="p">(</span><span class="nf">head</span>
              <span class="p">(</span><span class="nf">title</span> <span class="s">&quot;Hello, world!&quot;</span><span class="p">)</span>
              <span class="p">(</span><span class="nf">script</span> <span class="p">(</span><span class="nf">@</span> <span class="p">(</span><span class="nf">src</span> <span class="s">&quot;foo.js&quot;</span><span class="p">))))</span>
             <span class="p">(</span><span class="nf">body</span>
              <span class="p">(</span><span class="nf">h1</span> <span class="s">&quot;Hello!&quot;</span><span class="p">))))</span>
</pre>
</div>
<div class="highlight">
<pre><span class="nt">&lt;html&gt;</span>
  <span class="nt">&lt;head&gt;</span>
    <span class="nt">&lt;title&gt;</span>Hello, world!<span class="nt">&lt;/title&gt;</span>
    <span class="nt">&lt;script </span><span class="na">src=</span><span class="s">&quot;foo.js&quot;</span> <span class="nt">/&gt;</span><span class="err"> &lt;!-- what? --&gt;</span>
  <span class="nt">&lt;/head&gt;</span>
  <span class="nt">&lt;body&gt;</span>
    <span class="nt">&lt;h1&gt;</span>Hello!<span class="nt">&lt;/h1&gt;</span>
  <span class="nt">&lt;/body&gt;</span>
<span class="nt">&lt;/html&gt;</span>
</pre>
</div>
<p>That <tt class="docutils literal">&lt;script&gt;</tt> tag doesn&#8217;t look right!  Script tags don&#8217;t close<br />
themselves like that.  Well, we could hack around it:</p>
<div class="highlight">
<pre><span class="p">(</span><span class="nf">sxml-&gt;xml</span> <span class="o">&#39;</span><span class="p">(</span><span class="nv">html</span>
             <span class="p">(</span><span class="nf">head</span>
              <span class="p">(</span><span class="nf">title</span> <span class="s">&quot;Hello, world!&quot;</span><span class="p">)</span>
              <span class="p">(</span><span class="nf">script</span> <span class="p">(</span><span class="nf">@</span> <span class="p">(</span><span class="nf">src</span> <span class="s">&quot;foo.js&quot;</span><span class="p">))</span> <span class="s">&quot;&quot;</span><span class="p">))</span>
             <span class="p">(</span><span class="nf">body</span>
              <span class="p">(</span><span class="nf">h1</span> <span class="s">&quot;Hello!&quot;</span><span class="p">))))</span>
</pre>
</div>
<div class="highlight">
<pre><span class="nt">&lt;html&gt;</span>
  <span class="nt">&lt;head&gt;</span>
    <span class="nt">&lt;title&gt;</span>Hello, world!<span class="nt">&lt;/title&gt;</span>
    <span class="nt">&lt;script </span><span class="na">src=</span><span class="s">&quot;foo.js&quot;</span><span class="nt">&gt;&lt;/script&gt;</span>
  <span class="nt">&lt;/head&gt;</span>
  <span class="nt">&lt;body&gt;</span>
    <span class="nt">&lt;h1&gt;</span>Hello!<span class="nt">&lt;/h1&gt;</span>
  <span class="nt">&lt;/body&gt;</span>
<span class="nt">&lt;/html&gt;</span>
</pre>
</div>
<p>Note the use of the empty string in <tt class="docutils literal">(script (&#64; (src <span class="pre">&quot;foo.js&quot;))</span><br />
&quot;&quot;)</tt>.  The output looks correct now, great!  But what about the other<br />
void elements?  We&#8217;ll have to remember to use the empty string hack<br />
each time we use one.  That doesn&#8217;t sound very elegant.</p>
<p>Furthermore, text isn&#8217;t even escaped properly!</p>
<div class="highlight">
<pre><span class="p">(</span><span class="nf">sxml-&gt;xml</span> <span class="s">&quot;Copyright © 2015  David Thompson &lt;davet@gnu.org&gt;&quot;</span><span class="p">)</span>
</pre>
</div>
<div class="highlight">
<pre>Copyright © 2015  David Thompson <span class="ni">&amp;lt;</span>davet@gnu.org<span class="ni">&amp;gt;</span>
</pre>
</div>
<p>The <tt class="docutils literal">&lt;</tt> and <tt class="docutils literal">&gt;</tt> braces were escaped, but <tt class="docutils literal">©</tt> should&#8217;ve been<br />
rendered as <tt class="docutils literal">&amp;copy;</tt>.  Why does this fail, too?  Is there a bug in<br />
SXML?</p>
<p>There&#8217;s no bug.  The improper rendering happens because HTML, while<br />
similar to XML, has a bunch of different syntax rules.  Instead of<br />
using <tt class="docutils literal"><span class="pre">sxml-&gt;xml</span></tt>, a new procedure that is tailored to the HTML<br />
syntax is needed.  Introducing <tt class="docutils literal"><span class="pre">sxml-&gt;html</span></tt>:</p>
<div class="highlight">
<pre><span class="p">(</span><span class="nf">define*</span> <span class="p">(</span><span class="nf">sxml-&gt;html</span> <span class="nv">tree</span> <span class="o">#</span><span class="nv">:optional</span> <span class="p">(</span><span class="nf">port</span> <span class="p">(</span><span class="nf">current-output-port</span><span class="p">)))</span>
  <span class="s">&quot;Write the serialized HTML form of TREE to PORT.&quot;</span>
  <span class="p">(</span><span class="nf">match</span> <span class="nv">tree</span>
    <span class="p">(()</span> <span class="nv">*unspecified*</span><span class="p">)</span>
    <span class="p">((</span><span class="ss">&#39;doctype</span> <span class="nv">type</span><span class="p">)</span>
     <span class="p">(</span><span class="nf">doctype-&gt;html</span> <span class="nv">type</span> <span class="nv">port</span><span class="p">))</span>
    <span class="c1">;; Unescaped, raw HTML output</span>
    <span class="p">((</span><span class="ss">&#39;raw</span> <span class="nv">html</span><span class="p">)</span>
     <span class="p">(</span><span class="nb">display </span><span class="nv">html</span> <span class="nv">port</span><span class="p">))</span>
    <span class="p">(((</span><span class="nf">?</span> <span class="nv">symbol?</span> <span class="nv">tag</span><span class="p">)</span> <span class="p">(</span><span class="ss">&#39;@</span> <span class="nv">attrs</span> <span class="o">...</span><span class="p">)</span> <span class="nv">body</span> <span class="o">...</span><span class="p">)</span>
     <span class="p">(</span><span class="nf">element-&gt;html</span> <span class="nv">tag</span> <span class="nv">attrs</span> <span class="nv">body</span> <span class="nv">port</span><span class="p">))</span>
    <span class="p">(((</span><span class="nf">?</span> <span class="nv">symbol?</span> <span class="nv">tag</span><span class="p">)</span> <span class="nv">body</span> <span class="o">...</span><span class="p">)</span>
     <span class="p">(</span><span class="nf">element-&gt;html</span> <span class="nv">tag</span> <span class="o">&#39;</span><span class="p">()</span> <span class="nv">body</span> <span class="nv">port</span><span class="p">))</span>
    <span class="p">((</span><span class="nf">nodes</span> <span class="o">...</span><span class="p">)</span>
     <span class="p">(</span><span class="nb">for-each </span><span class="p">(</span><span class="nf">cut</span> <span class="nv">sxml-&gt;html</span> <span class="nv">&lt;&gt;</span> <span class="nv">port</span><span class="p">)</span> <span class="nv">nodes</span><span class="p">))</span>
    <span class="p">((</span><span class="nf">?</span> <span class="nv">string?</span> <span class="nv">text</span><span class="p">)</span>
     <span class="p">(</span><span class="nf">string-&gt;escaped-html</span> <span class="nv">text</span> <span class="nv">port</span><span class="p">))</span>
    <span class="c1">;; Render arbitrary Scheme objects, too.</span>
    <span class="p">(</span><span class="nf">obj</span> <span class="p">(</span><span class="nf">object-&gt;escaped-html</span> <span class="nv">obj</span> <span class="nv">port</span><span class="p">))))</span>
</pre>
</div>
<p>In addition to being aware of void elements and escape characters, it<br />
can also render <tt class="docutils literal">'(doctype &quot;html&quot;)</tt> as <tt class="docutils literal">&lt;!DOCTYPE html&gt;</tt>, or<br />
render an unescaped HTML string using <tt class="docutils literal">'(raw &quot;frog &amp;amp; toad&quot;)</tt>.</p>
<p>Here&#8217;s the full version of my <tt class="docutils literal">(sxml html)</tt> module.  It&#8217;s quite<br />
brief, if you don&#8217;t count the ~250 lines of escape codes!  This code<br />
requires Guile 2.0.11 or greater.</p>
<p>Happy hacking!</p>
<div class="highlight">
<pre><span class="p">(</span><span class="nf">define-module</span> <span class="p">(</span><span class="nf">sxml</span> <span class="nv">html</span><span class="p">)</span>
  <span class="o">#</span><span class="nv">:use-module</span> <span class="p">(</span><span class="nf">sxml</span> <span class="nv">simple</span><span class="p">)</span>
  <span class="o">#</span><span class="nv">:use-module</span> <span class="p">(</span><span class="nf">srfi</span> <span class="nv">srfi-26</span><span class="p">)</span>
  <span class="o">#</span><span class="nv">:use-module</span> <span class="p">(</span><span class="nf">ice-9</span> <span class="nv">match</span><span class="p">)</span>
  <span class="o">#</span><span class="nv">:use-module</span> <span class="p">(</span><span class="nf">ice-9</span> <span class="nv">format</span><span class="p">)</span>
  <span class="o">#</span><span class="nv">:use-module</span> <span class="p">(</span><span class="nf">ice-9</span> <span class="nv">hash-table</span><span class="p">)</span>
  <span class="o">#</span><span class="nv">:export</span> <span class="p">(</span><span class="nf">sxml-&gt;html</span><span class="p">))</span>

<span class="p">(</span><span class="k">define </span><span class="nv">%void-elements</span>
  <span class="o">&#39;</span><span class="p">(</span><span class="nv">area</span>
    <span class="nv">base</span>
    <span class="nv">br</span>
    <span class="nv">col</span>
    <span class="nv">command</span>
    <span class="nv">embed</span>
    <span class="nv">hr</span>
    <span class="nv">img</span>
    <span class="nv">input</span>
    <span class="nv">keygen</span>
    <span class="nv">link</span>
    <span class="nv">meta</span>
    <span class="nv">param</span>
    <span class="nv">source</span>
    <span class="nv">track</span>
    <span class="nv">wbr</span><span class="p">))</span>

<span class="p">(</span><span class="k">define </span><span class="p">(</span><span class="nf">void-element?</span> <span class="nv">tag</span><span class="p">)</span>
  <span class="s">&quot;Return #t if TAG is a void element.&quot;</span>
  <span class="p">(</span><span class="nb">pair? </span><span class="p">(</span><span class="nb">memq </span><span class="nv">tag</span> <span class="nv">%void-elements</span><span class="p">)))</span>

<span class="p">(</span><span class="k">define </span><span class="nv">%escape-chars</span>
  <span class="p">(</span><span class="nf">alist-&gt;hash-table</span>
   <span class="o">&#39;</span><span class="p">((</span><span class="sc">#&quot;</span> <span class="o">.</span> <span class="s">&quot;quot&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="sc">#&amp;</span> <span class="o">.</span> <span class="s">&quot;amp&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="sc">#&#39;</span> <span class="o">.</span> <span class="s">&quot;apos&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err"></span><span class="nv">&lt;</span> <span class="o">.</span> <span class="s">&quot;lt&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err"></span><span class="nv">&gt;</span> <span class="o">.</span> <span class="s">&quot;gt&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">¡</span> <span class="o">.</span> <span class="s">&quot;iexcl&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">¢</span> <span class="o">.</span> <span class="s">&quot;cent&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">£</span> <span class="o">.</span> <span class="s">&quot;pound&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">¤</span> <span class="o">.</span> <span class="s">&quot;curren&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">¥</span> <span class="o">.</span> <span class="s">&quot;yen&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">¦</span> <span class="o">.</span> <span class="s">&quot;brvbar&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="sc">#§</span> <span class="o">.</span> <span class="s">&quot;sect&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">¨</span> <span class="o">.</span> <span class="s">&quot;uml&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">©</span> <span class="o">.</span> <span class="s">&quot;copy&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">ª</span> <span class="o">.</span> <span class="s">&quot;ordf&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">«</span> <span class="o">.</span> <span class="s">&quot;laquo&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">¬</span> <span class="o">.</span> <span class="s">&quot;not&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">®</span> <span class="o">.</span> <span class="s">&quot;reg&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">¯</span> <span class="o">.</span> <span class="s">&quot;macr&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">°</span> <span class="o">.</span> <span class="s">&quot;deg&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">±</span> <span class="o">.</span> <span class="s">&quot;plusmn&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">²</span> <span class="o">.</span> <span class="s">&quot;sup2&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">³</span> <span class="o">.</span> <span class="s">&quot;sup3&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">´</span> <span class="o">.</span> <span class="s">&quot;acute&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">µ</span> <span class="o">.</span> <span class="s">&quot;micro&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">¶</span> <span class="o">.</span> <span class="s">&quot;para&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">·</span> <span class="o">.</span> <span class="s">&quot;middot&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">¸</span> <span class="o">.</span> <span class="s">&quot;cedil&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">¹</span> <span class="o">.</span> <span class="s">&quot;sup1&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">º</span> <span class="o">.</span> <span class="s">&quot;ordm&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">»</span> <span class="o">.</span> <span class="s">&quot;raquo&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">¼</span> <span class="o">.</span> <span class="s">&quot;frac14&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">½</span> <span class="o">.</span> <span class="s">&quot;frac12&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">¾</span> <span class="o">.</span> <span class="s">&quot;frac34&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">¿</span> <span class="o">.</span> <span class="s">&quot;iquest&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">À</span> <span class="o">.</span> <span class="s">&quot;Agrave&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Á</span> <span class="o">.</span> <span class="s">&quot;Aacute&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="sc">#Â</span> <span class="o">.</span> <span class="s">&quot;Acirc&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Ã</span> <span class="o">.</span> <span class="s">&quot;Atilde&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Ä</span> <span class="o">.</span> <span class="s">&quot;Auml&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Å</span> <span class="o">.</span> <span class="s">&quot;Aring&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Æ</span> <span class="o">.</span> <span class="s">&quot;AElig&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Ç</span> <span class="o">.</span> <span class="s">&quot;Ccedil&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">È</span> <span class="o">.</span> <span class="s">&quot;Egrave&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">É</span> <span class="o">.</span> <span class="s">&quot;Eacute&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Ê</span> <span class="o">.</span> <span class="s">&quot;Ecirc&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Ë</span> <span class="o">.</span> <span class="s">&quot;Euml&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Ì</span> <span class="o">.</span> <span class="s">&quot;Igrave&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Í</span> <span class="o">.</span> <span class="s">&quot;Iacute&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Î</span> <span class="o">.</span> <span class="s">&quot;Icirc&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Ï</span> <span class="o">.</span> <span class="s">&quot;Iuml&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Ð</span> <span class="o">.</span> <span class="s">&quot;ETH&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Ñ</span> <span class="o">.</span> <span class="s">&quot;Ntilde&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Ò</span> <span class="o">.</span> <span class="s">&quot;Ograve&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Ó</span> <span class="o">.</span> <span class="s">&quot;Oacute&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Ô</span> <span class="o">.</span> <span class="s">&quot;Ocirc&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Õ</span> <span class="o">.</span> <span class="s">&quot;Otilde&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Ö</span> <span class="o">.</span> <span class="s">&quot;Ouml&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">×</span> <span class="o">.</span> <span class="s">&quot;times&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Ø</span> <span class="o">.</span> <span class="s">&quot;Oslash&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Ù</span> <span class="o">.</span> <span class="s">&quot;Ugrave&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Ú</span> <span class="o">.</span> <span class="s">&quot;Uacute&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Û</span> <span class="o">.</span> <span class="s">&quot;Ucirc&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Ü</span> <span class="o">.</span> <span class="s">&quot;Uuml&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Ý</span> <span class="o">.</span> <span class="s">&quot;Yacute&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Þ</span> <span class="o">.</span> <span class="s">&quot;THORN&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">ß</span> <span class="o">.</span> <span class="s">&quot;szlig&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">à</span> <span class="o">.</span> <span class="s">&quot;agrave&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">á</span> <span class="o">.</span> <span class="s">&quot;aacute&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">â</span> <span class="o">.</span> <span class="s">&quot;acirc&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">ã</span> <span class="o">.</span> <span class="s">&quot;atilde&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">ä</span> <span class="o">.</span> <span class="s">&quot;auml&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">å</span> <span class="o">.</span> <span class="s">&quot;aring&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">æ</span> <span class="o">.</span> <span class="s">&quot;aelig&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">ç</span> <span class="o">.</span> <span class="s">&quot;ccedil&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">è</span> <span class="o">.</span> <span class="s">&quot;egrave&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">é</span> <span class="o">.</span> <span class="s">&quot;eacute&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">ê</span> <span class="o">.</span> <span class="s">&quot;ecirc&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">ë</span> <span class="o">.</span> <span class="s">&quot;euml&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">ì</span> <span class="o">.</span> <span class="s">&quot;igrave&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">í</span> <span class="o">.</span> <span class="s">&quot;iacute&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">î</span> <span class="o">.</span> <span class="s">&quot;icirc&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">ï</span> <span class="o">.</span> <span class="s">&quot;iuml&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">ð</span> <span class="o">.</span> <span class="s">&quot;eth&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">ñ</span> <span class="o">.</span> <span class="s">&quot;ntilde&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">ò</span> <span class="o">.</span> <span class="s">&quot;ograve&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">ó</span> <span class="o">.</span> <span class="s">&quot;oacute&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">ô</span> <span class="o">.</span> <span class="s">&quot;ocirc&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">õ</span> <span class="o">.</span> <span class="s">&quot;otilde&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">ö</span> <span class="o">.</span> <span class="s">&quot;ouml&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">÷</span> <span class="o">.</span> <span class="s">&quot;divide&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">ø</span> <span class="o">.</span> <span class="s">&quot;oslash&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">ù</span> <span class="o">.</span> <span class="s">&quot;ugrave&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">ú</span> <span class="o">.</span> <span class="s">&quot;uacute&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">û</span> <span class="o">.</span> <span class="s">&quot;ucirc&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">ü</span> <span class="o">.</span> <span class="s">&quot;uuml&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">ý</span> <span class="o">.</span> <span class="s">&quot;yacute&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">þ</span> <span class="o">.</span> <span class="s">&quot;thorn&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">ÿ</span> <span class="o">.</span> <span class="s">&quot;yuml&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Œ</span> <span class="o">.</span> <span class="s">&quot;OElig&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">œ</span> <span class="o">.</span> <span class="s">&quot;oelig&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Š</span> <span class="o">.</span> <span class="s">&quot;Scaron&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">š</span> <span class="o">.</span> <span class="s">&quot;scaron&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Ÿ</span> <span class="o">.</span> <span class="s">&quot;Yuml&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">ƒ</span> <span class="o">.</span> <span class="s">&quot;fnof&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">ˆ</span> <span class="o">.</span> <span class="s">&quot;circ&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">˜</span> <span class="o">.</span> <span class="s">&quot;tilde&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Α</span> <span class="o">.</span> <span class="s">&quot;Alpha&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Β</span> <span class="o">.</span> <span class="s">&quot;Beta&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Γ</span> <span class="o">.</span> <span class="s">&quot;Gamma&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Δ</span> <span class="o">.</span> <span class="s">&quot;Delta&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Ε</span> <span class="o">.</span> <span class="s">&quot;Epsilon&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Ζ</span> <span class="o">.</span> <span class="s">&quot;Zeta&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Η</span> <span class="o">.</span> <span class="s">&quot;Eta&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Θ</span> <span class="o">.</span> <span class="s">&quot;Theta&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Ι</span> <span class="o">.</span> <span class="s">&quot;Iota&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Κ</span> <span class="o">.</span> <span class="s">&quot;Kappa&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Λ</span> <span class="o">.</span> <span class="s">&quot;Lambda&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Μ</span> <span class="o">.</span> <span class="s">&quot;Mu&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Ν</span> <span class="o">.</span> <span class="s">&quot;Nu&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Ξ</span> <span class="o">.</span> <span class="s">&quot;Xi&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Ο</span> <span class="o">.</span> <span class="s">&quot;Omicron&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Π</span> <span class="o">.</span> <span class="s">&quot;Pi&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Ρ</span> <span class="o">.</span> <span class="s">&quot;Rho&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Σ</span> <span class="o">.</span> <span class="s">&quot;Sigma&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Τ</span> <span class="o">.</span> <span class="s">&quot;Tau&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Υ</span> <span class="o">.</span> <span class="s">&quot;Upsilon&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Φ</span> <span class="o">.</span> <span class="s">&quot;Phi&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Χ</span> <span class="o">.</span> <span class="s">&quot;Chi&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Ψ</span> <span class="o">.</span> <span class="s">&quot;Psi&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">Ω</span> <span class="o">.</span> <span class="s">&quot;Omega&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">α</span> <span class="o">.</span> <span class="s">&quot;alpha&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">β</span> <span class="o">.</span> <span class="s">&quot;beta&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">γ</span> <span class="o">.</span> <span class="s">&quot;gamma&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">δ</span> <span class="o">.</span> <span class="s">&quot;delta&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">ε</span> <span class="o">.</span> <span class="s">&quot;epsilon&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">ζ</span> <span class="o">.</span> <span class="s">&quot;zeta&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">η</span> <span class="o">.</span> <span class="s">&quot;eta&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">θ</span> <span class="o">.</span> <span class="s">&quot;theta&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">ι</span> <span class="o">.</span> <span class="s">&quot;iota&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">κ</span> <span class="o">.</span> <span class="s">&quot;kappa&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">λ</span> <span class="o">.</span> <span class="s">&quot;lambda&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">μ</span> <span class="o">.</span> <span class="s">&quot;mu&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">ν</span> <span class="o">.</span> <span class="s">&quot;nu&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">ξ</span> <span class="o">.</span> <span class="s">&quot;xi&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">ο</span> <span class="o">.</span> <span class="s">&quot;omicron&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">π</span> <span class="o">.</span> <span class="s">&quot;pi&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">ρ</span> <span class="o">.</span> <span class="s">&quot;rho&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">ς</span> <span class="o">.</span> <span class="s">&quot;sigmaf&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">σ</span> <span class="o">.</span> <span class="s">&quot;sigma&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">τ</span> <span class="o">.</span> <span class="s">&quot;tau&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">υ</span> <span class="o">.</span> <span class="s">&quot;upsilon&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">φ</span> <span class="o">.</span> <span class="s">&quot;phi&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">χ</span> <span class="o">.</span> <span class="s">&quot;chi&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">ψ</span> <span class="o">.</span> <span class="s">&quot;psi&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">ω</span> <span class="o">.</span> <span class="s">&quot;omega&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">ϑ</span> <span class="o">.</span> <span class="s">&quot;thetasym&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">ϒ</span> <span class="o">.</span> <span class="s">&quot;upsih&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">ϖ</span> <span class="o">.</span> <span class="s">&quot;piv&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err"> </span> <span class="o">.</span> <span class="s">&quot;ensp&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err"> </span> <span class="o">.</span> <span class="s">&quot;emsp&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err"> </span> <span class="o">.</span> <span class="s">&quot;thinsp&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">–</span> <span class="o">.</span> <span class="s">&quot;ndash&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">—</span> <span class="o">.</span> <span class="s">&quot;mdash&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">‘</span> <span class="o">.</span> <span class="s">&quot;lsquo&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">’</span> <span class="o">.</span> <span class="s">&quot;rsquo&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">‚</span> <span class="o">.</span> <span class="s">&quot;sbquo&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">“</span> <span class="o">.</span> <span class="s">&quot;ldquo&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">”</span> <span class="o">.</span> <span class="s">&quot;rdquo&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">„</span> <span class="o">.</span> <span class="s">&quot;bdquo&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">†</span> <span class="o">.</span> <span class="s">&quot;dagger&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">‡</span> <span class="o">.</span> <span class="s">&quot;Dagger&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">•</span> <span class="o">.</span> <span class="s">&quot;bull&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">…</span> <span class="o">.</span> <span class="s">&quot;hellip&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">‰</span> <span class="o">.</span> <span class="s">&quot;permil&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">′</span> <span class="o">.</span> <span class="s">&quot;prime&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">″</span> <span class="o">.</span> <span class="s">&quot;Prime&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">‹</span> <span class="o">.</span> <span class="s">&quot;lsaquo&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">›</span> <span class="o">.</span> <span class="s">&quot;rsaquo&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">‾</span> <span class="o">.</span> <span class="s">&quot;oline&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">⁄</span> <span class="o">.</span> <span class="s">&quot;frasl&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">€</span> <span class="o">.</span> <span class="s">&quot;euro&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">ℑ</span> <span class="o">.</span> <span class="s">&quot;image&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">℘</span> <span class="o">.</span> <span class="s">&quot;weierp&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">ℜ</span> <span class="o">.</span> <span class="s">&quot;real&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">&#x2122;</span> <span class="o">.</span> <span class="s">&quot;trade&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">ℵ</span> <span class="o">.</span> <span class="s">&quot;alefsym&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">←</span> <span class="o">.</span> <span class="s">&quot;larr&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">↑</span> <span class="o">.</span> <span class="s">&quot;uarr&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">→</span> <span class="o">.</span> <span class="s">&quot;rarr&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">↓</span> <span class="o">.</span> <span class="s">&quot;darr&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">&#x2194;</span> <span class="o">.</span> <span class="s">&quot;harr&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">↵</span> <span class="o">.</span> <span class="s">&quot;crarr&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">⇐</span> <span class="o">.</span> <span class="s">&quot;lArr&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">⇑</span> <span class="o">.</span> <span class="s">&quot;uArr&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">⇒</span> <span class="o">.</span> <span class="s">&quot;rArr&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">⇓</span> <span class="o">.</span> <span class="s">&quot;dArr&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">⇔</span> <span class="o">.</span> <span class="s">&quot;hArr&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">∀</span> <span class="o">.</span> <span class="s">&quot;forall&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">∂</span> <span class="o">.</span> <span class="s">&quot;part&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">∃</span> <span class="o">.</span> <span class="s">&quot;exist&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">∅</span> <span class="o">.</span> <span class="s">&quot;empty&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">∇</span> <span class="o">.</span> <span class="s">&quot;nabla&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">∈</span> <span class="o">.</span> <span class="s">&quot;isin&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">∉</span> <span class="o">.</span> <span class="s">&quot;notin&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">∋</span> <span class="o">.</span> <span class="s">&quot;ni&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">∏</span> <span class="o">.</span> <span class="s">&quot;prod&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">∑</span> <span class="o">.</span> <span class="s">&quot;sum&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">−</span> <span class="o">.</span> <span class="s">&quot;minus&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">∗</span> <span class="o">.</span> <span class="s">&quot;lowast&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">√</span> <span class="o">.</span> <span class="s">&quot;radic&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">∝</span> <span class="o">.</span> <span class="s">&quot;prop&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">∞</span> <span class="o">.</span> <span class="s">&quot;infin&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">∠</span> <span class="o">.</span> <span class="s">&quot;ang&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">∧</span> <span class="o">.</span> <span class="s">&quot;and&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">∨</span> <span class="o">.</span> <span class="s">&quot;or&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">∩</span> <span class="o">.</span> <span class="s">&quot;cap&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">∪</span> <span class="o">.</span> <span class="s">&quot;cup&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">∫</span> <span class="o">.</span> <span class="s">&quot;int&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">∴</span> <span class="o">.</span> <span class="s">&quot;there4&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">∼</span> <span class="o">.</span> <span class="s">&quot;sim&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">≅</span> <span class="o">.</span> <span class="s">&quot;cong&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">≈</span> <span class="o">.</span> <span class="s">&quot;asymp&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">≠</span> <span class="o">.</span> <span class="s">&quot;ne&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">≡</span> <span class="o">.</span> <span class="s">&quot;equiv&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">≤</span> <span class="o">.</span> <span class="s">&quot;le&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">≥</span> <span class="o">.</span> <span class="s">&quot;ge&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">⊂</span> <span class="o">.</span> <span class="s">&quot;sub&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">⊃</span> <span class="o">.</span> <span class="s">&quot;sup&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">⊄</span> <span class="o">.</span> <span class="s">&quot;nsub&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">⊆</span> <span class="o">.</span> <span class="s">&quot;sube&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">⊇</span> <span class="o">.</span> <span class="s">&quot;supe&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">⊕</span> <span class="o">.</span> <span class="s">&quot;oplus&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">⊗</span> <span class="o">.</span> <span class="s">&quot;otimes&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">⊥</span> <span class="o">.</span> <span class="s">&quot;perp&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">⋅</span> <span class="o">.</span> <span class="s">&quot;sdot&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">⋮</span> <span class="o">.</span> <span class="s">&quot;vellip&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">⌈</span> <span class="o">.</span> <span class="s">&quot;lceil&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">⌉</span> <span class="o">.</span> <span class="s">&quot;rceil&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">⌊</span> <span class="o">.</span> <span class="s">&quot;lfloor&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">⌋</span> <span class="o">.</span> <span class="s">&quot;rfloor&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">〈</span> <span class="o">.</span> <span class="s">&quot;lang&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">〉</span> <span class="o">.</span> <span class="s">&quot;rang&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">◊</span> <span class="o">.</span> <span class="s">&quot;loz&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">&#x2660;</span> <span class="o">.</span> <span class="s">&quot;spades&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">&#x2663;</span> <span class="o">.</span> <span class="s">&quot;clubs&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">&#x2665;</span> <span class="o">.</span> <span class="s">&quot;hearts&quot;</span><span class="p">)</span>
     <span class="p">(</span><span class="o">#</span><span class="err">&#x2666;</span> <span class="o">.</span> <span class="s">&quot;diams&quot;</span><span class="p">))))</span>

<span class="p">(</span><span class="k">define </span><span class="p">(</span><span class="nf">string-&gt;escaped-html</span> <span class="nv">s</span> <span class="nv">port</span><span class="p">)</span>
  <span class="s">&quot;Write the HTML escaped form of S to PORT.&quot;</span>
  <span class="p">(</span><span class="k">define </span><span class="p">(</span><span class="nf">escape</span> <span class="nv">c</span><span class="p">)</span>
    <span class="p">(</span><span class="k">let </span><span class="p">((</span><span class="nf">escaped</span> <span class="p">(</span><span class="nf">hash-ref</span> <span class="nv">%escape-chars</span> <span class="nv">c</span><span class="p">)))</span>
      <span class="p">(</span><span class="k">if </span><span class="nv">escaped</span>
          <span class="p">(</span><span class="nf">format</span> <span class="nv">port</span> <span class="s">&quot;&amp;~a;&quot;</span> <span class="nv">escaped</span><span class="p">)</span>
          <span class="p">(</span><span class="nb">display </span><span class="nv">c</span> <span class="nv">port</span><span class="p">))))</span>
  <span class="p">(</span><span class="nf">string-for-each</span> <span class="nv">escape</span> <span class="nv">s</span><span class="p">))</span>

<span class="p">(</span><span class="k">define </span><span class="p">(</span><span class="nf">object-&gt;escaped-html</span> <span class="nv">obj</span> <span class="nv">port</span><span class="p">)</span>
  <span class="s">&quot;Write the HTML escaped form of OBJ to PORT.&quot;</span>
  <span class="p">(</span><span class="nf">string-&gt;escaped-html</span>
   <span class="p">(</span><span class="nf">call-with-output-string</span> <span class="p">(</span><span class="nf">cut</span> <span class="nv">display</span> <span class="nv">obj</span> <span class="nv">&lt;&gt;</span><span class="p">))</span>
   <span class="nv">port</span><span class="p">))</span>

<span class="p">(</span><span class="k">define </span><span class="p">(</span><span class="nf">attribute-value-&gt;html</span> <span class="nv">value</span> <span class="nv">port</span><span class="p">)</span>
  <span class="s">&quot;Write the HTML escaped form of VALUE to PORT.&quot;</span>
  <span class="p">(</span><span class="k">if </span><span class="p">(</span><span class="nb">string? </span><span class="nv">value</span><span class="p">)</span>
      <span class="p">(</span><span class="nf">string-&gt;escaped-html</span> <span class="nv">value</span> <span class="nv">port</span><span class="p">)</span>
      <span class="p">(</span><span class="nf">object-&gt;escaped-html</span> <span class="nv">value</span> <span class="nv">port</span><span class="p">)))</span>

<span class="p">(</span><span class="k">define </span><span class="p">(</span><span class="nf">attribute-&gt;html</span> <span class="nv">attr</span> <span class="nv">value</span> <span class="nv">port</span><span class="p">)</span>
  <span class="s">&quot;Write ATTR and VALUE to PORT.&quot;</span>
  <span class="p">(</span><span class="nf">format</span> <span class="nv">port</span> <span class="s">&quot;~a=&quot;&quot;</span> <span class="nv">attr</span><span class="p">)</span>
  <span class="p">(</span><span class="nf">attribute-value-&gt;html</span> <span class="nv">value</span> <span class="nv">port</span><span class="p">)</span>
  <span class="p">(</span><span class="nb">display </span><span class="sc">#&quot;</span> <span class="nv">port</span><span class="p">))</span>

<span class="p">(</span><span class="k">define </span><span class="p">(</span><span class="nf">element-&gt;html</span> <span class="nv">tag</span> <span class="nv">attrs</span> <span class="nv">body</span> <span class="nv">port</span><span class="p">)</span>
  <span class="s">&quot;Write the HTML TAG to PORT, where TAG has the attributes in the</span>
<span class="s">list ATTRS and the child nodes in BODY.&quot;</span>
  <span class="p">(</span><span class="nf">format</span> <span class="nv">port</span> <span class="s">&quot;&lt;~a&quot;</span> <span class="nv">tag</span><span class="p">)</span>
  <span class="p">(</span><span class="nb">for-each </span><span class="p">(</span><span class="nf">match-lambda</span>
             <span class="p">((</span><span class="nf">attr</span> <span class="nv">value</span><span class="p">)</span>
              <span class="p">(</span><span class="nb">display </span><span class="sc">#space</span> <span class="nv">port</span><span class="p">)</span>
              <span class="p">(</span><span class="nf">attribute-&gt;html</span> <span class="nv">attr</span> <span class="nv">value</span> <span class="nv">port</span><span class="p">)))</span>
            <span class="nv">attrs</span><span class="p">)</span>
  <span class="p">(</span><span class="k">if </span><span class="p">(</span><span class="k">and </span><span class="p">(</span><span class="nb">null? </span><span class="nv">body</span><span class="p">)</span> <span class="p">(</span><span class="nf">void-element?</span> <span class="nv">tag</span><span class="p">))</span>
      <span class="p">(</span><span class="nb">display </span><span class="s">&quot; /&gt;&quot;</span> <span class="nv">port</span><span class="p">)</span>
      <span class="p">(</span><span class="nf">begin</span>
        <span class="p">(</span><span class="nb">display </span><span class="o">#</span><span class="err"></span><span class="nv">&gt;</span> <span class="nv">port</span><span class="p">)</span>
        <span class="p">(</span><span class="nb">for-each </span><span class="p">(</span><span class="nf">cut</span> <span class="nv">sxml-&gt;html</span> <span class="nv">&lt;&gt;</span> <span class="nv">port</span><span class="p">)</span> <span class="nv">body</span><span class="p">)</span>
        <span class="p">(</span><span class="nf">format</span> <span class="nv">port</span> <span class="s">&quot;&lt;/~a&gt;&quot;</span> <span class="nv">tag</span><span class="p">))))</span>

<span class="p">(</span><span class="k">define </span><span class="p">(</span><span class="nf">doctype-&gt;html</span> <span class="nv">doctype</span> <span class="nv">port</span><span class="p">)</span>
  <span class="p">(</span><span class="nf">format</span> <span class="nv">port</span> <span class="s">&quot;&lt;!DOCTYPE ~a&gt;&quot;</span> <span class="nv">doctype</span><span class="p">))</span>

<span class="p">(</span><span class="nf">define*</span> <span class="p">(</span><span class="nf">sxml-&gt;html</span> <span class="nv">tree</span> <span class="o">#</span><span class="nv">:optional</span> <span class="p">(</span><span class="nf">port</span> <span class="p">(</span><span class="nf">current-output-port</span><span class="p">)))</span>
  <span class="s">&quot;Write the serialized HTML form of TREE to PORT.&quot;</span>
  <span class="p">(</span><span class="nf">match</span> <span class="nv">tree</span>
    <span class="p">(()</span> <span class="nv">*unspecified*</span><span class="p">)</span>
    <span class="p">((</span><span class="ss">&#39;doctype</span> <span class="nv">type</span><span class="p">)</span>
     <span class="p">(</span><span class="nf">doctype-&gt;html</span> <span class="nv">type</span> <span class="nv">port</span><span class="p">))</span>
    <span class="c1">;; Unescaped, raw HTML output</span>
    <span class="p">((</span><span class="ss">&#39;raw</span> <span class="nv">html</span><span class="p">)</span>
     <span class="p">(</span><span class="nb">display </span><span class="nv">html</span> <span class="nv">port</span><span class="p">))</span>
    <span class="p">(((</span><span class="nf">?</span> <span class="nv">symbol?</span> <span class="nv">tag</span><span class="p">)</span> <span class="p">(</span><span class="ss">&#39;@</span> <span class="nv">attrs</span> <span class="o">...</span><span class="p">)</span> <span class="nv">body</span> <span class="o">...</span><span class="p">)</span>
     <span class="p">(</span><span class="nf">element-&gt;html</span> <span class="nv">tag</span> <span class="nv">attrs</span> <span class="nv">body</span> <span class="nv">port</span><span class="p">))</span>
    <span class="p">(((</span><span class="nf">?</span> <span class="nv">symbol?</span> <span class="nv">tag</span><span class="p">)</span> <span class="nv">body</span> <span class="o">...</span><span class="p">)</span>
     <span class="p">(</span><span class="nf">element-&gt;html</span> <span class="nv">tag</span> <span class="o">&#39;</span><span class="p">()</span> <span class="nv">body</span> <span class="nv">port</span><span class="p">))</span>
    <span class="p">((</span><span class="nf">nodes</span> <span class="o">...</span><span class="p">)</span>
     <span class="p">(</span><span class="nb">for-each </span><span class="p">(</span><span class="nf">cut</span> <span class="nv">sxml-&gt;html</span> <span class="nv">&lt;&gt;</span> <span class="nv">port</span><span class="p">)</span> <span class="nv">nodes</span><span class="p">))</span>
    <span class="p">((</span><span class="nf">?</span> <span class="nv">string?</span> <span class="nv">text</span><span class="p">)</span>
     <span class="p">(</span><span class="nf">string-&gt;escaped-html</span> <span class="nv">text</span> <span class="nv">port</span><span class="p">))</span>
    <span class="c1">;; Render arbitrary Scheme objects, too.</span>
    <span class="p">(</span><span class="nf">obj</span> <span class="p">(</span><span class="nf">object-&gt;escaped-html</span> <span class="nv">obj</span> <span class="nv">port</span><span class="p">))))</span>
</pre>
</div>

<p class="syndicated-attribution"><em>From the blog <a href="http://dthompson.us/">dthompson</a> by <a href="https://cs.worcester.edu/author/0/" title="Read other posts by David Thompson">David Thompson</a></em> and used with permission of the author. All other rights reserved by the author.</p>]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">3948</post-id>	</item>
		<item>
		<title>Reproducible Development Environments with GNU Guix</title>
		<link>http://dthompson.us/reproducible-development-environments-with-gnu-guix.html</link>
		
		<dc:creator><![CDATA[David Thompson]]></dc:creator>
		<pubDate>Sun, 09 Nov 2014 03:00:00 +0000</pubDate>
				<category><![CDATA[gnu]]></category>
		<category><![CDATA[guile]]></category>
		<category><![CDATA[guix]]></category>
		<category><![CDATA[scheme]]></category>
		<category><![CDATA[WSU]]></category>
		<guid isPermaLink="false">http://cs.worcester.edu/blog/?guid=9a5370ca9c54a34a5168828756ea3cb0</guid>

					<description><![CDATA[<p>If you're a software developer, then you probably know very well that
setting up a project's development environment for the first time can
be a real pain.  Installing all of the necessary dependencies using
your system's package manager can be very tedious.  To "solve" this
problem, we have resorted to inventing new package managers and
dependency bundlers for pretty much every programming language.  Ruby
has rubygems and bundler, Python has pip and virtualenv, PHP has
composer, node.js has npm, and so on.  Wouldn't it be nice to instead
have a single package manager that can handle it all?  Enter <a href="https://gnu.org/software/guix">GNU
Guix</a>, a purely functional package manager and GNU/Linux
distribution.  Using Guix, you can easily create a development
environment for any software project using the <tt>guix environment</tt>
tool.</p>
<p><tt>guix environment</tt> is a new utility added in Guix 0.8, which should
be released in a few weeks.  It accepts one on more packages as input
and produces a new shell environment in which all of the dependencies
for those packages are made available.  For example, <tt>guix
environment emacs</tt> will get you everything you need to build GNU
Emacs from a source release tarball.  By default, your <tt>$SHELL</tt> is
spawned, but you may opt to use any arbitrary shell command instead.
If you've used Nix before, you may notice that this sounds exactly
like <tt><span>nix-shell</span></tt>, and that's because it was what inspired me to
write <tt>guix environment</tt>.</p>
<p>Now, let's take a look at an example.  One of my hobby projects is
<a href="https://gitorious.org/sly/sly">Sly</a>, a game engine written in Guile Scheme.  Here's the relevant Guix
code that will produce a complete development environment:</p>
<div><pre><span>;;; Copyright (C) 2014 David Thompson &#60;davet@gnu.org&#62;</span>
<span>;;;</span>
<span>;;; Sly is free software: you can redistribute it and/or modify it</span>
<span>;;; under the terms of the GNU General Public License as published by</span>
<span>;;; the Free Software Foundation, either version 3 of the License, or</span>
<span>;;; (at your option) any later version.</span>

<span>(</span><span>use-modules</span> <span>(</span><span>guix</span> <span>packages</span><span>)</span>
             <span>(</span><span>guix</span> <span>licenses</span><span>)</span>
             <span>(</span><span>guix</span> <span>build-system</span> <span>gnu</span><span>)</span>
             <span>(</span><span>gnu</span> <span>packages</span><span>)</span>
             <span>(</span><span>gnu</span> <span>packages</span> <span>autotools</span><span>)</span>
             <span>(</span><span>gnu</span> <span>packages</span> <span>guile</span><span>)</span>
             <span>(</span><span>gnu</span> <span>packages</span> <span>gl</span><span>)</span>
             <span>(</span><span>gnu</span> <span>packages</span> <span>pkg-config</span><span>)</span>
             <span>(</span><span>gnu</span> <span>packages</span> <span>sdl</span><span>)</span>
             <span>(</span><span>gnu</span> <span>packages</span> <span>maths</span><span>)</span>
             <span>(</span><span>gnu</span> <span>packages</span> <span>image</span><span>))</span>

<span>;; The development environment needs a tweaked LD_LIBRARY_PATH for</span>
<span>;; finding libfreeimage.</span>
<span>(</span><span>define </span><span>freeimage</span>
  <span>(</span><span>package</span> <span>(</span><span>inherit</span> <span>freeimage</span><span>)</span>
    <span>(</span><span>native-search-paths</span>
     <span>(</span><span>list </span><span>(</span><span>search-path-specification</span>
            <span>(</span><span>variable</span> <span>"LD_LIBRARY_PATH"</span><span>)</span>
            <span>(</span><span>directories</span> <span>'</span><span>(</span><span>"lib"</span><span>)))))))</span>

<span>(</span><span>package</span>
  <span>(</span><span>name</span> <span>"sly"</span><span>)</span>
  <span>(</span><span>version</span> <span>"0.0"</span><span>)</span>
  <span>(</span><span>source</span> <span>#f</span><span>)</span>
  <span>(</span><span>build-system</span> <span>gnu-build-system</span><span>)</span>
  <span>(</span><span>inputs</span>
   <span>`</span><span>((</span><span>"pkg-config"</span> <span>,</span><span>pkg-config</span><span>)</span>
     <span>(</span><span>"autoconf"</span> <span>,</span><span>autoconf</span><span>)</span>
     <span>(</span><span>"automake"</span> <span>,</span><span>automake</span><span>)</span>
     <span>(</span><span>"guile"</span> <span>,</span><span>guile-2</span><span>.</span><span>0</span><span>)</span>
     <span>(</span><span>"guile-sdl"</span> <span>,</span><span>guile-sdl</span><span>)</span>
     <span>(</span><span>"guile-opengl"</span> <span>,</span><span>guile-opengl</span><span>)</span>
     <span>(</span><span>"gsl"</span> <span>,</span><span>gsl</span><span>)</span>
     <span>(</span><span>"freeimage"</span> <span>,</span><span>freeimage</span><span>)</span>
     <span>(</span><span>"mesa"</span> <span>,</span><span>mesa</span><span>)))</span>
  <span>(</span><span>synopsis</span> <span>"2D/3D game engine for GNU Guile"</span><span>)</span>
  <span>(</span><span>description</span> <span>"Sly is a 2D/3D game engine written in Guile Scheme.</span>
<span>Sly differs from most game engines in that it emphasizes functional</span>
<span>reactive programming and live coding."</span><span>)</span>
  <span>(</span><span>home-page</span> <span>"https://gitorious.org/sly/sly"</span><span>)</span>
  <span>(</span><span>license</span> <span>gpl3+</span><span>))</span>
</pre></div>
<p>You may have noticed that the source field has been set to false.
This is because the package is not for building and installing.  It's
sole purpose is to provide the necessary software needed to build Sly
from a fresh git checkout.</p>
<p>Assuming this code is in a file called <tt>package.scm</tt>, you can simply
run <tt>guix environment <span>-l</span> package.scm</tt> to spawn a shell for hacking
on Sly.  By default, the environment created is an augmented version
of your pre-existing shell's environment.  This is convenient when you
want to use your installed software in the new environment, such as
git.  However, it's important to make sure that the environment really
does have everything needed for development without relying on any
impurities introduced by your existing environment.  Without verifying
this, new developers might be frustrated to find out that the
environment provided to them is incomplete.  To verify, pass the
<tt><span>--pure</span></tt> flag and build from scratch.</p>
<p>So, <tt>guix environment</tt> is a pretty nice way to acquire all the
dependencies you need to work on a project, but there is still a lot
of room for improvement.  What if you were working on a web
application that required a running PostgreSQL database, Redis server,
and XMPP server?  It would be really great if Guix could handle
setting this up for you, too, a la Vagrant.  To do so, <tt>guix
environment</tt> could use the existing features of <tt>guix system</tt> to
spawn a new virtual machine that shared the host system's package
store and the project's source tree, and then spawn a shell with your
development environment.  I hope to implement this in the
not-too-distant future.  Until next time, happy hacking!</p>]]></description>
										<content:encoded><![CDATA[<p>If you&#8217;re a software developer, then you probably know very well that<br />
setting up a project&#8217;s development environment for the first time can<br />
be a real pain.  Installing all of the necessary dependencies using<br />
your system&#8217;s package manager can be very tedious.  To &quot;solve&quot; this<br />
problem, we have resorted to inventing new package managers and<br />
dependency bundlers for pretty much every programming language.  Ruby<br />
has rubygems and bundler, Python has pip and virtualenv, PHP has<br />
composer, node.js has npm, and so on.  Wouldn&#8217;t it be nice to instead<br />
have a single package manager that can handle it all?  Enter <a class="reference external" href="https://gnu.org/software/guix">GNU<br />
Guix</a>, a purely functional package manager and GNU/Linux<br />
distribution.  Using Guix, you can easily create a development<br />
environment for any software project using the <tt class="docutils literal">guix environment</tt><br />
tool.</p>
<p><tt class="docutils literal">guix environment</tt> is a new utility added in Guix 0.8, which should<br />
be released in a few weeks.  It accepts one on more packages as input<br />
and produces a new shell environment in which all of the dependencies<br />
for those packages are made available.  For example, <tt class="docutils literal">guix<br />
environment emacs</tt> will get you everything you need to build GNU<br />
Emacs from a source release tarball.  By default, your <tt class="docutils literal">$SHELL</tt> is<br />
spawned, but you may opt to use any arbitrary shell command instead.<br />
If you&#8217;ve used Nix before, you may notice that this sounds exactly<br />
like <tt class="docutils literal"><span class="pre">nix-shell</span></tt>, and that&#8217;s because it was what inspired me to<br />
write <tt class="docutils literal">guix environment</tt>.</p>
<p>Now, let&#8217;s take a look at an example.  One of my hobby projects is<br />
<a class="reference external" href="https://gitorious.org/sly/sly">Sly</a>, a game engine written in Guile Scheme.  Here&#8217;s the relevant Guix<br />
code that will produce a complete development environment:</p>
<div class="highlight">
<pre><span class="c1">;;; Copyright (C) 2014 David Thompson &lt;davet@gnu.org&gt;</span>
<span class="c1">;;;</span>
<span class="c1">;;; Sly is free software: you can redistribute it and/or modify it</span>
<span class="c1">;;; under the terms of the GNU General Public License as published by</span>
<span class="c1">;;; the Free Software Foundation, either version 3 of the License, or</span>
<span class="c1">;;; (at your option) any later version.</span>

<span class="p">(</span><span class="nf">use-modules</span> <span class="p">(</span><span class="nf">guix</span> <span class="nv">packages</span><span class="p">)</span>
             <span class="p">(</span><span class="nf">guix</span> <span class="nv">licenses</span><span class="p">)</span>
             <span class="p">(</span><span class="nf">guix</span> <span class="nv">build-system</span> <span class="nv">gnu</span><span class="p">)</span>
             <span class="p">(</span><span class="nf">gnu</span> <span class="nv">packages</span><span class="p">)</span>
             <span class="p">(</span><span class="nf">gnu</span> <span class="nv">packages</span> <span class="nv">autotools</span><span class="p">)</span>
             <span class="p">(</span><span class="nf">gnu</span> <span class="nv">packages</span> <span class="nv">guile</span><span class="p">)</span>
             <span class="p">(</span><span class="nf">gnu</span> <span class="nv">packages</span> <span class="nv">gl</span><span class="p">)</span>
             <span class="p">(</span><span class="nf">gnu</span> <span class="nv">packages</span> <span class="nv">pkg-config</span><span class="p">)</span>
             <span class="p">(</span><span class="nf">gnu</span> <span class="nv">packages</span> <span class="nv">sdl</span><span class="p">)</span>
             <span class="p">(</span><span class="nf">gnu</span> <span class="nv">packages</span> <span class="nv">maths</span><span class="p">)</span>
             <span class="p">(</span><span class="nf">gnu</span> <span class="nv">packages</span> <span class="nv">image</span><span class="p">))</span>

<span class="c1">;; The development environment needs a tweaked LD_LIBRARY_PATH for</span>
<span class="c1">;; finding libfreeimage.</span>
<span class="p">(</span><span class="k">define </span><span class="nv">freeimage</span>
  <span class="p">(</span><span class="nf">package</span> <span class="p">(</span><span class="nf">inherit</span> <span class="nv">freeimage</span><span class="p">)</span>
    <span class="p">(</span><span class="nf">native-search-paths</span>
     <span class="p">(</span><span class="nb">list </span><span class="p">(</span><span class="nf">search-path-specification</span>
            <span class="p">(</span><span class="nf">variable</span> <span class="s">&quot;LD_LIBRARY_PATH&quot;</span><span class="p">)</span>
            <span class="p">(</span><span class="nf">directories</span> <span class="o">&#39;</span><span class="p">(</span><span class="s">&quot;lib&quot;</span><span class="p">)))))))</span>

<span class="p">(</span><span class="nf">package</span>
  <span class="p">(</span><span class="nf">name</span> <span class="s">&quot;sly&quot;</span><span class="p">)</span>
  <span class="p">(</span><span class="nf">version</span> <span class="s">&quot;0.0&quot;</span><span class="p">)</span>
  <span class="p">(</span><span class="nf">source</span> <span class="no">#f</span><span class="p">)</span>
  <span class="p">(</span><span class="nf">build-system</span> <span class="nv">gnu-build-system</span><span class="p">)</span>
  <span class="p">(</span><span class="nf">inputs</span>
   <span class="o">`</span><span class="p">((</span><span class="s">&quot;pkg-config&quot;</span> <span class="o">,</span><span class="nv">pkg-config</span><span class="p">)</span>
     <span class="p">(</span><span class="s">&quot;autoconf&quot;</span> <span class="o">,</span><span class="nv">autoconf</span><span class="p">)</span>
     <span class="p">(</span><span class="s">&quot;automake&quot;</span> <span class="o">,</span><span class="nv">automake</span><span class="p">)</span>
     <span class="p">(</span><span class="s">&quot;guile&quot;</span> <span class="o">,</span><span class="nv">guile-2</span><span class="o">.</span><span class="mi">0</span><span class="p">)</span>
     <span class="p">(</span><span class="s">&quot;guile-sdl&quot;</span> <span class="o">,</span><span class="nv">guile-sdl</span><span class="p">)</span>
     <span class="p">(</span><span class="s">&quot;guile-opengl&quot;</span> <span class="o">,</span><span class="nv">guile-opengl</span><span class="p">)</span>
     <span class="p">(</span><span class="s">&quot;gsl&quot;</span> <span class="o">,</span><span class="nv">gsl</span><span class="p">)</span>
     <span class="p">(</span><span class="s">&quot;freeimage&quot;</span> <span class="o">,</span><span class="nv">freeimage</span><span class="p">)</span>
     <span class="p">(</span><span class="s">&quot;mesa&quot;</span> <span class="o">,</span><span class="nv">mesa</span><span class="p">)))</span>
  <span class="p">(</span><span class="nf">synopsis</span> <span class="s">&quot;2D/3D game engine for GNU Guile&quot;</span><span class="p">)</span>
  <span class="p">(</span><span class="nf">description</span> <span class="s">&quot;Sly is a 2D/3D game engine written in Guile Scheme.</span>
<span class="s">Sly differs from most game engines in that it emphasizes functional</span>
<span class="s">reactive programming and live coding.&quot;</span><span class="p">)</span>
  <span class="p">(</span><span class="nf">home-page</span> <span class="s">&quot;https://gitorious.org/sly/sly&quot;</span><span class="p">)</span>
  <span class="p">(</span><span class="nf">license</span> <span class="nv">gpl3+</span><span class="p">))</span>
</pre>
</div>
<p>You may have noticed that the source field has been set to false.<br />
This is because the package is not for building and installing.  It&#8217;s<br />
sole purpose is to provide the necessary software needed to build Sly<br />
from a fresh git checkout.</p>
<p>Assuming this code is in a file called <tt class="docutils literal">package.scm</tt>, you can simply<br />
run <tt class="docutils literal">guix environment <span class="pre">-l</span> package.scm</tt> to spawn a shell for hacking<br />
on Sly.  By default, the environment created is an augmented version<br />
of your pre-existing shell&#8217;s environment.  This is convenient when you<br />
want to use your installed software in the new environment, such as<br />
git.  However, it&#8217;s important to make sure that the environment really<br />
does have everything needed for development without relying on any<br />
impurities introduced by your existing environment.  Without verifying<br />
this, new developers might be frustrated to find out that the<br />
environment provided to them is incomplete.  To verify, pass the<br />
<tt class="docutils literal"><span class="pre">--pure</span></tt> flag and build from scratch.</p>
<p>So, <tt class="docutils literal">guix environment</tt> is a pretty nice way to acquire all the<br />
dependencies you need to work on a project, but there is still a lot<br />
of room for improvement.  What if you were working on a web<br />
application that required a running PostgreSQL database, Redis server,<br />
and XMPP server?  It would be really great if Guix could handle<br />
setting this up for you, too, a la Vagrant.  To do so, <tt class="docutils literal">guix<br />
environment</tt> could use the existing features of <tt class="docutils literal">guix system</tt> to<br />
spawn a new virtual machine that shared the host system&#8217;s package<br />
store and the project&#8217;s source tree, and then spawn a shell with your<br />
development environment.  I hope to implement this in the<br />
not-too-distant future.  Until next time, happy hacking!</p>

<p class="syndicated-attribution"><em>From the blog <a href="http://dthompson.us/">dthompson</a> by <a href="https://cs.worcester.edu/author/0/" title="Read other posts by David Thompson">David Thompson</a></em> and used with permission of the author. All other rights reserved by the author.</p>]]></content:encoded>
					
		
		<enclosure url="" length="0" type="" />

		<post-id xmlns="com-wordpress:feed-additions:1">3493</post-id>	</item>
		<item>
		<title>Guile-2D is now named &#034;Sly&#034;</title>
		<link>http://dthompson.us/guile-2d-is-now-named-sly.html</link>
		
		<dc:creator><![CDATA[David Thompson]]></dc:creator>
		<pubDate>Mon, 11 Aug 2014 23:00:00 +0000</pubDate>
				<category><![CDATA[FOSS]]></category>
		<category><![CDATA[gamedev]]></category>
		<category><![CDATA[gnu]]></category>
		<category><![CDATA[guile]]></category>
		<category><![CDATA[scheme]]></category>
		<category><![CDATA[WSU]]></category>
		<guid isPermaLink="false">http://cs.worcester.edu/blog/?guid=1d3c5cfeebf5c8b945cd1a42397ea1c7</guid>

					<description><![CDATA[Guile-2D the a working title for my game engine written in Guile
Scheme.  The name has become very limiting since I realized that it
wouldn't be much extra work to support 3D graphics.  After much
indecision, I've finally decided on an official name: S...]]></description>
										<content:encoded><![CDATA[<p>Guile-2D the a working title for my game engine written in Guile<br />
Scheme.  The name has become very limiting since I realized that it<br />
wouldn&#8217;t be much extra work to support 3D graphics.  After much<br />
indecision, I&#8217;ve finally decided on an official name: Sly.  I think<br />
it&#8217;s a great name.  It&#8217;s short, easy to type, and slyness is one of<br />
the definitions of &#8220;guile&#8221;.</p>
<p>In other news:</p>
<ul>
<li>
<p>Sly has a new contributor!<br />
  <a href="https://gitorious.org/~seconded">Jordan Russel</a> has written a<br />
  <a href="https://gitorious.org/sly/sly/source/9231dca37261de8269149ccad4517acad41aa015:sly/joystick.scm">new module</a><br />
  that provides joystick input support.</p>
</li>
<li>
<p>I have written a<br />
  <a href="https://gitorious.org/sly/sly/source/9231dca37261de8269149ccad4517acad41aa015:sly/transition.scm">module for describing animations</a>.</p>
</li>
<li>
<p>I have been slowly working on a scene graph implementation that<br />
  plays well with the functional reactive programming API.</p>
</li>
<li>
<p>As mentioned above, 3D graphics support is on the way!  So far, I<br />
  have implemented a perspective projection matrix, a &#8220;look at&#8221;<br />
  matrix, and a cube primitive.</p>
</li>
</ul>
<p><img data-recalc-dims="1" decoding="async" alt="3D Scene Graph" src="https://i0.wp.com/dthompson.us/images/sly/scene-graph-prototype.png?w=625" /></p>
<p>Check out the Sly source code repository on<br />
<a href="https://gitorious.org/sly/sly">Gitorious</a>!</p>

<p class="syndicated-attribution"><em>From the blog <a href="http://dthompson.us/">dthompson</a> by <a href="https://cs.worcester.edu/author/0/" title="Read other posts by David Thompson">David Thompson</a></em> and used with permission of the author. All other rights reserved by the author.</p>]]></content:encoded>
					
		
		<enclosure url="" length="0" type="" />

		<post-id xmlns="com-wordpress:feed-additions:1">3388</post-id>	</item>
		<item>
		<title>Live Asset Reloading with guile-2d</title>
		<link>http://dthompson.us/live-asset-reloading-with-guile-2d.html</link>
		
		<dc:creator><![CDATA[David Thompson]]></dc:creator>
		<pubDate>Mon, 05 May 2014 02:00:00 +0000</pubDate>
				<category><![CDATA[FOSS]]></category>
		<category><![CDATA[gamedev]]></category>
		<category><![CDATA[gnu]]></category>
		<category><![CDATA[guile]]></category>
		<category><![CDATA[scheme]]></category>
		<category><![CDATA[WSU]]></category>
		<guid isPermaLink="false">http://cs.worcester.edu/blog/?guid=5d0b0d652fac70b1dd2c0f703975b135</guid>

					<description><![CDATA[<p>Guile-2d provides a dynamic environment in which a developer can build
a game incrementally as it runs via the Guile REPL.  It's nice to be
able to hot-swap code and have the running game reflect the changes
made, but what about the game data files?  If an image file or other
game asset is modified, it would be nice if the game engine took
notice and reloaded it automatically.  This is what guile-2d's live
asset reloading feature does.</p>
<p>The new <tt>(2d <span>live-reload)</span></tt> module provides the <tt><span>live-reload</span></tt>
procedure.  <tt><span>live-reload</span></tt> takes a procedure like <tt><span>load-texture</span></tt>
and returns a new procedure that adds the live reload magic.  The new
procedure returns assets wrapped in a signal, a time-varying value.  A
coroutine is started that periodically checks if the asset file has
been modified, and if so, reloads the asset and propagates it via the
signal.  Game objects that depend on the asset will be regenerated
immediately.</p>
<p>Here's some example code:</p>
<div><pre><span>(</span><span>define </span><span>load-texture/live</span>
  <span>(</span><span>live-reload</span> <span>load-texture</span><span>))</span>

<span>(</span><span>define-signal</span> <span>texture</span>
  <span>(</span><span>load-texture/live</span> <span>"images/p1_front.png"</span><span>))</span>

<span>(</span><span>define-signal</span> <span>sprite</span>
  <span>(</span><span>signal-map</span>
   <span>(</span><span>lambda </span><span>(</span><span>texture</span><span>)</span>
     <span>(</span><span>make-sprite</span> <span>texture</span>
                  <span>#</span><span>:position</span> <span>(</span><span>vector2</span> <span>320</span> <span>240</span><span>)))</span>
   <span>texture</span><span>))</span>
</pre></div>
<p><tt><span>load-texture/live</span></tt> loads textures and reloads them when they change
on disk.  Every time the texture is reloaded, the sprite is
regenerated using the new texture.</p>
<p>Here's a screencast to see live reloading in action:</p>
<p>Guile-2d is ever-so-slowly approaching a 0.2 release.  Stay tuned!</p>]]></description>
										<content:encoded><![CDATA[<p>Guile-2d provides a dynamic environment in which a developer can build<br />
a game incrementally as it runs via the Guile REPL.  It&#8217;s nice to be<br />
able to hot-swap code and have the running game reflect the changes<br />
made, but what about the game data files?  If an image file or other<br />
game asset is modified, it would be nice if the game engine took<br />
notice and reloaded it automatically.  This is what guile-2d&#8217;s live<br />
asset reloading feature does.</p>
<p>The new <tt class="docutils literal">(2d <span class="pre">live-reload)</span></tt> module provides the <tt class="docutils literal"><span class="pre">live-reload</span></tt><br />
procedure.  <tt class="docutils literal"><span class="pre">live-reload</span></tt> takes a procedure like <tt class="docutils literal"><span class="pre">load-texture</span></tt><br />
and returns a new procedure that adds the live reload magic.  The new<br />
procedure returns assets wrapped in a signal, a time-varying value.  A<br />
coroutine is started that periodically checks if the asset file has<br />
been modified, and if so, reloads the asset and propagates it via the<br />
signal.  Game objects that depend on the asset will be regenerated<br />
immediately.</p>
<p>Here&#8217;s some example code:</p>
<div class="highlight">
<pre><span class="p">(</span><span class="k">define </span><span class="nv">load-texture/live</span>
  <span class="p">(</span><span class="nf">live-reload</span> <span class="nv">load-texture</span><span class="p">))</span>

<span class="p">(</span><span class="nf">define-signal</span> <span class="nv">texture</span>
  <span class="p">(</span><span class="nf">load-texture/live</span> <span class="s">&quot;images/p1_front.png&quot;</span><span class="p">))</span>

<span class="p">(</span><span class="nf">define-signal</span> <span class="nv">sprite</span>
  <span class="p">(</span><span class="nf">signal-map</span>
   <span class="p">(</span><span class="k">lambda </span><span class="p">(</span><span class="nf">texture</span><span class="p">)</span>
     <span class="p">(</span><span class="nf">make-sprite</span> <span class="nv">texture</span>
                  <span class="o">#</span><span class="nv">:position</span> <span class="p">(</span><span class="nf">vector2</span> <span class="mi">320</span> <span class="mi">240</span><span class="p">)))</span>
   <span class="nv">texture</span><span class="p">))</span>
</pre>
</div>
<p><tt class="docutils literal"><span class="pre">load-texture/live</span></tt> loads textures and reloads them when they change<br />
on disk.  Every time the texture is reloaded, the sprite is<br />
regenerated using the new texture.</p>
<p>Here&#8217;s a screencast to see live reloading in action:</p>
<p><video src="http://media.dthompson.us/mgoblin_media/media_entries/10/Screencast_from_05-04-2014_053639_PM.medium.webm"
       style="width:640px;height:360px;" controls><br />
</video></p>
<p>Guile-2d is ever-so-slowly approaching a 0.2 release.  Stay tuned!</p>

<p class="syndicated-attribution"><em>From the blog <a href="http://dthompson.us/">dthompson</a> by <a href="https://cs.worcester.edu/author/0/" title="Read other posts by David Thompson">David Thompson</a></em> and used with permission of the author. All other rights reserved by the author.</p>]]></content:encoded>
					
		
		<enclosure url="" length="0" type="" />

		<post-id xmlns="com-wordpress:feed-additions:1">2994</post-id>	</item>
		<item>
		<title>Functional Reactive Programming in Scheme with guile-2d</title>
		<link>http://dthompson.us/functional-reactive-programming-in-scheme-with-guile-2d.html</link>
		
		<dc:creator><![CDATA[David Thompson]]></dc:creator>
		<pubDate>Mon, 10 Mar 2014 01:00:00 +0000</pubDate>
				<category><![CDATA[FOSS]]></category>
		<category><![CDATA[gamedev]]></category>
		<category><![CDATA[gnu]]></category>
		<category><![CDATA[guile]]></category>
		<category><![CDATA[scheme]]></category>
		<category><![CDATA[WSU]]></category>
		<guid isPermaLink="false">http://cs.worcester.edu/blog/?guid=e1e33aff69b508d40050466a1116adc0</guid>

					<description><![CDATA[<p>Last month, the <a href="http://gnu.org/s/guile">GNU Guile</a> project celebrated the 3rd anniversary of
its 2.0 release with a hacker <a href="http://savannah.gnu.org/forum/forum.php?forum_id=7887">potluck</a>.  Guilers were encouraged to
bring a tasty hack to the mailing list to share with everyone.  My
dish was a simple <a href="https://en.wikipedia.org/wiki/Functional_reactive_programming">functional reactive programming</a> library.</p>
<p>Functional reactive programming (FRP) provides a way to describe
time-varying values and their relationships using a functional and
declarative programming style.  To understand what this means, let's
investigate a typical variable definition in Scheme.  The expression
<tt>(define c (+ a b))</tt> defines the variable <tt>c</tt> to be the sum of
variables <tt>a</tt> and <tt>b</tt> at the time of evaluation.  If <tt>a</tt> or
<tt>b</tt> is assigned a new value, <tt>c</tt> remains the same.  However, for
applications that deal with state that transforms over time, it would
be convenient if we could define <tt>c</tt> to react to changes in <tt>a</tt>
and <tt>b</tt> by recomputing the sum.  Contrast this approach with the
more traditional style of modeling dynamic state via events and
callbacks.  A lot of programmers, myself included, have written code
with so many callbacks that the resulting program is unmaintainable
spaghetti code.  Callback hell is real, but if you accept FRP into
your heart then you will be saved!</p>
<p>By now you're probably wondering: "What the hell does all this mean?"
So, here's a real-world example of guile-2d's FRP API:</p>
<div><pre><span>(</span><span>define-signal</span> <span>position</span>
  <span>(</span><span>signal-fold</span> <span>v+</span> <span>(</span><span>vector2</span> <span>320</span> <span>240</span><span>)</span>
               <span>(</span><span>signal-map</span> <span>(</span><span>lambda </span><span>(</span><span>v</span><span>)</span>
                             <span>(</span><span>vscale</span> <span>v</span> <span>4</span><span>))</span>
                           <span>(</span><span>signal-sample</span> <span>game-agenda</span> <span>1</span> <span>key-arrows</span><span>))))</span>
</pre></div>
<p>In guile-2d, time-varying values are called "signals".  The above
signal describes a relationship between the arrow keys on the keyboard
and the position of the player.  <tt><span>signal-sample</span></tt> is used to trigger
a signal update upon every game tick that provides the current state
of the arrow keys.  <tt><span>key-arrows</span></tt> is a vector2 that maps to the
current state of the arrow keys, allowing for 8 direction movement.
This vector2 is then scaled 4x to make the player move faster.
Finally, the scaled vector is added to the previous player position
via <tt><span>signal-fold</span></tt>.  The player's position is at (320, 240)
initially.  As you can see, there are no callbacks and explicit
mutation needed.  Those details have been abstracted away, freeing the
programmer to focus on more important things.</p>
<p>I think it's helpful to see FRP in action to really appreciate the
magic.  So, check out this screencast!</p>
<p>To see all of the juicy implementation details, check out the <a href="https://gitorious.org/sly/sly/source/sly/signal.scm">git
repository</a>.  Thanks for following along!</p>]]></description>
										<content:encoded><![CDATA[<p>Last month, the <a class="reference external" href="http://gnu.org/s/guile">GNU Guile</a> project celebrated the 3rd anniversary of<br />
its 2.0 release with a hacker <a class="reference external" href="http://savannah.gnu.org/forum/forum.php?forum_id=7887">potluck</a>.  Guilers were encouraged to<br />
bring a tasty hack to the mailing list to share with everyone.  My<br />
dish was a simple <a class="reference external" href="https://en.wikipedia.org/wiki/Functional_reactive_programming">functional reactive programming</a> library.</p>
<p>Functional reactive programming (FRP) provides a way to describe<br />
time-varying values and their relationships using a functional and<br />
declarative programming style.  To understand what this means, let&#8217;s<br />
investigate a typical variable definition in Scheme.  The expression<br />
<tt class="docutils literal">(define c (+ a b))</tt> defines the variable <tt class="docutils literal">c</tt> to be the sum of<br />
variables <tt class="docutils literal">a</tt> and <tt class="docutils literal">b</tt> at the time of evaluation.  If <tt class="docutils literal">a</tt> or<br />
<tt class="docutils literal">b</tt> is assigned a new value, <tt class="docutils literal">c</tt> remains the same.  However, for<br />
applications that deal with state that transforms over time, it would<br />
be convenient if we could define <tt class="docutils literal">c</tt> to react to changes in <tt class="docutils literal">a</tt><br />
and <tt class="docutils literal">b</tt> by recomputing the sum.  Contrast this approach with the<br />
more traditional style of modeling dynamic state via events and<br />
callbacks.  A lot of programmers, myself included, have written code<br />
with so many callbacks that the resulting program is unmaintainable<br />
spaghetti code.  Callback hell is real, but if you accept FRP into<br />
your heart then you will be saved!</p>
<p>By now you&#8217;re probably wondering: &quot;What the hell does all this mean?&quot;<br />
So, here&#8217;s a real-world example of guile-2d&#8217;s FRP API:</p>
<div class="highlight">
<pre><span class="p">(</span><span class="nf">define-signal</span> <span class="nv">position</span>
  <span class="p">(</span><span class="nf">signal-fold</span> <span class="nv">v+</span> <span class="p">(</span><span class="nf">vector2</span> <span class="mi">320</span> <span class="mi">240</span><span class="p">)</span>
               <span class="p">(</span><span class="nf">signal-map</span> <span class="p">(</span><span class="k">lambda </span><span class="p">(</span><span class="nf">v</span><span class="p">)</span>
                             <span class="p">(</span><span class="nf">vscale</span> <span class="nv">v</span> <span class="mi">4</span><span class="p">))</span>
                           <span class="p">(</span><span class="nf">signal-sample</span> <span class="nv">game-agenda</span> <span class="mi">1</span> <span class="nv">key-arrows</span><span class="p">))))</span>
</pre>
</div>
<p>In guile-2d, time-varying values are called &quot;signals&quot;.  The above<br />
signal describes a relationship between the arrow keys on the keyboard<br />
and the position of the player.  <tt class="docutils literal"><span class="pre">signal-sample</span></tt> is used to trigger<br />
a signal update upon every game tick that provides the current state<br />
of the arrow keys.  <tt class="docutils literal"><span class="pre">key-arrows</span></tt> is a vector2 that maps to the<br />
current state of the arrow keys, allowing for 8 direction movement.<br />
This vector2 is then scaled 4x to make the player move faster.<br />
Finally, the scaled vector is added to the previous player position<br />
via <tt class="docutils literal"><span class="pre">signal-fold</span></tt>.  The player&#8217;s position is at (320, 240)<br />
initially.  As you can see, there are no callbacks and explicit<br />
mutation needed.  Those details have been abstracted away, freeing the<br />
programmer to focus on more important things.</p>
<p>I think it&#8217;s helpful to see FRP in action to really appreciate the<br />
magic.  So, check out this screencast!</p>
<p><video src="/videos/guile-2d-frp-demo.webm"
       style="width:640px;height:360px;" controls><br />
</video></p>
<p>To see all of the juicy implementation details, check out the <a class="reference external" href="https://gitorious.org/sly/sly/source/sly/signal.scm">git<br />
repository</a>.  Thanks for following along!</p>

<p class="syndicated-attribution"><em>From the blog <a href="http://dthompson.us/">dthompson</a> by <a href="https://cs.worcester.edu/author/0/" title="Read other posts by David Thompson">David Thompson</a></em> and used with permission of the author. All other rights reserved by the author.</p>]]></content:encoded>
					
		
		<enclosure url="" length="0" type="" />

		<post-id xmlns="com-wordpress:feed-additions:1">2890</post-id>	</item>
		<item>
		<title>A Cooperative REPL Server for Guile 2.0.10</title>
		<link>http://dthompson.us/a-cooperative-repl-server-for-guile-2010.html</link>
		
		<dc:creator><![CDATA[David Thompson]]></dc:creator>
		<pubDate>Sat, 25 Jan 2014 03:00:00 +0000</pubDate>
				<category><![CDATA[gnu]]></category>
		<category><![CDATA[guile]]></category>
		<category><![CDATA[scheme]]></category>
		<category><![CDATA[WSU]]></category>
		<guid isPermaLink="false">http://cs.worcester.edu/blog/?guid=23ca7c0d265fb2e743a7babc0242a634</guid>

					<description><![CDATA[<p>The next release of GNU Guile, 2.0.10, is to be released "real soon
now".  My contribution to this release is the new <tt>(system repl
<span>coop-server)</span></tt> module.  This module introduces a useful variant of the
REPL server that I've named the "cooperative" REPL server.  It is
cooperative because it can be integrated with single-threaded programs
without the thread synchronization issues present in the ordinary REPL
server.</p>
<p>Using delimited continuations and mvars (another new feature coming in
Guile 2.0.10), it was possible to create a REPL server whose clients
all ran in the context of a single thread.  The cooperative server
puts the user in control of when it is safe to evaluate expressions
entered at the REPL prompt.</p>
<p>Here's an example of how to use it:</p>
<div><pre><span>(</span><span>use-modules</span> <span>(</span><span>system</span> <span>repl</span> <span>coop-server</span><span>))</span>

<span>(</span><span>define </span><span>server</span> <span>(</span><span>spawn-coop-repl-server</span><span>))</span>

<span>(</span><span>while</span> <span>#t</span>
  <span>(</span><span>poll-coop-repl-server</span> <span>server</span><span>)</span>
  <span>(</span><span>sleep</span> <span>1</span><span>))</span>
</pre></div>
<p>That's all it takes.  There are only 2 public procedures!
<tt><span>spawn-coop-repl-server</span></tt> creates a new cooperative REPL server
object and starts listening for clients.  <tt><span>poll-coop-repl-server</span></tt>
applies pending operations for the server.</p>
<p>Now that I've explained the API, onto the implementation details!
Although the REPLs run in the context of a single thread, there are
other threads needed to make it all work.  To avoid thinking too much
about thread synchronization issues, I used the new <tt><span>(ice-9</span> mvars)</tt>
module to provide thread-safe objects for read/write operations.  I
used delimited continuations in order to yield control back to the
user from inside the loop.</p>
<p>When the server is spawned, a new thread is created to listen for
client connections.  When a client connects, a request to create a new
REPL is put into the server's "evaluation" mvar, the storage place for
pending server operations.  The job of <tt><span>poll-coop-repl-server</span></tt> is to
attempt to take from the evaluation mvar and execute the operation
stored within, if any.  In this case, an operation called <tt><span>new-repl</span></tt>
is hanging out along with the client socket.  The contents of the mvar
are removed, and a new REPL is started in the main thread.</p>
<p>This new REPL is run within a "prompt", Guile's implementation of
delimited continuations.  The prompt allows the REPL to be paused
temporarily while waiting for user input.  Just before the prompt is
aborted, a thunk containing the logic to read user input is stored
within the client's "read" mvar for yet another thread to use.
Without this additional thread and the use of a prompt, the main
thread would block while waiting for input, defeating the purpose of
the cooperative REPL.  The reader thread waits for this thunk to
appear in the read mvar.  When it appears, the thunk is applied and
the resulting expression is stored as an <tt>eval</tt> operation within the
evaluation mvar.  When <tt><span>poll-coop-repl-server</span></tt> is called, the REPL
prompt is resumed.  The input expression is evaluated in the context
of the main thread, the result is printed, and the process repeats
itself.</p>
<p>That's all, folks.  Thanks for following along.  I'm very excited to
use the cooperative REPL server in guile-2d and I hope that others
find it useful as well.  Many thanks to Mark Weaver for helping me out
when I got stuck and for all of the helpful code review.</p>]]></description>
										<content:encoded><![CDATA[<p>The next release of GNU Guile, 2.0.10, is to be released &quot;real soon<br />
now&quot;.  My contribution to this release is the new <tt class="docutils literal">(system repl<br />
<span class="pre">coop-server)</span></tt> module.  This module introduces a useful variant of the<br />
REPL server that I&#8217;ve named the &quot;cooperative&quot; REPL server.  It is<br />
cooperative because it can be integrated with single-threaded programs<br />
without the thread synchronization issues present in the ordinary REPL<br />
server.</p>
<p>Using delimited continuations and mvars (another new feature coming in<br />
Guile 2.0.10), it was possible to create a REPL server whose clients<br />
all ran in the context of a single thread.  The cooperative server<br />
puts the user in control of when it is safe to evaluate expressions<br />
entered at the REPL prompt.</p>
<p>Here&#8217;s an example of how to use it:</p>
<div class="highlight">
<pre><span class="p">(</span><span class="nf">use-modules</span> <span class="p">(</span><span class="nf">system</span> <span class="nv">repl</span> <span class="nv">coop-server</span><span class="p">))</span>

<span class="p">(</span><span class="k">define </span><span class="nv">server</span> <span class="p">(</span><span class="nf">spawn-coop-repl-server</span><span class="p">))</span>

<span class="p">(</span><span class="nf">while</span> <span class="no">#t</span>
  <span class="p">(</span><span class="nf">poll-coop-repl-server</span> <span class="nv">server</span><span class="p">)</span>
  <span class="p">(</span><span class="nf">sleep</span> <span class="mi">1</span><span class="p">))</span>
</pre>
</div>
<p>That&#8217;s all it takes.  There are only 2 public procedures!<br />
<tt class="docutils literal"><span class="pre">spawn-coop-repl-server</span></tt> creates a new cooperative REPL server<br />
object and starts listening for clients.  <tt class="docutils literal"><span class="pre">poll-coop-repl-server</span></tt><br />
applies pending operations for the server.</p>
<p>Now that I&#8217;ve explained the API, onto the implementation details!<br />
Although the REPLs run in the context of a single thread, there are<br />
other threads needed to make it all work.  To avoid thinking too much<br />
about thread synchronization issues, I used the new <tt class="docutils literal"><span class="pre">(ice-9</span> mvars)</tt><br />
module to provide thread-safe objects for read/write operations.  I<br />
used delimited continuations in order to yield control back to the<br />
user from inside the loop.</p>
<p>When the server is spawned, a new thread is created to listen for<br />
client connections.  When a client connects, a request to create a new<br />
REPL is put into the server&#8217;s &quot;evaluation&quot; mvar, the storage place for<br />
pending server operations.  The job of <tt class="docutils literal"><span class="pre">poll-coop-repl-server</span></tt> is to<br />
attempt to take from the evaluation mvar and execute the operation<br />
stored within, if any.  In this case, an operation called <tt class="docutils literal"><span class="pre">new-repl</span></tt><br />
is hanging out along with the client socket.  The contents of the mvar<br />
are removed, and a new REPL is started in the main thread.</p>
<p>This new REPL is run within a &quot;prompt&quot;, Guile&#8217;s implementation of<br />
delimited continuations.  The prompt allows the REPL to be paused<br />
temporarily while waiting for user input.  Just before the prompt is<br />
aborted, a thunk containing the logic to read user input is stored<br />
within the client&#8217;s &quot;read&quot; mvar for yet another thread to use.<br />
Without this additional thread and the use of a prompt, the main<br />
thread would block while waiting for input, defeating the purpose of<br />
the cooperative REPL.  The reader thread waits for this thunk to<br />
appear in the read mvar.  When it appears, the thunk is applied and<br />
the resulting expression is stored as an <tt class="docutils literal">eval</tt> operation within the<br />
evaluation mvar.  When <tt class="docutils literal"><span class="pre">poll-coop-repl-server</span></tt> is called, the REPL<br />
prompt is resumed.  The input expression is evaluated in the context<br />
of the main thread, the result is printed, and the process repeats<br />
itself.</p>
<p>That&#8217;s all, folks.  Thanks for following along.  I&#8217;m very excited to<br />
use the cooperative REPL server in guile-2d and I hope that others<br />
find it useful as well.  Many thanks to Mark Weaver for helping me out<br />
when I got stuck and for all of the helpful code review.</p>

<p class="syndicated-attribution"><em>From the blog <a href="http://dthompson.us/">dthompson</a> by <a href="https://cs.worcester.edu/author/0/" title="Read other posts by David Thompson">David Thompson</a></em> and used with permission of the author. All other rights reserved by the author.</p>]]></content:encoded>
					
		
		<enclosure url="" length="0" type="" />

		<post-id xmlns="com-wordpress:feed-additions:1">2806</post-id>	</item>
		<item>
		<title>First GNU Guile Patch and More Guix Packages</title>
		<link>http://dthompson.us/first-gnu-guile-patch-and-more-guix-packages.html</link>
		
		<dc:creator><![CDATA[David Thompson]]></dc:creator>
		<pubDate>Sat, 23 Nov 2013 02:00:00 +0000</pubDate>
				<category><![CDATA[gnu]]></category>
		<category><![CDATA[guile]]></category>
		<category><![CDATA[guix]]></category>
		<category><![CDATA[scheme]]></category>
		<category><![CDATA[WSU]]></category>
		<guid isPermaLink="false">http://cs.worcester.edu/blog/?guid=2577123a41e5bed615faac6966c502bd</guid>

					<description><![CDATA[<p>I have spent some of the last month working on contributing to GNU
Guile and now I can finally say that I have contributed code to the
project. Guile has several hash table implementations: a Guile native
one, SRFI-69, and R6RS. SRFI-69 contains a handy procedure,
<tt><span>alist-&#62;hash-table</span></tt>, which allows for a sort of hash literal-like
syntax:</p>
<div><pre><span>(</span><span>alist-&#62;hash-table</span>
 <span>'</span><span>((</span><span>foo</span> <span>.</span> <span>1</span><span>)</span>
   <span>(</span><span>bar</span> <span>.</span> <span>2</span><span>)</span>
   <span>(</span><span>baz</span> <span>.</span> <span>3</span><span>)))</span>
</pre></div>
<p>However, I prefer to use Guile's native hash implementation, and
SRFI-69 is incompatible with it, so I decided to port
<tt><span>alist-&#62;hash-table</span></tt>. Unfortunately, it was not as simple as writing
just one procedure. The native hash tables actually have 4 different
ways of doing key comparisons: Using <tt>equal?</tt>, <tt>eq?</tt>, <tt>eqv?</tt>,
and user-defined procedures. This is a design flaw because the user
must make sure to use the right procedures at all times rather than
simply set the <tt>hash</tt> and <tt>assoc</tt> procedures when creating the
hash table instance.</p>
<p>Below is the final implementation. Since 3 of the 4 variations were
essentially the same, I wrote a short macro to reduce code
duplication.</p>
<div><pre><span>;;;; Copyright (C) 2013 Free Software Foundation, Inc.</span>
<span>;;;;</span>
<span>;;;; This library is free software; you can redistribute it and/or</span>
<span>;;;; modify it under the terms of the GNU Lesser General Public</span>
<span>;;;; License as published by the Free Software Foundation; either</span>
<span>;;;; version 3 of the License, or (at your option) any later version.</span>
<span>;;;;</span>
<span>;;;; This library is distributed in the hope that it will be useful,</span>
<span>;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of</span>
<span>;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU</span>
<span>;;;; Lesser General Public License for more details.</span>
<span>;;;;</span>
<span>;;;; You should have received a copy of the GNU Lesser General Public</span>
<span>;;;; License along with this library; if not, write to the Free Software</span>
<span>;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA</span>
<span>;;;;</span>

<span>(</span><span>define-syntax-rule</span> <span>(</span><span>define-alist-converter</span> <span>name</span> <span>hash-set-proc</span><span>)</span>
  <span>(</span><span>define </span><span>(</span><span>name</span> <span>alist</span><span>)</span>
    <span>"Convert ALIST into a hash table."</span>
    <span>(</span><span>let </span><span>((</span><span>table</span> <span>(</span><span>make-hash-table</span><span>)))</span>
      <span>(</span><span>for-each </span><span>(</span><span>lambda </span><span>(</span><span>pair</span><span>)</span>
                  <span>(</span><span>hash-set-proc</span> <span>table</span> <span>(</span><span>car </span><span>pair</span><span>)</span> <span>(</span><span>cdr </span><span>pair</span><span>)))</span>
                <span>(</span><span>reverse </span><span>alist</span><span>))</span>
      <span>table</span><span>)))</span>

<span>(</span><span>define-alist-converter</span> <span>alist-&#62;hash-table</span> <span>hash-set!</span><span>)</span>
<span>(</span><span>define-alist-converter</span> <span>alist-&#62;hashq-table</span> <span>hashq-set!</span><span>)</span>
<span>(</span><span>define-alist-converter</span> <span>alist-&#62;hashv-table</span> <span>hashv-set!</span><span>)</span>

<span>(</span><span>define </span><span>(</span><span>alist-&#62;hashx-table</span> <span>hash</span> <span>assoc</span> <span>alist</span><span>)</span>
  <span>"Convert ALIST into a hash table with custom HASH and ASSOC</span>
<span>procedures."</span>
  <span>(</span><span>let </span><span>((</span><span>table</span> <span>(</span><span>make-hash-table</span><span>)))</span>
    <span>(</span><span>for-each </span><span>(</span><span>lambda </span><span>(</span><span>pair</span><span>)</span>
                <span>(</span><span>hashx-set!</span> <span>hash</span> <span>assoc</span> <span>table</span> <span>(</span><span>car </span><span>pair</span><span>)</span> <span>(</span><span>cdr </span><span>pair</span><span>)))</span>
              <span>(</span><span>reverse </span><span>alist</span><span>))</span>
    <span>table</span><span>))</span>
</pre></div>
<p>Not only did I manage to get my code into Guile, I was given commit
access to GNU Guix by the lead developer, Ludovic Court&#232;s. I have
never had commit access to any free software project repositories
besides my own. I feel quite honored, as cheesy as that may sound.</p>
<p>Packages for SDL and SDL2 have been merged into master, and packages
for SDL_gfx, SDL_image, SDL_mixer, SDL_net, and SDL_ttf for SDL 1.2
are pending review.</p>
<p>I like to show off the elegance of Guix package recipes, so here's
some code:</p>
<div><pre><span>;;; Copyright &#169; 2013 David Thompson &#60;dthompson2@worcester.edu&#62;</span>
<span>;;;</span>
<span>;;; This file is part of GNU Guix.</span>
<span>;;;</span>
<span>;;; GNU Guix is free software; you can redistribute it and/or modify it</span>
<span>;;; under the terms of the GNU General Public License as published by</span>
<span>;;; the Free Software Foundation; either version 3 of the License, or (at</span>
<span>;;; your option) any later version.</span>
<span>;;;</span>
<span>;;; GNU Guix is distributed in the hope that it will be useful, but</span>
<span>;;; WITHOUT ANY WARRANTY; without even the implied warranty of</span>
<span>;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span>
<span>;;; GNU General Public License for more details.</span>
<span>;;;</span>
<span>;;; You should have received a copy of the GNU General Public License</span>
<span>;;; along with GNU Guix.  If not, see &#60;http://www.gnu.org/licenses/&#62;.</span>

<span>(</span><span>define </span><span>sdl</span>
  <span>(</span><span>package</span>
    <span>(</span><span>name</span> <span>"sdl"</span><span>)</span>
    <span>(</span><span>version</span> <span>"1.2.15"</span><span>)</span>
    <span>(</span><span>source</span> <span>(</span><span>origin</span>
             <span>(</span><span>method</span> <span>url-fetch</span><span>)</span>
             <span>(</span><span>uri</span>
              <span>(</span><span>string-append </span><span>"http://libsdl.org/release/SDL-"</span>
                             <span>version</span> <span>".tar.gz"</span><span>))</span>
             <span>(</span><span>sha256</span>
              <span>(</span><span>base32</span>
               <span>"005d993xcac8236fpvd1iawkz4wqjybkpn8dbwaliqz5jfkidlyn"</span><span>))))</span>
    <span>(</span><span>build-system</span> <span>gnu-build-system</span><span>)</span>
    <span>(</span><span>arguments</span> <span>'</span><span>(</span><span>#</span><span>:tests?</span> <span>#f</span><span>))</span> <span>; no check target</span>
    <span>(</span><span>inputs</span> <span>`</span><span>((</span><span>"libx11"</span> <span>,</span><span>libx11</span><span>)</span>
              <span>(</span><span>"libxrandr"</span> <span>,</span><span>libxrandr</span><span>)</span>
              <span>(</span><span>"mesa"</span> <span>,</span><span>mesa</span><span>)</span>
              <span>(</span><span>"alsa-lib"</span> <span>,</span><span>alsa-lib</span><span>)</span>
              <span>(</span><span>"pkg-config"</span> <span>,</span><span>pkg-config</span><span>)</span>
              <span>(</span><span>"pulseaudio"</span> <span>,</span><span>pulseaudio</span><span>)))</span>
    <span>(</span><span>synopsis</span> <span>"Cross platform game development library"</span><span>)</span>
    <span>(</span><span>description</span> <span>"Simple DirectMedia Layer is a cross-platform development</span>
<span>library designed to provide low level access to audio, keyboard, mouse,</span>
<span>joystick, and graphics hardware."</span><span>)</span>
    <span>(</span><span>home-page</span> <span>"http://libsdl.org/"</span><span>)</span>
    <span>(</span><span>license</span> <span>lgpl2</span><span>.</span><span>1</span><span>)))</span>

<span>(</span><span>define </span><span>sdl2</span>
  <span>(</span><span>package</span> <span>(</span><span>inherit</span> <span>sdl</span><span>)</span>
    <span>(</span><span>name</span> <span>"sdl2"</span><span>)</span>
    <span>(</span><span>version</span> <span>"2.0.0"</span><span>)</span>
    <span>(</span><span>source</span> <span>(</span><span>origin</span>
             <span>(</span><span>method</span> <span>url-fetch</span><span>)</span>
             <span>(</span><span>uri</span>
              <span>(</span><span>string-append </span><span>"http://libsdl.org/release/SDL2-"</span>
                             <span>version</span> <span>".tar.gz"</span><span>))</span>
             <span>(</span><span>sha256</span>
              <span>(</span><span>base32</span>
               <span>"0y3in99brki7vc2mb4c0w39v70mf4h341mblhh8nmq4h7lawhskg"</span><span>))))</span>
    <span>(</span><span>license</span> <span>bsd-3</span><span>)))</span>
</pre></div>
<p>Much help is needed to package the GNU system for Guix. If you are
interested in helping, please drop by #guix on freenode, we are
friendly. :)</p>]]></description>
										<content:encoded><![CDATA[<p>I have spent some of the last month working on contributing to GNU<br />
Guile and now I can finally say that I have contributed code to the<br />
project. Guile has several hash table implementations: a Guile native<br />
one, SRFI-69, and R6RS. SRFI-69 contains a handy procedure,<br />
<tt class="docutils literal"><span class="pre">alist-&gt;hash-table</span></tt>, which allows for a sort of hash literal-like<br />
syntax:</p>
<div class="highlight">
<pre><span class="p">(</span><span class="nf">alist-&gt;hash-table</span>
 <span class="o">&#39;</span><span class="p">((</span><span class="nf">foo</span> <span class="o">.</span> <span class="mi">1</span><span class="p">)</span>
   <span class="p">(</span><span class="nf">bar</span> <span class="o">.</span> <span class="mi">2</span><span class="p">)</span>
   <span class="p">(</span><span class="nf">baz</span> <span class="o">.</span> <span class="mi">3</span><span class="p">)))</span>
</pre>
</div>
<p>However, I prefer to use Guile&#8217;s native hash implementation, and<br />
SRFI-69 is incompatible with it, so I decided to port<br />
<tt class="docutils literal"><span class="pre">alist-&gt;hash-table</span></tt>. Unfortunately, it was not as simple as writing<br />
just one procedure. The native hash tables actually have 4 different<br />
ways of doing key comparisons: Using <tt class="docutils literal">equal?</tt>, <tt class="docutils literal">eq?</tt>, <tt class="docutils literal">eqv?</tt>,<br />
and user-defined procedures. This is a design flaw because the user<br />
must make sure to use the right procedures at all times rather than<br />
simply set the <tt class="docutils literal">hash</tt> and <tt class="docutils literal">assoc</tt> procedures when creating the<br />
hash table instance.</p>
<p>Below is the final implementation. Since 3 of the 4 variations were<br />
essentially the same, I wrote a short macro to reduce code<br />
duplication.</p>
<div class="highlight">
<pre><span class="c1">;;;; Copyright (C) 2013 Free Software Foundation, Inc.</span>
<span class="c1">;;;;</span>
<span class="c1">;;;; This library is free software; you can redistribute it and/or</span>
<span class="c1">;;;; modify it under the terms of the GNU Lesser General Public</span>
<span class="c1">;;;; License as published by the Free Software Foundation; either</span>
<span class="c1">;;;; version 3 of the License, or (at your option) any later version.</span>
<span class="c1">;;;;</span>
<span class="c1">;;;; This library is distributed in the hope that it will be useful,</span>
<span class="c1">;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of</span>
<span class="c1">;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU</span>
<span class="c1">;;;; Lesser General Public License for more details.</span>
<span class="c1">;;;;</span>
<span class="c1">;;;; You should have received a copy of the GNU Lesser General Public</span>
<span class="c1">;;;; License along with this library; if not, write to the Free Software</span>
<span class="c1">;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA</span>
<span class="c1">;;;;</span>

<span class="p">(</span><span class="nf">define-syntax-rule</span> <span class="p">(</span><span class="nf">define-alist-converter</span> <span class="nv">name</span> <span class="nv">hash-set-proc</span><span class="p">)</span>
  <span class="p">(</span><span class="k">define </span><span class="p">(</span><span class="nf">name</span> <span class="nv">alist</span><span class="p">)</span>
    <span class="s">&quot;Convert ALIST into a hash table.&quot;</span>
    <span class="p">(</span><span class="k">let </span><span class="p">((</span><span class="nf">table</span> <span class="p">(</span><span class="nf">make-hash-table</span><span class="p">)))</span>
      <span class="p">(</span><span class="nb">for-each </span><span class="p">(</span><span class="k">lambda </span><span class="p">(</span><span class="nf">pair</span><span class="p">)</span>
                  <span class="p">(</span><span class="nf">hash-set-proc</span> <span class="nv">table</span> <span class="p">(</span><span class="nb">car </span><span class="nv">pair</span><span class="p">)</span> <span class="p">(</span><span class="nb">cdr </span><span class="nv">pair</span><span class="p">)))</span>
                <span class="p">(</span><span class="nb">reverse </span><span class="nv">alist</span><span class="p">))</span>
      <span class="nv">table</span><span class="p">)))</span>

<span class="p">(</span><span class="nf">define-alist-converter</span> <span class="nv">alist-&gt;hash-table</span> <span class="nv">hash-set!</span><span class="p">)</span>
<span class="p">(</span><span class="nf">define-alist-converter</span> <span class="nv">alist-&gt;hashq-table</span> <span class="nv">hashq-set!</span><span class="p">)</span>
<span class="p">(</span><span class="nf">define-alist-converter</span> <span class="nv">alist-&gt;hashv-table</span> <span class="nv">hashv-set!</span><span class="p">)</span>

<span class="p">(</span><span class="k">define </span><span class="p">(</span><span class="nf">alist-&gt;hashx-table</span> <span class="nv">hash</span> <span class="nv">assoc</span> <span class="nv">alist</span><span class="p">)</span>
  <span class="s">&quot;Convert ALIST into a hash table with custom HASH and ASSOC</span>
<span class="s">procedures.&quot;</span>
  <span class="p">(</span><span class="k">let </span><span class="p">((</span><span class="nf">table</span> <span class="p">(</span><span class="nf">make-hash-table</span><span class="p">)))</span>
    <span class="p">(</span><span class="nb">for-each </span><span class="p">(</span><span class="k">lambda </span><span class="p">(</span><span class="nf">pair</span><span class="p">)</span>
                <span class="p">(</span><span class="nf">hashx-set!</span> <span class="nv">hash</span> <span class="nv">assoc</span> <span class="nv">table</span> <span class="p">(</span><span class="nb">car </span><span class="nv">pair</span><span class="p">)</span> <span class="p">(</span><span class="nb">cdr </span><span class="nv">pair</span><span class="p">)))</span>
              <span class="p">(</span><span class="nb">reverse </span><span class="nv">alist</span><span class="p">))</span>
    <span class="nv">table</span><span class="p">))</span>
</pre>
</div>
<p>Not only did I manage to get my code into Guile, I was given commit<br />
access to GNU Guix by the lead developer, Ludovic Courtès. I have<br />
never had commit access to any free software project repositories<br />
besides my own. I feel quite honored, as cheesy as that may sound.</p>
<p>Packages for SDL and SDL2 have been merged into master, and packages<br />
for SDL_gfx, SDL_image, SDL_mixer, SDL_net, and SDL_ttf for SDL 1.2<br />
are pending review.</p>
<p>I like to show off the elegance of Guix package recipes, so here&#8217;s<br />
some code:</p>
<div class="highlight">
<pre><span class="c1">;;; Copyright © 2013 David Thompson &lt;dthompson2@worcester.edu&gt;</span>
<span class="c1">;;;</span>
<span class="c1">;;; This file is part of GNU Guix.</span>
<span class="c1">;;;</span>
<span class="c1">;;; GNU Guix is free software; you can redistribute it and/or modify it</span>
<span class="c1">;;; under the terms of the GNU General Public License as published by</span>
<span class="c1">;;; the Free Software Foundation; either version 3 of the License, or (at</span>
<span class="c1">;;; your option) any later version.</span>
<span class="c1">;;;</span>
<span class="c1">;;; GNU Guix is distributed in the hope that it will be useful, but</span>
<span class="c1">;;; WITHOUT ANY WARRANTY; without even the implied warranty of</span>
<span class="c1">;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span>
<span class="c1">;;; GNU General Public License for more details.</span>
<span class="c1">;;;</span>
<span class="c1">;;; You should have received a copy of the GNU General Public License</span>
<span class="c1">;;; along with GNU Guix.  If not, see &lt;http://www.gnu.org/licenses/&gt;.</span>

<span class="p">(</span><span class="k">define </span><span class="nv">sdl</span>
  <span class="p">(</span><span class="nf">package</span>
    <span class="p">(</span><span class="nf">name</span> <span class="s">&quot;sdl&quot;</span><span class="p">)</span>
    <span class="p">(</span><span class="nf">version</span> <span class="s">&quot;1.2.15&quot;</span><span class="p">)</span>
    <span class="p">(</span><span class="nf">source</span> <span class="p">(</span><span class="nf">origin</span>
             <span class="p">(</span><span class="nf">method</span> <span class="nv">url-fetch</span><span class="p">)</span>
             <span class="p">(</span><span class="nf">uri</span>
              <span class="p">(</span><span class="nb">string-append </span><span class="s">&quot;http://libsdl.org/release/SDL-&quot;</span>
                             <span class="nv">version</span> <span class="s">&quot;.tar.gz&quot;</span><span class="p">))</span>
             <span class="p">(</span><span class="nf">sha256</span>
              <span class="p">(</span><span class="nf">base32</span>
               <span class="s">&quot;005d993xcac8236fpvd1iawkz4wqjybkpn8dbwaliqz5jfkidlyn&quot;</span><span class="p">))))</span>
    <span class="p">(</span><span class="nf">build-system</span> <span class="nv">gnu-build-system</span><span class="p">)</span>
    <span class="p">(</span><span class="nf">arguments</span> <span class="o">&#39;</span><span class="p">(</span><span class="o">#</span><span class="nv">:tests?</span> <span class="no">#f</span><span class="p">))</span> <span class="c1">; no check target</span>
    <span class="p">(</span><span class="nf">inputs</span> <span class="o">`</span><span class="p">((</span><span class="s">&quot;libx11&quot;</span> <span class="o">,</span><span class="nv">libx11</span><span class="p">)</span>
              <span class="p">(</span><span class="s">&quot;libxrandr&quot;</span> <span class="o">,</span><span class="nv">libxrandr</span><span class="p">)</span>
              <span class="p">(</span><span class="s">&quot;mesa&quot;</span> <span class="o">,</span><span class="nv">mesa</span><span class="p">)</span>
              <span class="p">(</span><span class="s">&quot;alsa-lib&quot;</span> <span class="o">,</span><span class="nv">alsa-lib</span><span class="p">)</span>
              <span class="p">(</span><span class="s">&quot;pkg-config&quot;</span> <span class="o">,</span><span class="nv">pkg-config</span><span class="p">)</span>
              <span class="p">(</span><span class="s">&quot;pulseaudio&quot;</span> <span class="o">,</span><span class="nv">pulseaudio</span><span class="p">)))</span>
    <span class="p">(</span><span class="nf">synopsis</span> <span class="s">&quot;Cross platform game development library&quot;</span><span class="p">)</span>
    <span class="p">(</span><span class="nf">description</span> <span class="s">&quot;Simple DirectMedia Layer is a cross-platform development</span>
<span class="s">library designed to provide low level access to audio, keyboard, mouse,</span>
<span class="s">joystick, and graphics hardware.&quot;</span><span class="p">)</span>
    <span class="p">(</span><span class="nf">home-page</span> <span class="s">&quot;http://libsdl.org/&quot;</span><span class="p">)</span>
    <span class="p">(</span><span class="nf">license</span> <span class="nv">lgpl2</span><span class="o">.</span><span class="mi">1</span><span class="p">)))</span>

<span class="p">(</span><span class="k">define </span><span class="nv">sdl2</span>
  <span class="p">(</span><span class="nf">package</span> <span class="p">(</span><span class="nf">inherit</span> <span class="nv">sdl</span><span class="p">)</span>
    <span class="p">(</span><span class="nf">name</span> <span class="s">&quot;sdl2&quot;</span><span class="p">)</span>
    <span class="p">(</span><span class="nf">version</span> <span class="s">&quot;2.0.0&quot;</span><span class="p">)</span>
    <span class="p">(</span><span class="nf">source</span> <span class="p">(</span><span class="nf">origin</span>
             <span class="p">(</span><span class="nf">method</span> <span class="nv">url-fetch</span><span class="p">)</span>
             <span class="p">(</span><span class="nf">uri</span>
              <span class="p">(</span><span class="nb">string-append </span><span class="s">&quot;http://libsdl.org/release/SDL2-&quot;</span>
                             <span class="nv">version</span> <span class="s">&quot;.tar.gz&quot;</span><span class="p">))</span>
             <span class="p">(</span><span class="nf">sha256</span>
              <span class="p">(</span><span class="nf">base32</span>
               <span class="s">&quot;0y3in99brki7vc2mb4c0w39v70mf4h341mblhh8nmq4h7lawhskg&quot;</span><span class="p">))))</span>
    <span class="p">(</span><span class="nf">license</span> <span class="nv">bsd-3</span><span class="p">)))</span>
</pre>
</div>
<p>Much help is needed to package the GNU system for Guix. If you are<br />
interested in helping, please drop by #guix on freenode, we are<br />
friendly. <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>

<p class="syndicated-attribution"><em>From the blog <a href="http://dthompson.us/">dthompson</a> by <a href="https://cs.worcester.edu/author/0/" title="Read other posts by David Thompson">David Thompson</a></em> and used with permission of the author. All other rights reserved by the author.</p>]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2709</post-id>	</item>
	</channel>
</rss>
