aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Faulhaber <git_net@infolace.com>2010-05-28 09:07:25 -0700
committerTom Faulhaber <git_net@infolace.com>2010-05-28 09:07:25 -0700
commit7a8e827f2e15566dcdf72e01bebfb28360adeea4 (patch)
tree65c91b75720038cc7115cfe1c3263d687954cc88
parenta045b1aa22355285b899b698af58263cb6d3040c (diff)
Autodoc commit for master/4fe738db, 1.1.x/d132c5f1
-rw-r--r--branch-1.1.x/datalog-api.html6
-rw-r--r--branch-1.1.x/doc/datalog.html221
-rw-r--r--branch-1.1.x/doc/pprint/CommonLispFormat.html302
-rw-r--r--branch-1.1.x/doc/pprint/PrettyPrinting.html359
-rw-r--r--branch-1.1.x/io-api.html482
-rw-r--r--branch-1.1.x/pprint-api.html8
-rw-r--r--branch-1.1.x/seq-api.html315
-rw-r--r--datalog-api.html6
-rw-r--r--doc/datalog.html10
-rw-r--r--doc/pprint/CommonLispFormat.html10
-rw-r--r--doc/pprint/PrettyPrinting.html10
-rw-r--r--duck-streams-api.html40
-rw-r--r--generic.comparison-api.html20
-rw-r--r--io-api.html52
-rw-r--r--pprint-api.html8
15 files changed, 986 insertions, 863 deletions
diff --git a/branch-1.1.x/datalog-api.html b/branch-1.1.x/datalog-api.html
index 98af1f08..9caf0d22 100644
--- a/branch-1.1.x/datalog-api.html
+++ b/branch-1.1.x/datalog-api.html
@@ -237,7 +237,11 @@ by <span id="author">Jeffrey Straszheim</span><br />
<br />
-<h2>Public Variables and Functions</h2>
+<span id="external-doc">Related documentation:
+ <span id="external-doc-link">
+ <br /><a href="doc/datalog.html">An Overview of Datalog</a>
+ <br /></span><br />
+</span><h2>Public Variables and Functions</h2>
<div id="var-entry">
<br />
<hr />
diff --git a/branch-1.1.x/doc/datalog.html b/branch-1.1.x/doc/datalog.html
new file mode 100644
index 00000000..52593d54
--- /dev/null
+++ b/branch-1.1.x/doc/datalog.html
@@ -0,0 +1,221 @@
+<html>
+ <head>
+ <title>An Overview of Datalog</title>
+ <link href="../../static/favicon.png" rel="icon" />
+ <link href="../../static/favicon.png" rel="shortcut icon" />
+ <link media="all" type="text/css" href="../../static/clojure.css" rel="stylesheet" />
+ <link media="all" type="text/css" href="../../static/wiki.css" rel="stylesheet" />
+ <link media="all" type="text/css" href="../../static/internal.css" rel="stylesheet" />
+ <!-- TODO: are we using these (from clojure.org)? If so, add the files -->
+ <script src="file/view/code_highlighter.js" type="text/javascript"></script>
+ <script src="file/view/clojure.js" type="text/javascript"></script>
+ <style>.menuWrapper{height: 36px;}</style>
+ <!--[if lte IE 6]>
+ <link rel="stylesheet" href="http://www.wikispaces.com/_/2009051601/s/internal_ie.css" type="text/css" />
+ <![endif]-->
+ </head>
+<!--
+This document was auto-generated from the source by the clojure autodoc system.
+To report errors or ask questions about the overall documentation structure, formatting,
+etc., contact Tom Faulhaber (google mail name: tomfaulhaber).
+For errors in the documentation of a particular namespace, contact the author of that
+namespace.
+-->
+ <body>
+ <div id="AllContentContainer">
+ <div id="Header">
+ <a id="Logo" href="index.html"><img alt="Clojure" height="100" width="100" src="../../static/clojure-icon.gif" /></a>
+ <h1><a title="page header title" id="page-header" href="index.html">Clojure-contrib API Reference</a></h1>
+ </div>
+ <div id="leftcolumn"><div style="text-align: center;"></div>
+<div class="menu">
+ <div class="WikiCustomNav WikiElement wiki">
+ <div class="BranchTOC">
+ <a class="wiki_link" href="#">Branches</a>
+ <ul id="left-sidebar-branch-list">
+ <li><a href="../index.html" class="wiki_link">master</a></li><li><a href="../branch-1.1.x/index.html" class="wiki_link">1.1.x</a></li>
+ </ul>
+ </div>
+ <a class="wiki_link" href="index.html">Overview</a><br />
+ <a class="wiki_link" href="api-index.html">API Index</a><br />
+ <a class="wiki_link" href="#">Namespaces:</a>
+ <ul id="left-sidebar-list">
+ <li><a href="accumulators-api.html" class="wiki_link">accumulators</a></li><li><a href="agent-utils-api.html" class="wiki_link">agent-utils</a></li><li><a href="apply-macro-api.html" class="wiki_link">apply-macro</a></li><li><a href="base64-api.html" class="wiki_link">base64</a></li><li><a href="classpath-api.html" class="wiki_link">classpath</a></li><li><a href="combinatorics-api.html" class="wiki_link">combinatorics</a></li><li><a href="command-line-api.html" class="wiki_link">command-line</a></li><li><a href="complex-numbers-api.html" class="wiki_link">complex-numbers</a></li><li><a href="cond-api.html" class="wiki_link">cond</a></li><li><a href="condition-api.html" class="wiki_link">condition</a></li><li><a href="core-api.html" class="wiki_link">core</a></li><li><a href="dataflow-api.html" class="wiki_link">dataflow</a></li><li><a href="datalog-api.html" class="wiki_link">datalog</a></li><li><a href="def-api.html" class="wiki_link">def</a></li><li><a href="duck-streams-api.html" class="wiki_link">duck-streams</a></li><li><a href="error-kit-api.html" class="wiki_link">error-kit</a></li><li><a href="except-api.html" class="wiki_link">except</a></li><li><a href="fcase-api.html" class="wiki_link">fcase</a></li><li><a href="find-namespaces-api.html" class="wiki_link">find-namespaces</a></li><li><a href="fnmap-api.html" class="wiki_link">fnmap</a></li><li><a href="gen-html-docs-api.html" class="wiki_link">gen-html-docs</a></li><li><a href="generic.arithmetic-api.html" class="wiki_link">generic.arithmetic</a></li><li><a href="generic.collection-api.html" class="wiki_link">generic.collection</a></li><li><a href="generic.comparison-api.html" class="wiki_link">generic.comparison</a></li><li><a href="generic.functor-api.html" class="wiki_link">generic.functor</a></li><li><a href="generic.math-functions-api.html" class="wiki_link">generic.math-functions</a></li><li><a href="graph-api.html" class="wiki_link">graph</a></li><li><a href="greatest-least-api.html" class="wiki_link">greatest-least</a></li><li><a href="http.agent-api.html" class="wiki_link">http.agent</a></li><li><a href="http.connection-api.html" class="wiki_link">http.connection</a></li><li><a href="import-static-api.html" class="wiki_link">import-static</a></li><li><a href="jar-api.html" class="wiki_link">jar</a></li><li><a href="java-utils-api.html" class="wiki_link">java-utils</a></li><li><a href="javadoc.browse-api.html" class="wiki_link">javadoc.browse</a></li><li><a href="jmx-api.html" class="wiki_link">jmx</a></li><li><a href="json.read-api.html" class="wiki_link">json.read</a></li><li><a href="json.write-api.html" class="wiki_link">json.write</a></li><li><a href="lazy-seqs-api.html" class="wiki_link">lazy-seqs</a></li><li><a href="lazy-xml-api.html" class="wiki_link">lazy-xml</a></li><li><a href="logging-api.html" class="wiki_link">logging</a></li><li><a href="macro-utils-api.html" class="wiki_link">macro-utils</a></li><li><a href="macros-api.html" class="wiki_link">macros</a></li><li><a href="map-utils-api.html" class="wiki_link">map-utils</a></li><li><a href="math-api.html" class="wiki_link">math</a></li><li><a href="miglayout-api.html" class="wiki_link">miglayout</a></li><li><a href="mmap-api.html" class="wiki_link">mmap</a></li><li><a href="mock-api.html" class="wiki_link">mock</a></li><li><a href="monadic-io-streams-api.html" class="wiki_link">monadic-io-streams</a></li><li><a href="monads-api.html" class="wiki_link">monads</a></li><li><a href="ns-utils-api.html" class="wiki_link">ns-utils</a></li><li><a href="pprint-api.html" class="wiki_link">pprint</a></li><li><a href="probabilities.finite-distributions-api.html" class="wiki_link">probabilities.finite-distributions</a></li><li><a href="probabilities.monte-carlo-api.html" class="wiki_link">probabilities.monte-carlo</a></li><li><a href="probabilities.random-numbers-api.html" class="wiki_link">probabilities.random-numbers</a></li><li><a href="profile-api.html" class="wiki_link">profile</a></li><li><a href="prxml-api.html" class="wiki_link">prxml</a></li><li><a href="repl-ln-api.html" class="wiki_link">repl-ln</a></li><li><a href="repl-utils-api.html" class="wiki_link">repl-utils</a></li><li><a href="seq-utils-api.html" class="wiki_link">seq-utils</a></li><li><a href="server-socket-api.html" class="wiki_link">server-socket</a></li><li><a href="set-api.html" class="wiki_link">set</a></li><li><a href="shell-out-api.html" class="wiki_link">shell-out</a></li><li><a href="singleton-api.html" class="wiki_link">singleton</a></li><li><a href="sql-api.html" class="wiki_link">sql</a></li><li><a href="str-utils-api.html" class="wiki_link">str-utils</a></li><li><a href="str-utils2-api.html" class="wiki_link">str-utils2</a></li><li><a href="stream-utils-api.html" class="wiki_link">stream-utils</a></li><li><a href="swing-utils-api.html" class="wiki_link">swing-utils</a></li><li><a href="test-is-api.html" class="wiki_link">test-is</a></li><li><a href="trace-api.html" class="wiki_link">trace</a></li><li><a href="types-api.html" class="wiki_link">types</a></li><li><a href="with-ns-api.html" class="wiki_link">with-ns</a></li><li><a href="zip-filter-api.html" class="wiki_link">zip-filter</a></li>
+ </ul>
+ </div>
+</div>
+</div>
+ <div id="rightcolumn">
+ <div id="Content">
+ <div class="contentBox"><div class="innerContentBox">
+ <div id="content_view" class="wiki wikiPage">
+ <div id="right-sidebar"></div>
+ <div id="content-tag"><html><body><h1>An Overview of Datalog</h1>
+
+<p>By Jeffrey Straszheim</p>
+
+<p><em>What Datalog is, and what it can do for you.</em></p>
+
+<p><em>Work in Progress</em></p>
+
+<h2>Introduction</h2>
+
+<p>Datalog is a logical query language. It exists somewhere between relational algebra (the formal theory behind SQL) and Prolog, but is closer in motivation to the former than the later. It was invented to apply some of the principles of logic programming to database theory. Its primary addition to the semantics of databases is <em>recursive</em> queries. Examples will be provided below.</p>
+
+<p>The implementation of Datalog that is provided (in this library) departs a bit from the original model insofar as it supports <em>in memory</em> data structures only. It is intended to give developers tools to use relational modeling for their data. A good overview of why you would want to do this is Ben Mosely's <em>Functional Relational Programming</em> material, found here: <a href="http://web.mac.com/ben_moseley/frp/frp.html">http://web.mac.com/ben_moseley/frp/frp.html</a>.</p>
+
+<h2>Details</h2>
+
+<h3>The Database</h3>
+
+<p>Clojure Datalog supports an in memory relational database format, implemented in clojure.contrib.datalog.database (<a href="http://github.com/richhickey/clojure-contrib/blob/master/src/clojure/contrib/datalog/database.clj">here</a>). It supports relations (tables) with named columns and simple hash based indexes. At the present time it does not support any integrity constraints (perhaps later).</p>
+
+<p>Tables are built with <code>make-database</code>, like this:</p>
+
+<pre><code>(make-database
+ (relation :employee [:id :name :position])
+ (index :employee :name)
+
+ (relation :boss [:employee-id :boss-id])
+ (index :boss :employee-id)
+
+ (relation :can-do-job [:position :job])
+ (index :can-do-job :position)
+
+ (relation :job-replacement [:job :can-be-done-by])
+
+ (relation :job-exceptions [:id :job]))
+</code></pre>
+
+<p>The schema can be modified by <code>add-relation</code> and <code>add-index</code>. Under the hood, it is standard Clojure map from relation name to relation, and can be directly modified if needed.</p>
+
+<p>Data is added like this:</p>
+
+<pre><code>(add-tuples db-base
+ [:employee :id 1 :name "Bob" :position :boss]
+ [:employee :id 2 :name "Mary" :position :chief-accountant]
+ [:employee :id 3 :name "John" :position :accountant]
+ [:employee :id 4 :name "Sameer" :position :chief-programmer]
+ [:employee :id 5 :name "Lilian" :position :programmer]
+ [:employee :id 6 :name "Li" :position :technician]
+ [:employee :id 7 :name "Fred" :position :sales]
+ [:employee :id 8 :name "Brenda" :position :sales]
+ [:employee :id 9 :name "Miki" :position :project-management]
+ [:employee :id 10 :name "Albert" :position :technician]
+
+ [:boss :employee-id 2 :boss-id 1]
+ [:boss :employee-id 3 :boss-id 2]
+ [:boss :employee-id 4 :boss-id 1]
+ [:boss :employee-id 5 :boss-id 4]
+ [:boss :employee-id 6 :boss-id 4]
+ [:boss :employee-id 7 :boss-id 1]
+ [:boss :employee-id 8 :boss-id 7]
+ [:boss :employee-id 9 :boss-id 1]
+ [:boss :employee-id 10 :boss-id 6]
+
+ [:can-do-job :position :boss :job :management]
+ [:can-do-job :position :accountant :job :accounting]
+ [:can-do-job :position :chief-accountant :job :accounting]
+ [:can-do-job :position :programmer :job :programming]
+ [:can-do-job :position :chief-programmer :job :programming]
+ [:can-do-job :position :technician :job :server-support]
+ [:can-do-job :position :sales :job :sales]
+ [:can-do-job :position :project-management :job :project-management]
+
+ [:job-replacement :job :pc-support :can-be-done-by :server-support]
+ [:job-replacement :job :pc-support :can-be-done-by :programming]
+ [:job-replacement :job :payroll :can-be-done-by :accounting]
+
+ [:job-exceptions :id 4 :job :pc-support])
+</code></pre>
+
+<p>The meaning is, I believe, obvious.</p>
+
+<p>Functions that add/remove individual tuples are also provided. Use the source.</p>
+
+<h3>Rules</h3>
+
+<p>In addition to the database itself, Datalog lets you define a series of <em>inference rules</em> to apply to your data. Rules look like this:</p>
+
+<pre><code>(&lt;- (:works-for :employee ?x :boss ?y) (:boss :employee-id ?e-id :boss-id ?b-id)
+ (:employee :id ?e-id :name ?x)
+ (:employee :id ?b-id :name ?y))
+</code></pre>
+
+<p>The <code>&lt;-</code> operator represents implication. The first form is the head of the rule, the remainder the body. The meaning is that the head is true if each member of the body is true. We can read this above rule as:</p>
+
+<ul>
+<li>An employee (?x) works for a boss (?y) if: in the :boss relation there is an employee id (?e-id) matched to a boss id (?b-id) <em>and</em> in the :employee relation that (?e-id) matches the name (?x) <em>and also</em> in the :employee relation the id (?b-id) matches the name (?y).</li>
+</ul>
+
+<p>Notice two things: Logic variables are prefixed by a '?', and the meaning of those variables in a rule can join together entities.</p>
+
+<p>That same rule might be expressed in SQL as:</p>
+
+<pre><code>select e.name, b.name
+ from employee as e, employee as b, boss
+ where e.id = boss.employee-id and b.id = boss.boss-id
+</code></pre>
+
+<p>However, unlike SQL, Datalog rules can be recursive. Like this:</p>
+
+<pre><code>(&lt;- (:works-for :employee ?x :boss ?y) (:works-for :employee ?x :boss ?z)
+ (:works-for :employee ?z :boss ?y))
+</code></pre>
+
+<p>If you combine these two rules, this builds a <em>transitive closure</em> of the works-for relation. It will return not only ?x's direct boss, but the boss of his boss, and so on. This cannot be done in most forms of SQL.</p>
+
+<h4>Negation and Conditionals</h4>
+
+<p><em>Todo</em></p>
+
+<h3>Queries</h3>
+
+<p>A query is how you request information from a set of rules and a database. Queries look like this:</p>
+
+<pre><code>(?- :works-for :employee ??name :boss ?y)
+</code></pre>
+
+<p>Notice the double '?'!</p>
+
+<p>This asks for the name and boss columns from the works-for relation, which was defined by the two rules above. The double ?? allow you to parameterize your query.</p>
+
+<h3>Work Plans</h3>
+
+<p>A set of work rules and a query can form a work plan. It is done like this:</p>
+
+<pre><code>(build-work-plan rules (?- :works-for :employee '??name :boss ?x))
+</code></pre>
+
+<p>This takes a set of rules and a query, and performs some basic filtering an optimization. it is a fairly expensive operation, so try to build the plans you need once in your program, or perhaps cache them somehow.</p>
+
+<p>In SQL, a work plan is similar to a prepared statement.</p>
+
+<h3>Running your Work Plan</h3>
+
+<p>You run a work plan like this:</p>
+
+<pre><code>(run-work-plan wp db {'??name "Albert"})
+</code></pre>
+
+<p>Where wp is the result of (build-work-plan ...) and db is a database. The last argument is a map of bindings. It provides the specific values for any ??X forms in your query. Given the rules and query defined above, it should return a sequence of tuples of all the people that "Albert" works for.</p>
+
+<h3>Examples</h3>
+
+<p>A completed example is provided at <a href="http://github.com/richhickey/clojure-contrib/blob/master/src/clojure/contrib/datalog/example.clj">http://github.com/richhickey/clojure-contrib/blob/master/src/clojure/contrib/datalog/example.clj</a>.</p>
+</body></html></div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div id="foot">
+ <div style="text-align: center;" id="copyright">Copyright 2007-2009 by Rich Hickey and the various contributors</div>
+ </div>
+ </div>
+ <div id="DesignedBy">Logo &amp; site design by <a title="Visit Tom Hickey's website." href="http://www.tomhickey.com">Tom Hickey</a>.<br />
+ Clojure auto-documentation system by Tom Faulhaber.</div>
+ </div>
+ <!-- /AllContentContainer -->
+ </body>
+
+</html> \ No newline at end of file
diff --git a/branch-1.1.x/doc/pprint/CommonLispFormat.html b/branch-1.1.x/doc/pprint/CommonLispFormat.html
new file mode 100644
index 00000000..315f76db
--- /dev/null
+++ b/branch-1.1.x/doc/pprint/CommonLispFormat.html
@@ -0,0 +1,302 @@
+<html>
+ <head>
+ <title>A Common Lisp-compatible Format Function</title>
+ <link href="../../../static/favicon.png" rel="icon" />
+ <link href="../../../static/favicon.png" rel="shortcut icon" />
+ <link media="all" type="text/css" href="../../../static/clojure.css" rel="stylesheet" />
+ <link media="all" type="text/css" href="../../../static/wiki.css" rel="stylesheet" />
+ <link media="all" type="text/css" href="../../../static/internal.css" rel="stylesheet" />
+ <!-- TODO: are we using these (from clojure.org)? If so, add the files -->
+ <script src="file/view/code_highlighter.js" type="text/javascript"></script>
+ <script src="file/view/clojure.js" type="text/javascript"></script>
+ <style>.menuWrapper{height: 36px;}</style>
+ <!--[if lte IE 6]>
+ <link rel="stylesheet" href="http://www.wikispaces.com/_/2009051601/s/internal_ie.css" type="text/css" />
+ <![endif]-->
+ </head>
+<!--
+This document was auto-generated from the source by the clojure autodoc system.
+To report errors or ask questions about the overall documentation structure, formatting,
+etc., contact Tom Faulhaber (google mail name: tomfaulhaber).
+For errors in the documentation of a particular namespace, contact the author of that
+namespace.
+-->
+ <body>
+ <div id="AllContentContainer">
+ <div id="Header">
+ <a id="Logo" href="index.html"><img alt="Clojure" height="100" width="100" src="../../../static/clojure-icon.gif" /></a>
+ <h1><a title="page header title" id="page-header" href="index.html">Clojure-contrib API Reference</a></h1>
+ </div>
+ <div id="leftcolumn"><div style="text-align: center;"></div>
+<div class="menu">
+ <div class="WikiCustomNav WikiElement wiki">
+ <div class="BranchTOC">
+ <a class="wiki_link" href="#">Branches</a>
+ <ul id="left-sidebar-branch-list">
+ <li><a href="../index.html" class="wiki_link">master</a></li><li><a href="../branch-1.1.x/index.html" class="wiki_link">1.1.x</a></li>
+ </ul>
+ </div>
+ <a class="wiki_link" href="index.html">Overview</a><br />
+ <a class="wiki_link" href="api-index.html">API Index</a><br />
+ <a class="wiki_link" href="#">Namespaces:</a>
+ <ul id="left-sidebar-list">
+ <li><a href="accumulators-api.html" class="wiki_link">accumulators</a></li><li><a href="agent-utils-api.html" class="wiki_link">agent-utils</a></li><li><a href="apply-macro-api.html" class="wiki_link">apply-macro</a></li><li><a href="base64-api.html" class="wiki_link">base64</a></li><li><a href="classpath-api.html" class="wiki_link">classpath</a></li><li><a href="combinatorics-api.html" class="wiki_link">combinatorics</a></li><li><a href="command-line-api.html" class="wiki_link">command-line</a></li><li><a href="complex-numbers-api.html" class="wiki_link">complex-numbers</a></li><li><a href="cond-api.html" class="wiki_link">cond</a></li><li><a href="condition-api.html" class="wiki_link">condition</a></li><li><a href="core-api.html" class="wiki_link">core</a></li><li><a href="dataflow-api.html" class="wiki_link">dataflow</a></li><li><a href="datalog-api.html" class="wiki_link">datalog</a></li><li><a href="def-api.html" class="wiki_link">def</a></li><li><a href="duck-streams-api.html" class="wiki_link">duck-streams</a></li><li><a href="error-kit-api.html" class="wiki_link">error-kit</a></li><li><a href="except-api.html" class="wiki_link">except</a></li><li><a href="fcase-api.html" class="wiki_link">fcase</a></li><li><a href="find-namespaces-api.html" class="wiki_link">find-namespaces</a></li><li><a href="fnmap-api.html" class="wiki_link">fnmap</a></li><li><a href="gen-html-docs-api.html" class="wiki_link">gen-html-docs</a></li><li><a href="generic.arithmetic-api.html" class="wiki_link">generic.arithmetic</a></li><li><a href="generic.collection-api.html" class="wiki_link">generic.collection</a></li><li><a href="generic.comparison-api.html" class="wiki_link">generic.comparison</a></li><li><a href="generic.functor-api.html" class="wiki_link">generic.functor</a></li><li><a href="generic.math-functions-api.html" class="wiki_link">generic.math-functions</a></li><li><a href="graph-api.html" class="wiki_link">graph</a></li><li><a href="greatest-least-api.html" class="wiki_link">greatest-least</a></li><li><a href="http.agent-api.html" class="wiki_link">http.agent</a></li><li><a href="http.connection-api.html" class="wiki_link">http.connection</a></li><li><a href="import-static-api.html" class="wiki_link">import-static</a></li><li><a href="jar-api.html" class="wiki_link">jar</a></li><li><a href="java-utils-api.html" class="wiki_link">java-utils</a></li><li><a href="javadoc.browse-api.html" class="wiki_link">javadoc.browse</a></li><li><a href="jmx-api.html" class="wiki_link">jmx</a></li><li><a href="json.read-api.html" class="wiki_link">json.read</a></li><li><a href="json.write-api.html" class="wiki_link">json.write</a></li><li><a href="lazy-seqs-api.html" class="wiki_link">lazy-seqs</a></li><li><a href="lazy-xml-api.html" class="wiki_link">lazy-xml</a></li><li><a href="logging-api.html" class="wiki_link">logging</a></li><li><a href="macro-utils-api.html" class="wiki_link">macro-utils</a></li><li><a href="macros-api.html" class="wiki_link">macros</a></li><li><a href="map-utils-api.html" class="wiki_link">map-utils</a></li><li><a href="math-api.html" class="wiki_link">math</a></li><li><a href="miglayout-api.html" class="wiki_link">miglayout</a></li><li><a href="mmap-api.html" class="wiki_link">mmap</a></li><li><a href="mock-api.html" class="wiki_link">mock</a></li><li><a href="monadic-io-streams-api.html" class="wiki_link">monadic-io-streams</a></li><li><a href="monads-api.html" class="wiki_link">monads</a></li><li><a href="ns-utils-api.html" class="wiki_link">ns-utils</a></li><li><a href="pprint-api.html" class="wiki_link">pprint</a></li><li><a href="probabilities.finite-distributions-api.html" class="wiki_link">probabilities.finite-distributions</a></li><li><a href="probabilities.monte-carlo-api.html" class="wiki_link">probabilities.monte-carlo</a></li><li><a href="probabilities.random-numbers-api.html" class="wiki_link">probabilities.random-numbers</a></li><li><a href="profile-api.html" class="wiki_link">profile</a></li><li><a href="prxml-api.html" class="wiki_link">prxml</a></li><li><a href="repl-ln-api.html" class="wiki_link">repl-ln</a></li><li><a href="repl-utils-api.html" class="wiki_link">repl-utils</a></li><li><a href="seq-utils-api.html" class="wiki_link">seq-utils</a></li><li><a href="server-socket-api.html" class="wiki_link">server-socket</a></li><li><a href="set-api.html" class="wiki_link">set</a></li><li><a href="shell-out-api.html" class="wiki_link">shell-out</a></li><li><a href="singleton-api.html" class="wiki_link">singleton</a></li><li><a href="sql-api.html" class="wiki_link">sql</a></li><li><a href="str-utils-api.html" class="wiki_link">str-utils</a></li><li><a href="str-utils2-api.html" class="wiki_link">str-utils2</a></li><li><a href="stream-utils-api.html" class="wiki_link">stream-utils</a></li><li><a href="swing-utils-api.html" class="wiki_link">swing-utils</a></li><li><a href="test-is-api.html" class="wiki_link">test-is</a></li><li><a href="trace-api.html" class="wiki_link">trace</a></li><li><a href="types-api.html" class="wiki_link">types</a></li><li><a href="with-ns-api.html" class="wiki_link">with-ns</a></li><li><a href="zip-filter-api.html" class="wiki_link">zip-filter</a></li>
+ </ul>
+ </div>
+</div>
+</div>
+ <div id="rightcolumn">
+ <div id="Content">
+ <div class="contentBox"><div class="innerContentBox">
+ <div id="content_view" class="wiki wikiPage">
+ <div id="right-sidebar"></div>
+ <div id="content-tag"><html><body><h1>A Common Lisp-compatible Format Function</h1>
+
+<p>cl-format is an implementation of the incredibly baroque Common Lisp format function as specified
+in <a href="http://www.cs.cmu.edu/afs/cs.cmu.edu/project/ai-repository/ai/html/cltl/clm/node200.html#SECTION002633000000000000000">Common Lisp, the Language, 2nd edition, Chapter 22</a>.</p>
+
+<p>Format gives you an easy and powerful way to format text and data for output. It supports rich
+formatting of strings and numbers, loops, conditionals, embedded formats, etc. It is really a
+domain-specific language for formatting.</p>
+
+<p>This implementation for clojure has the following goals:</p>
+
+<ul>
+<li>Support the full feature set of the Common Lisp format function (including the X3J13 extensions) with the only exception being concepts that make no sense or are differently interpreted in Clojure.</li>
+<li>Make porting code from Common Lisp easier.</li>
+<li>Provide a more native feeling solution for Clojure programmers than the Java format method and its relatives.</li>
+<li>Be fast. This includes the ability to precompile formats that are going to be used reptitively.</li>
+<li>Include useful error handling and comprehensive documentation.</li>
+</ul>
+
+<h2>Why would I use cl-format?</h2>
+
+<p>For some people the answer to this question is that they are used to
+Common Lisp and, therefore, they already know the syntax of format
+strings and all the directives.</p>
+
+<p>A more interesting answer is that cl-format provides a way of
+rendering strings that is much more suited to Lisp and its data
+structures. </p>
+
+<p>Because iteration and conditionals are built into the directive
+structure of cl-format, it is possible to render sequences and other
+complex data structures directly without having to loop over the data
+structure. </p>
+
+<p>For example, to print the elements of a sequence separated by commas,
+you simply say:</p>
+
+<pre><code>(cl-format true "~{~a~^, ~}" aseq)
+</code></pre>
+
+<p>(This example is taken from
+<a href="http://www.gigamonkeys.com/book/">Practical Common Lisp</a>
+by Peter Seibel.)</p>
+
+<p>The corresponding output using Clojure's Java-based <em>format</em> function
+would involve a nasty loop/recur with some code to figure out about
+the commas. Yuck!</p>
+
+<h2>Current Status of cl-format</h2>
+
+<p>cl-format is 100% compatible with the Common Lisp standard as
+specified in CLtLv2.
+This includes all of the functionality of Common
+Lisp's format function including iteration, conditionals,
+text justification and rich
+options for displaying real and integer values. It also includes the
+directives to support pretty printing structured output.</p>
+
+<p>If you find a bug in a directive, drop me a line
+with a chunk of code that exhibits the bug and the version of
+cl-format you found it in and I'll try to get it fixed.</p>
+
+<p>I also intend to have good built-in documentation for the directives,
+but I haven't built that yet.</p>
+
+<p>The following directives are
+not yet supported: ~:T and ~@:T (but all other forms of ~T work)
+and extensions with ~/. </p>
+
+<p>The pretty printer interface is similar, but not identical to the
+interface in Common Lisp.</p>
+
+<p>The custom dispatch table functionality is not fully fleshed out yet.</p>
+
+<p>Next up: </p>
+
+<ul>
+<li>Support for ~/</li>
+<li>Restructure unit tests into modular chunks.</li>
+<li>Import tests from CLISP and SBCL.</li>
+<li>Unit tests for exception conditions.</li>
+<li>Interactive documentation</li>
+</ul>
+
+<h2>How to use cl-format</h2>
+
+<h3>Loading cl-format in your program</h3>
+
+<p>Once cl-format is in your path, adding it to your code is easy:</p>
+
+<pre><code>(ns your-namespace-here
+ (:use clojure.contrib.pprint))
+</code></pre>
+
+<p>If you want to refer to the cl-format function as "format" (rather
+than using the clojure function of that name), you can use this idiom:</p>
+
+<pre><code>(ns your-namespace-here
+ (:refer-clojure :exclude [format])
+ (:use clojure.contrib.pprint))
+
+(def format cl-format)
+</code></pre>
+
+<p>You might want to do this in code that you've ported from Common Lisp,
+for instance, or maybe just because old habits die hard.</p>
+
+<p>From the REPL, you can grab it using (use):</p>
+
+<pre><code>(use 'clojure.contrib.pprint)
+</code></pre>
+
+<h3>Calling cl-format</h3>
+
+<p>cl-format is a standard clojure function that takes a variable number
+of arguments. You call it like this:</p>
+
+<pre><code>(cl-format stream format args...)
+</code></pre>
+
+<p><em>stream</em> can be any Java Writer (that is java.io.Writer) or the values
+<em>true</em>, <em>false</em>, or <em>nil</em>. The argument <em>true</em> is identical to using
+<code>*</code>out<code>*</code> while <em>false</em> or <em>nil</em> indicate that cl-format should return
+its result as a string rather than writing it to a stream.</p>
+
+<p><em>format</em> is either a format string or a compiled format (see
+below). The format string controls the output that's written in a way
+that's similar to (but much more powerful than) the standard Clojure
+API format function (which is based on Java's
+java.lang.String.Format).</p>
+
+<p>Format strings consist of characters that are to be written to the
+output stream plus directives (which are marked by ~) as in "The
+answer is ~,2f". Format strings are documented in detail in
+<a href="http://www.cs.cmu.edu/afs/cs.cmu.edu/project/ai-repository/ai/html/cltl/clm/node200.html#SECTION002633000000000000000"><em>Common Lisp the Language</em>, 2nd edition, Chapter 22</a>.</p>
+
+<p><em>args</em> is a set of arguments whose use is defined by the format.</p>
+
+<h3>Compiled formats</h3>
+
+<p>When you use a format string many times (for example, when you're outputting
+in a loop), you can improve your performance by compiling the format
+with <em>compile-format</em>. The result of compile format can be passed to
+<em>cl-format</em> just like a format string but it doesn't need to be
+parsed.</p>
+
+<p>For example:</p>
+
+<pre><code>(def log-format (compile-format "~2,'0D/~2,'0D/~D ~2D:~2,'0D ~:[PM,AM]: ~A~%"))
+
+(defn log [msg]
+ (let [[m d y h min am?] (some-date-decomposition-fn)]
+ (cl-format log-format m d y h min am? msg)))
+</code></pre>
+
+<h2>Using column aware streams across format invocations</h2>
+
+<p>Writers in Java have no real idea of current column or device page width, so the format
+directives that want to work relative to the current position on the
+page have nothing to work with. To deal with this, cl-format contains
+an extension to writer called PrettyWriter. PrettyWriter watches the
+output and keeps track of what column the current output is going to.</p>
+
+<p>When you call format and your format includes a directive that cares
+about what column it's in (~T, ~&amp;, ~&lt;...~&gt;), cl-format will
+automatically wrap the Writer you passed in with a PrettyWriter. This
+means that by default all cl-format statements act like they begin on
+a fresh line and have a page width of 72.</p>
+
+<p>For many applications, these assumptions are fine and you need to do
+nothing more. But sometimes you want to use multiple cl-format calls
+that output partial lines. You may also want to mix cl-format calls
+with the native clojure calls like print. If you want stay
+column-aware while doingg this you need to create a PrettyWriter of
+your own (and possibly bind it to <code>*</code>out<code>*</code>).</p>
+
+<p>As an example of this, this function takes a nested list and prints it
+as a table (returning the result as a string):</p>
+
+<pre><code>(defn list-to-table [aseq column-width]
+ (let [stream (PrettyWriter. (java.io.StringWriter.))]
+ (binding [*out* stream]
+ (doseq [row aseq]
+ (doseq [col row]
+ (cl-format true "~4D~7,vT" col column-width))
+ (prn)))
+ (.toString (.getWriter stream))))
+</code></pre>
+
+<p>(In reality, you'd probably do this as a single call to cl-format.)</p>
+
+<p>The constructor to PrettyWriter takes the Writer it's wrapping and
+(optionally) the page width (in columns) for use with ~&lt;...~&gt;. </p>
+
+<h2>Examples</h2>
+
+<p>The following function uses cl-format to dump a columnized table of the Java system properties:</p>
+
+<pre><code>(defn show-props [stream]
+ (let [p (mapcat
+ #(vector (key %) (val %))
+ (sort-by key (System/getProperties)))]
+ (cl-format stream "~30A~A~%~{~20,,,'-A~10A~}~%~{~30A~S~%~}"
+ "Property" "Value" ["" "" "" ""] p)))
+</code></pre>
+
+<p>There are some more examples in the clojure.contrib.pprint.examples
+package:</p>
+
+<ul>
+<li>hexdump - a program that uses cl-format to create a standard formatted hexdump of the requested stream.</li>
+<li>multiply - a function to show a formatted multipication table in a very "first-order" way.</li>
+<li>props - the show-props example shown above.</li>
+<li>show_doc - some utilities for showing documentation from various name spaces.</li>
+</ul>
+
+<h2>Differences from the Common Lisp format function</h2>
+
+<p>The floating point directives that show exponents (~E, ~G) show E for
+the exponent character in all cases (unless overridden with an
+<em>exponentchar</em>). Clojure does not distinguish between floats and
+doubles in its printed representation and neither does cl-format.</p>
+
+<p>The ~A and ~S directives accept the colon prefix, but ignore it since
+() and nil are not equivalent in Clojure.</p>
+
+<p>Clojure has 3 different reader syntaxes for characters. The ~@c
+directive to cl-format has an argument extension to let you choose:</p>
+
+<ul>
+<li>~@c (with no argument) prints "\c" (backslash followed by the printed representation of the character or \newline, \space, \tab, \backspace, \return)</li>
+<li>~'o@c prints "\oDDD" where DDD are the o