emacs.d/clones/lisp/www.cliki.net/infix.html

401 lines
54 KiB
HTML
Raw Normal View History

2022-10-07 15:47:14 +02:00
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>CLiki: Infix</title>
<link rel="alternate" type="application/atom+xml" title="ATOM feed of edits to current article"
href="https://www.cliki.net/site/feed/article.atom?title=Infix">
<link rel="stylesheet" href="static/css/style.css">
<link rel="stylesheet" href="static/css/colorize.css">
</head>
<body>
<span class="hidden">CLiki - Infix</span>
<div id="content"><div id="content-area"><div id="article-title">Infix</div><div id="article">The infix notation for arithmetic in Common Lisp.<p><ul>
<li>
<a href="polisher.html" class="internal">polisher</a> -
<a href="Infix.html" class="category">Infix</a> notation to <a href="s-exp&#32;syntax.html" class="internal">S-expression</a> (Polish notation) translator for Common Lisp
</li>
<li>
<a href="ugly-tiny-infix-macro.html" class="internal">ugly-tiny-infix-macro</a> -
This is a powerful lisp macro for the purpose of writing your expressions in <a href="infix.html" class="category">infix</a> notation while not losing out on lisp's power
</li>
</ul> <p><h2>Infix reader-macro by Mark Kantrowitz.</h2><p>Available from the <a href="CMU&#32;AI&#32;Repository.html" class="internal">CMU AI Repository</a>: <a href="http://www.cs.cmu.edu/afs/cs/project/ai-repository/ai/lang/lisp/code/syntax/infix/infix.cl">infix.cl</a>.<p>The Changelog from the <a href="cclan.html" class="internal">cclan</a> version reads<p><pre>
2005-06-06:
* infix.cl: bind *read-suppress* in infix-reader to support the
use of infix notation when *read-suppress* is true.
Christophe Rhodes &lt;csr21@cam.ac.uk&gt;
2002-03-04:
* infix.cl: moved definition of infix-error macro to before its
first use.
Christophe Rhodes &lt;csr21@cam.ac.uk&gt;.
</pre><p>This is not the most volatile piece of software.<p>Incidentally, it's probably <a href="non-free.html" class="internal">non-free</a> — there's a non-commercial clause in the <a href="license.html" class="internal">license</a>.<p>There is also a <a href="Debian&#32;package.html" class="category">Debian package</a>.<p>Note: Users may want to consider <a href="readable.html" class="internal">readable</a> instead, which is <a href="MIT.html" class="internal">MIT</a>-licensed and has support for an infix notation.<p>Another package by Alan Manuel Gloria can be found <a href="http://web.archive.org/web/20100102215454/http://plaza.ufl.edu/lavigne/resources/index.html">here</a>, but it's buggy on expressions like <p><div class="code"><span class="nonparen"><span class="paren1">(<span class="nonparen">nfx 55 <a href="https://www.cliki.net/site/HyperSpec/Body/any_-.html" class="symbol">-</a> 3 <a href="https://www.cliki.net/site/HyperSpec/Body/any_st.html" class="symbol">*</a> 4 <a href="https://www.cliki.net/site/HyperSpec/Body/any_pl.html" class="symbol">+</a> 2000000</span>)</span></span></div><p>(giving -1999957 instead of the correct result 2000043. There seems to be a problem with different operators of the same precedence. <p>Here's a corrected version of the macro implementation:<p><div class="code"><span class="nonparen"><span class="comment">;; infix.lisp
</span><span class="comment">;; by AmkG
</span>
<span class="comment">;; Title : Infix notation macro
</span><span class="comment">;; Filename : infix.lisp
</span><span class="comment">;; Written by : Alan Manuel K. Gloria &lt;almkglor@gmail.com&gt;
</span><span class="comment">;; Corrected by : Bruno Daniel &lt;bruno.daniel@gmx.net&gt;
</span>
<span class="comment">;; Copyright status:
</span><span class="comment">;; Err. I don't care? Okay, I do care. To be honest, I'll just
</span><span class="comment">;; be plain happy if somebody ELSE uses this. Drop me a line,
</span><span class="comment">;; or something. Or don't. I built this for my own amusement,
</span><span class="comment">;; so if anyone else is amused too, well, drop me a line!
</span>
<span class="comment">;; tested on:
</span><span class="comment">;; clisp
</span><span class="comment">;; gcl
</span><span class="comment">;; sbcl
</span><span class="comment">;; ecl
</span>
<span class="comment">;; infix notation:
</span><span class="comment">;; Lisp has traditionally used prefix notation for all formulae: in this
</span><span class="comment">;; notation, the operation to be performed is specified before the
</span><span class="comment">;; operands it is to be performed on. This simple notation gives a
</span><span class="comment">;; consistent, regular syntax which greatly facilitates
</span><span class="comment">;; metaprogramming.
</span>
<span class="comment">;; However, one weakness of prefix notation is that some simple
</span><span class="comment">;; algebraic/arithmetic operations do not and cannot follow the
</span><span class="comment">;; traditional syntax taught to us during elementary - that is, the
</span><span class="comment">;; notation we are used to in arithmetic is not prefix, but infix
</span><span class="comment">;; notation:
</span><span class="comment">;; 1 + 2 - 4 * 5
</span><span class="comment">;; In Lisp this would be:
</span><span class="comment">;; (- (+ 1 2) (* 4 5)))
</span><span class="comment">;; Despite the inherent advantages of prefix notation, sometimes
</span><span class="comment">;; it's just much easier to write mathematical formulae a little more
</span><span class="comment">;; like the way we actually write them on paper.
</span>
<span class="comment">;; This file contains a macro, 'nfx, which allows for such an infix
</span><span class="comment">;; notation. There are limitations: you need to put a LOT of spaces
</span><span class="comment">;; in the formula:
</span><span class="comment">;; (nfx 1+2-3) ;would confuse the Lisp parser
</span><span class="comment">;; (nfx 1 + 2 - 3) ;would be understood
</span>
<span class="comment">;; You can't use certain symbols as variable names:
</span><span class="comment">;; (setf + 42)
</span><span class="comment">;; (nfx (max + 3)) ; would look awfully like +(max,3), not max(+,3)
</span>
<span class="comment">;; ...but you can embed prefix notation in it!
</span><span class="comment">;; (nfx 1 + (- x 100)) ;it's valid!
</span><span class="comment">;; (nfx 1 + (- x (3 * 3))) ;it's ALSO valid!
</span><span class="comment">;; (nfx 1 + (- x 3 * 3)) ;err... this can give you unexpected behavior
</span>
<span class="comment">;; ...also, you can define your own infix symbols using definfix:
</span><span class="comment">;; (definfix my-infix-symbol
</span><span class="comment">;; :precedence 40
</span><span class="comment">;; :function-name +)
</span><span class="comment">;; (nfx 1 my-infix-symbol 2)
</span><span class="comment">;; =&gt; 3
</span>
<span class="comment">;; send any feedback, bugreports, bugfixes, and cute girls to:
</span><span class="comment">;; almkglor@gmail.com
</span>
<span class="comment">;; This file defines a macro of the form (nfx ...) whose
</span><span class="comment">;; parameters are a stream of LISP "tokens" (either symbols,
</span><span class="comment">;; constants, or lists). The stream of tokens is interpreted
</span><span class="comment">;; in infix notation. The macro then expands to the prefix
</span><span class="comment">;; form equivalent to the infix form
</span><span class="comment">;; Ex.
</span><span class="comment">;; (macroexpand-1 '(nfx foo = 32))
</span><span class="comment">;; =&gt; (setf foo 32)
</span><span class="comment">;; (macroexpand-1 '(nfx bar == (3 + foo) * quux ))
</span><span class="comment">;; =&gt; (equal bar (* (+ 3 foo) quux))
</span>
<span class="comment">;; NOTE: detection of function calls
</span><span class="comment">;; function call forms should be supported:
</span><span class="comment">;; (macroexpand-1 '(nfx foo = (max (bar + 32) quux niaw) ))
</span><span class="comment">;; =&gt; (setf foo (max (+ bar 32) quux niaw))
</span><span class="comment">;; (macroexpand-1 '(nfx (cdr foo) = (cons (qux + 1) nil)))
</span><span class="comment">;; =&gt; (setf (cdr foo) (cons (+ qux 1) nil))
</span>
<span class="comment">;; If any infix notation is in a function call within an
</span><span class="comment">;; nfx form, it should be within a parentheses:
</span><span class="comment">;; (macroexpand-1 '(nfx (max (bar + foo) (quux + quuux)) ))
</span><span class="comment">;; =&gt; (max (+ bar foo) (+ quux quuux))
</span><span class="comment">;; (macroexpand-1 '(nfx (max bar + foo quux + quuux) ))
</span><span class="comment">;; =&gt; (max bar + foo quux + quuux)
</span>
<span class="comment">;; function calls are detected in the following manner:
</span><span class="comment">;; if nfx detects a list in the input stream,
</span><span class="comment">;; if the second item is not a registered infix,
</span><span class="comment">;; function call, for each element recurse and replace the element
</span><span class="comment">;; not a function call, recurse on the list as a new stream
</span>
<span class="comment">;; this allows us to use prefix operators (such as -) as-is:
</span><span class="comment">;; (macroexpand-1 '(nfx (- bar) == (/ (foo + 1)) ))
</span><span class="comment">;; =&gt; (equal (- bar) (/ (+ foo 1)))
</span>
<span class="comment">;; (nfx-operator-base &lt;action&gt; ...)
</span><span class="comment">;; Handles the operator database
</span>
<span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/speope_letcm_letst.html" class="symbol"><i><span class="symbol">let</span></i></a> <span class="paren2">(<span class="nonparen"><span class="paren3">(<span class="nonparen">nfx-data <span class="paren4">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_make-hash-table.html" class="symbol">make-hash-table</a> <span class="keyword">:test</span> '<a href="https://www.cliki.net/site/HyperSpec/Body/fun_eq.html" class="symbol">eq</a></span>)</span></span>)</span></span>)</span>
<span class="paren2">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_defun.html" class="symbol"><i><span class="symbol">defun</span></i></a> nfx-operator-base <span class="paren3">(<span class="nonparen">action &amp;rest params</span>)</span>
<span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/speope_fletcm_scm_macrolet.html" class="symbol"><i><span class="symbol">labels</span></i></a>
<span class="paren4">(<span class="nonparen"><span class="paren5">(<span class="nonparen">getval <span class="paren6">(<span class="nonparen">sym</span>)</span>
<span class="paren6">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_gethash.html" class="symbol">gethash</a> sym nfx-data</span>)</span> </span>)</span>
<span class="paren5">(<span class="nonparen">add <span class="paren6">(<span class="nonparen">params</span>)</span>
<span class="paren6">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_setf.html" class="symbol">setf</a> <span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_gethash.html" class="symbol">gethash</a> <span class="paren2">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_carcm_cdr_darcm_cddddr.html" class="symbol">car</a> params</span>)</span> nfx-data</span>)</span>
<span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_apply.html" class="symbol">apply</a> #'<a href="https://www.cliki.net/site/HyperSpec/Body/any_vector.html" class="symbol">vector</a> params</span>)</span></span>)</span></span>)</span></span>)</span>
<span class="paren4">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_casecm_ccasecm_ecase.html" class="symbol">case</a> action
<span class="paren5">(<span class="nonparen"><span class="keyword">:get</span> <span class="paren6">(<span class="nonparen">getval <span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_carcm_cdr_darcm_cddddr.html" class="symbol">car</a> params</span>)</span></span>)</span></span>)</span>
<span class="paren5">(<span class="nonparen"><span class="keyword">:add</span> <span class="paren6">(<span class="nonparen">add params</span>)</span></span>)</span></span>)</span></span>)</span></span>)</span></span>)</span>
<span class="comment">;;; the nfx macro
</span>
<span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_defun.html" class="symbol"><i><span class="symbol">defun</span></i></a> nfx-impl <span class="paren2">(<span class="nonparen">s</span>)</span>
<span class="paren2">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/speope_letcm_letst.html" class="symbol"><i><span class="symbol">let</span></i></a> <span class="paren3">(<span class="nonparen">opstack
curop tmp
<span class="paren4">(<span class="nonparen">bldg <span class="paren5">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_cons.html" class="symbol">cons</a> <a href="https://www.cliki.net/site/HyperSpec/Body/any_nil.html" class="symbol">nil</a> <a href="https://www.cliki.net/site/HyperSpec/Body/any_nil.html" class="symbol">nil</a></span>)</span></span>)</span></span>)</span>
<span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/speope_fletcm_scm_macrolet.html" class="symbol"><i><span class="symbol">labels</span></i></a>
<span class="paren4">(<span class="nonparen"> <span class="comment">;; tconc = a cons with pointers to the head and the last element of
</span> <span class="comment">;; a list. This function appends an element to such a tconc.
</span> <span class="paren5">(<span class="nonparen">tconc-append <span class="paren6">(<span class="nonparen">l v</span>)</span>
<span class="paren6">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/speope_if.html" class="symbol"><i><span class="symbol">if</span></i></a> <span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_carcm_cdr_darcm_cddddr.html" class="symbol">car</a> l</span>)</span>
<span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_setf.html" class="symbol">setf</a> <span class="paren2">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_carcm_cdr_darcm_cddddr.html" class="symbol">cdr</a> l</span>)</span> <span class="paren2">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_setf.html" class="symbol">setf</a> <span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_carcm_cdr_darcm_cddddr.html" class="symbol">cddr</a> l</span>)</span> <span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_cons.html" class="symbol">cons</a> v <a href="https://www.cliki.net/site/HyperSpec/Body/any_nil.html" class="symbol">nil</a></span>)</span></span>)</span></span>)</span>
<span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_setf.html" class="symbol">setf</a> <span class="paren2">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_carcm_cdr_darcm_cddddr.html" class="symbol">car</a> l</span>)</span> <span class="paren2">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_setf.html" class="symbol">setf</a> <span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_carcm_cdr_darcm_cddddr.html" class="symbol">cdr</a> l</span>)</span> <span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_cons.html" class="symbol">cons</a> v <a href="https://www.cliki.net/site/HyperSpec/Body/any_nil.html" class="symbol">nil</a></span>)</span></span>)</span></span>)</span> </span>)</span></span>)</span>
<span class="comment">;; top-of-stack query
</span> <span class="paren5">(<span class="nonparen">top-opstack <span class="paren6">(<span class="nonparen"></span>)</span>
<span class="paren6">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_carcm_cdr_darcm_cddddr.html" class="symbol">caaar</a> opstack</span>)</span></span>)</span>
<span class="comment">;; handles any sub-lists
</span> <span class="paren5">(<span class="nonparen">enlist <span class="paren6">(<span class="nonparen">l</span>)</span>
<span class="paren6">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_whencm_unless.html" class="symbol">when</a> l
<span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_cond.html" class="symbol"><i><span class="symbol">cond</span></i></a> <span class="paren2">(<span class="nonparen"><span class="paren3">(<span class="nonparen">getop <span class="paren4">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_carcm_cdr_darcm_cddddr.html" class="symbol">cadr</a> l</span>)</span></span>)</span>
<span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_cons.html" class="symbol">cons</a> 'nfx l</span>)</span></span>)</span>
<span class="paren2">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_t.html" class="symbol">t</a> <span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_mapccm_ma_istcm_mapcon.html" class="symbol">mapcar</a> #'<span class="paren4">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_lambda.html" class="symbol"><i><span class="symbol">lambda</span></i></a> <span class="paren5">(<span class="nonparen">o</span>)</span> <span class="paren5">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/speope_if.html" class="symbol"><i><span class="symbol">if</span></i></a> <span class="paren6">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_listp.html" class="symbol">listp</a> o</span>)</span> <span class="paren6">(<span class="nonparen">enlist o</span>)</span> o</span>)</span></span>)</span>
l</span>)</span></span>)</span></span>)</span></span>)</span></span>)</span>
<span class="comment">;; pushes an operation onto the stack - used when the currently
</span> <span class="comment">;; being built operation is of lower precedence than the
</span> <span class="comment">;; operation being considered
</span> <span class="paren5">(<span class="nonparen">push-oper <span class="paren6">(<span class="nonparen"></span>)</span>
<span class="paren6">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_push.html" class="symbol">push</a> bldg opstack</span>)</span>
<span class="paren6">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_setf.html" class="symbol">setf</a> bldg <span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_cons.html" class="symbol">cons</a> <a href="https://www.cliki.net/site/HyperSpec/Body/any_nil.html" class="symbol">nil</a> <a href="https://www.cliki.net/site/HyperSpec/Body/any_nil.html" class="symbol">nil</a></span>)</span></span>)</span></span>)</span>
<span class="comment">;; pops off an operation from the stack,
</span> <span class="comment">;; - used before collapsing the call
</span> <span class="paren5">(<span class="nonparen">pop-oper <span class="paren6">(<span class="nonparen"></span>)</span>
<span class="paren6">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/speope_letcm_letst.html" class="symbol"><i><span class="symbol">let</span></i></a> <span class="paren1">(<span class="nonparen"><span class="paren2">(<span class="nonparen">top <span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_pop.html" class="symbol">pop</a> opstack</span>)</span></span>)</span> </span>)</span>
<span class="paren1">(<span class="nonparen">tconc-append top <span class="paren2">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_carcm_cdr_darcm_cddddr.html" class="symbol">car</a> bldg</span>)</span></span>)</span>
<span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_setf.html" class="symbol">setf</a> bldg top</span>)</span></span>)</span></span>)</span>
<span class="comment">;; sub-expression handling code
</span> <span class="paren5">(<span class="nonparen">expr <span class="paren6">(<span class="nonparen">o</span>)</span>
<span class="paren6">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/speope_if.html" class="symbol"><i><span class="symbol">if</span></i></a> <span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_listp.html" class="symbol">listp</a> o</span>)</span>
<span class="paren1">(<span class="nonparen">enlist o</span>)</span>
o</span>)</span></span>)</span>
<span class="comment">;; determine if the specified operation has precedence over the
</span> <span class="comment">;; operation currently being built
</span> <span class="paren5">(<span class="nonparen">precedes? <span class="paren6">(<span class="nonparen">op1 op2 associativity</span>)</span>
<span class="paren6">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_or.html" class="symbol">or</a> <span class="paren1">(<span class="nonparen">&lt; <span class="paren2">(<span class="nonparen">precedence op1</span>)</span> <span class="paren2">(<span class="nonparen">precedence op2</span>)</span></span>)</span>
<span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_and.html" class="symbol">and</a> <span class="paren2">(<span class="nonparen">= <span class="paren3">(<span class="nonparen">precedence op1</span>)</span> <span class="paren3">(<span class="nonparen">precedence op2</span>)</span></span>)</span>
<span class="paren2">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_eq.html" class="symbol">eq</a> <span class="paren3">(<span class="nonparen">associativity op1</span>)</span> associativity</span>)</span></span>)</span></span>)</span></span>)</span>
<span class="comment">;; funges bldg: collapses fungible operations into one form
</span> <span class="paren5">(<span class="nonparen">fungebldg <span class="paren6">(<span class="nonparen">bldg</span>)</span>
<span class="paren6">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_mapccm_ma_istcm_mapcon.html" class="symbol">mapcan</a>
#'<span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_lambda.html" class="symbol"><i><span class="symbol">lambda</span></i></a> <span class="paren2">(<span class="nonparen">o</span>)</span>
<span class="paren2">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_cond.html" class="symbol"><i><span class="symbol">cond</span></i></a> <span class="paren3">(<span class="nonparen"><span class="paren4">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_listp.html" class="symbol">listp</a> o</span>)</span>
<span class="paren4">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_setf.html" class="symbol">setf</a> o <span class="paren5">(<span class="nonparen">fungebldg o</span>)</span></span>)</span>
<span class="paren4">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_cond.html" class="symbol"><i><span class="symbol">cond</span></i></a> <span class="paren5">(<span class="nonparen"><span class="paren6">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_and.html" class="symbol">and</a> <span class="paren1">(<span class="nonparen">fungible <span class="paren2">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_carcm_cdr_darcm_cddddr.html" class="symbol">car</a> bldg</span>)</span></span>)</span>
<span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_eq.html" class="symbol">eq</a> <span class="paren2">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_carcm_cdr_darcm_cddddr.html" class="symbol">car</a> o</span>)</span> <span class="paren2">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_carcm_cdr_darcm_cddddr.html" class="symbol">car</a> bldg</span>)</span></span>)</span></span>)</span>
<span class="paren6">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_carcm_cdr_darcm_cddddr.html" class="symbol">cdr</a> o</span>)</span></span>)</span>
<span class="paren5">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_t.html" class="symbol">t</a> <span class="paren6">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_cons.html" class="symbol">cons</a> o <a href="https://www.cliki.net/site/HyperSpec/Body/any_nil.html" class="symbol">nil</a></span>)</span></span>)</span></span>)</span></span>)</span>
<span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_t.html" class="symbol">t</a> <span class="paren4">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_cons.html" class="symbol">cons</a> o <a href="https://www.cliki.net/site/HyperSpec/Body/any_nil.html" class="symbol">nil</a></span>)</span></span>)</span></span>)</span></span>)</span>
bldg</span>)</span></span>)</span>
<span class="comment">;; fixes bldg: changes operation objects to their functions
</span> <span class="paren5">(<span class="nonparen">fixbldg <span class="paren6">(<span class="nonparen">bldg</span>)</span>
<span class="paren6">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_whencm_unless.html" class="symbol">when</a> <span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_vectorp.html" class="symbol">vectorp</a> <span class="paren2">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_carcm_cdr_darcm_cddddr.html" class="symbol">car</a> bldg</span>)</span></span>)</span>
<span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_setf.html" class="symbol">setf</a> <span class="paren2">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_carcm_cdr_darcm_cddddr.html" class="symbol">car</a> bldg</span>)</span> <span class="paren2">(<span class="nonparen">function-name <span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_carcm_cdr_darcm_cddddr.html" class="symbol">car</a> bldg</span>)</span></span>)</span></span>)</span> </span>)</span>
<span class="paren6">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_mapccm_ma_istcm_mapcon.html" class="symbol">mapc</a>
#'<span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_lambda.html" class="symbol"><i><span class="symbol">lambda</span></i></a> <span class="paren2">(<span class="nonparen">o</span>)</span>
<span class="paren2">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_whencm_unless.html" class="symbol">when</a> <span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_listp.html" class="symbol">listp</a> o</span>)</span>
<span class="paren3">(<span class="nonparen">fixbldg o</span>)</span> </span>)</span></span>)</span>
bldg </span>)</span></span>)</span>
<span class="comment">;; error-handling function
</span> <span class="paren5">(<span class="nonparen">err <span class="paren6">(<span class="nonparen">l</span>)</span>
<span class="paren6">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_error.html" class="symbol">error</a> <span class="string">"improper nfx expression:~%~s"</span> l</span>)</span></span>)</span>
<span class="paren5">(<span class="nonparen">print-expr-list <span class="paren6">(<span class="nonparen">l</span>)</span>
<span class="paren6">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_format.html" class="symbol">format</a> <a href="https://www.cliki.net/site/HyperSpec/Body/any_t.html" class="symbol">t</a> <span class="string">"("</span></span>)</span>
<span class="paren6">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_loop.html" class="symbol"><i><span class="symbol">loop</span></i></a> <span class="keyword">:for</span> x in l
<span class="keyword">:for</span> i from 0 <span class="keyword">:do</span>
<span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_whencm_unless.html" class="symbol">when</a> <span class="paren2">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_minuspcm_plusp.html" class="symbol">plusp</a> i</span>)</span>
<span class="paren2">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_format.html" class="symbol">format</a> <a href="https://www.cliki.net/site/HyperSpec/Body/any_t.html" class="symbol">t</a> <span class="string">" "</span></span>)</span></span>)</span>
<span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_cond.html" class="symbol"><i><span class="symbol">cond</span></i></a> <span class="paren2">(<span class="nonparen"><span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_vectorp.html" class="symbol">vectorp</a> x</span>)</span>
<span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_format.html" class="symbol">format</a> <a href="https://www.cliki.net/site/HyperSpec/Body/any_t.html" class="symbol">t</a> <span class="string">"~s"</span> <span class="paren4">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_aref.html" class="symbol">aref</a> x 0</span>)</span></span>)</span></span>)</span>
<span class="paren2">(<span class="nonparen"><span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_listp.html" class="symbol">listp</a> x</span>)</span>
<span class="paren3">(<span class="nonparen">print-expr-list x</span>)</span></span>)</span>
<span class="paren2">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_t.html" class="symbol">t</a>
<span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_format.html" class="symbol">format</a> <a href="https://www.cliki.net/site/HyperSpec/Body/any_t.html" class="symbol">t</a> <span class="string">"~s"</span> x</span>)</span></span>)</span></span>)</span></span>)</span>
<span class="paren6">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_format.html" class="symbol">format</a> <a href="https://www.cliki.net/site/HyperSpec/Body/any_t.html" class="symbol">t</a> <span class="string">")"</span></span>)</span></span>)</span>
<span class="comment">;; (print-tconc (tc)
</span> <span class="comment">;; (print-expr-list (car tc))
</span> <span class="comment">;; (format t "~%"))
</span> <span class="comment">;; accessor functions
</span> <span class="paren5">(<span class="nonparen">precedence <span class="paren6">(<span class="nonparen">op</span>)</span> <span class="paren6">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/speope_if.html" class="symbol"><i><span class="symbol">if</span></i></a> op <span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_aref.html" class="symbol">aref</a> op 1</span>)</span> 99999</span>)</span></span>)</span>
<span class="paren5">(<span class="nonparen">associativity <span class="paren6">(<span class="nonparen">op</span>)</span> <span class="paren6">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_aref.html" class="symbol">aref</a> op 2</span>)</span></span>)</span>
<span class="paren5">(<span class="nonparen">function-name <span class="paren6">(<span class="nonparen">op</span>)</span> <span class="paren6">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_aref.html" class="symbol">aref</a> op 3</span>)</span></span>)</span>
<span class="paren5">(<span class="nonparen">fungible <span class="paren6">(<span class="nonparen">op</span>)</span> <span class="paren6">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_whencm_unless.html" class="symbol">when</a> <span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_vectorp.html" class="symbol">vectorp</a> op</span>)</span> <span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_aref.html" class="symbol">aref</a> op 4</span>)</span></span>)</span></span>)</span>
<span class="comment">;; get the data for a (presumed) infix operator
</span> <span class="paren5">(<span class="nonparen">getop <span class="paren6">(<span class="nonparen">op</span>)</span>
<span class="paren6">(<span class="nonparen">nfx-operator-base <span class="keyword">:get</span> op</span>)</span></span>)</span></span>)</span>
<span class="paren4">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_casecm_ccasecm_ecase.html" class="symbol">case</a> <span class="paren5">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_length.html" class="symbol">length</a> s</span>)</span>
<span class="paren5">(<span class="nonparen">1 <span class="paren6">(<span class="nonparen">expr <span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_carcm_cdr_darcm_cddddr.html" class="symbol">car</a> s</span>)</span></span>)</span></span>)</span>
<span class="paren5">(<span class="nonparen">2 <span class="paren6">(<span class="nonparen">err s</span>)</span></span>)</span>
<span class="paren5">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_t.html" class="symbol">t</a>
<span class="paren6">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_docm_dost.html" class="symbol">do</a> <span class="paren1">(<span class="nonparen"> <span class="comment">;; variable and step list
</span> <span class="paren2">(<span class="nonparen">oL s <span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_carcm_cdr_darcm_cddddr.html" class="symbol">cddr</a> oL</span>)</span></span>)</span> </span>)</span>
<span class="paren1">(<span class="nonparen"> <span class="comment">;; termination condition
</span> <span class="paren2">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_null.html" class="symbol">null</a> <span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_carcm_cdr_darcm_cddddr.html" class="symbol">cddr</a> oL</span>)</span></span>)</span>
<span class="paren2">(<span class="nonparen">tconc-append bldg <span class="paren3">(<span class="nonparen">expr <span class="paren4">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_carcm_cdr_darcm_cddddr.html" class="symbol">car</a> oL</span>)</span></span>)</span></span>)</span>
<span class="paren2">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_whencm_unless.html" class="symbol">when</a> <span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_carcm_cdr_darcm_cddddr.html" class="symbol">cdr</a> oL</span>)</span>
<span class="paren3">(<span class="nonparen">err oL</span>)</span> </span>)</span>
<span class="paren2">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_loop.html" class="symbol"><i><span class="symbol">loop</span></i></a> <span class="keyword">:while</span> opstack <span class="keyword">:do</span>
<span class="paren3">(<span class="nonparen">pop-oper</span>)</span></span>)</span>
<span class="paren2">(<span class="nonparen">fixbldg <span class="paren3">(<span class="nonparen">fungebldg <span class="paren4">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_carcm_cdr_darcm_cddddr.html" class="symbol">caar</a> bldg</span>)</span></span>)</span></span>)</span></span>)</span>
<span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_setf.html" class="symbol">setf</a> curop <span class="paren2">(<span class="nonparen">getop <span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_carcm_cdr_darcm_cddddr.html" class="symbol">cadr</a> oL</span>)</span></span>)</span></span>)</span>
<span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_cond.html" class="symbol"><i><span class="symbol">cond</span></i></a> <span class="paren2">(<span class="nonparen">curop
<span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_cond.html" class="symbol"><i><span class="symbol">cond</span></i></a> <span class="paren4">(<span class="nonparen"><span class="paren5">(<span class="nonparen">precedes? curop <span class="paren6">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_carcm_cdr_darcm_cddddr.html" class="symbol">caar</a> bldg</span>)</span> <span class="keyword">:right</span></span>)</span>
<span class="paren5">(<span class="nonparen">push-oper</span>)</span>
<span class="paren5">(<span class="nonparen">tconc-append bldg curop</span>)</span>
<span class="paren5">(<span class="nonparen">tconc-append bldg <span class="paren6">(<span class="nonparen">expr <span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_carcm_cdr_darcm_cddddr.html" class="symbol">car</a> oL</span>)</span></span>)</span></span>)</span> </span>)</span>
<span class="paren4">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_t.html" class="symbol">t</a>
<span class="paren5">(<span class="nonparen">tconc-append bldg <span class="paren6">(<span class="nonparen">expr <span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_carcm_cdr_darcm_cddddr.html" class="symbol">car</a> oL</span>)</span></span>)</span></span>)</span>
<span class="comment">;; collapse while the stacktop is precedent over the
</span> <span class="comment">;; current op
</span> <span class="paren5">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_loop.html" class="symbol"><i><span class="symbol">loop</span></i></a> <span class="keyword">:while</span> <span class="paren6">(<span class="nonparen">precedes? <span class="paren1">(<span class="nonparen">top-opstack</span>)</span> curop <span class="keyword">:left</span></span>)</span> <span class="keyword">:do</span>
<span class="paren6">(<span class="nonparen">pop-oper</span>)</span></span>)</span>
<span class="paren5">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_setf.html" class="symbol">setf</a> tmp <span class="paren6">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_carcm_cdr_darcm_cddddr.html" class="symbol">car</a> bldg</span>)</span></span>)</span>
<span class="paren5">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_setf.html" class="symbol">setf</a> bldg <span class="paren6">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_cons.html" class="symbol">cons</a> <a href="https://www.cliki.net/site/HyperSpec/Body/any_nil.html" class="symbol">nil</a> <a href="https://www.cliki.net/site/HyperSpec/Body/any_nil.html" class="symbol">nil</a></span>)</span></span>)</span>
<span class="paren5">(<span class="nonparen">tconc-append bldg curop</span>)</span>
<span class="paren5">(<span class="nonparen">tconc-append bldg tmp</span>)</span> </span>)</span></span>)</span></span>)</span>
<span class="paren2">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_t.html" class="symbol">t</a>
<span class="paren3">(<span class="nonparen">err oL</span>)</span></span>)</span></span>)</span></span>)</span></span>)</span></span>)</span></span>)</span></span>)</span></span>)</span>
<span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_defmacro.html" class="symbol"><i><span class="symbol">defmacro</span></i></a> nfx <span class="paren2">(<span class="nonparen">&amp;rest s</span>)</span>
<span class="paren2">(<span class="nonparen">nfx-impl s</span>)</span></span>)</span>
<span class="comment">;; (definfix &lt;operator&gt;
</span><span class="comment">;; :precedence &lt;integer&gt;
</span><span class="comment">;; [:associativity &lt;:left | :right&gt;]
</span><span class="comment">;; [:function-name &lt;actual function&gt;]
</span><span class="comment">;; [:fungible &lt;t | nil&gt;])
</span><span class="comment">;; - defines an infix operator with the symbol &lt;operator&gt;,
</span><span class="comment">;; with a precedence of &lt;integer&gt;. The smaller the precedence
</span><span class="comment">;; number, the more precedence it has: * and / have smaller
</span><span class="comment">;; precedence number than + and -.
</span><span class="comment">;; - associativity defaults to :left, which means that if two
</span><span class="comment">;; operators of the same precedence are encountered, the first
</span><span class="comment">;; one resolves first: 1 x 2 x 3 becomes ((1 x 2) x 3). This
</span><span class="comment">;; is appropriate for most maths. :right associativity means
</span><span class="comment">;; that 1 x 2 x 3 becomes (1 x (2 x 3)). This is appropriate
</span><span class="comment">;; for assignment. IMPORTANT: operators with the same
</span><span class="comment">;; precedence must have the same associativities!
</span><span class="comment">;; - function-name defaults to the same symbol as the operator.
</span><span class="comment">;; For example, the function-name of = is setf.
</span><span class="comment">;; - fungible means that if the same operator is encountered
</span><span class="comment">;; several times, then all inputs are funged into one function
</span><span class="comment">;; call. For example, 1 + 2 + 3 becomes (+ 1 2 3), 1 &lt; 2 &lt; 3
</span><span class="comment">;; becomes (&lt; 1 2 3). This is not true for assignment:
</span><span class="comment">;; x = y = z should become (setf x (setf y z)), not (setf x y z)
</span><span class="comment">;; - fungible defaults to t because I noticed that nearly every
</span><span class="comment">;; single darned operator was fungible. Except assignment.
</span><span class="comment">;; Saved some dozen lines of code too.
</span>
<span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_defmacro.html" class="symbol"><i><span class="symbol">defmacro</span></i></a> <i><span class="symbol">definfix</span></i> <span class="paren2">(<span class="nonparen">operator
&amp;key precedence <span class="paren3">(<span class="nonparen">associativity <span class="keyword">:left</span></span>)</span>
function-name <span class="paren3">(<span class="nonparen">fungible <a href="https://www.cliki.net/site/HyperSpec/Body/any_t.html" class="symbol">t</a></span>)</span></span>)</span>
`<span class="paren2">(<span class="nonparen">nfx-operator-base <span class="keyword">:add</span> ',operator
,precedence ,associativity
',<span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/speope_if.html" class="symbol"><i><span class="symbol">if</span></i></a> function-name function-name operator </span>)</span>
,fungible</span>)</span></span>)</span>
<span class="comment">;; Predefined operators
</span><span class="comment">;; Note: precedences are divisibles of 10, in case you
</span><span class="comment">;; want to insert precedence levels between levels.
</span>
<span class="comment">;; since we expect infix notation only (not infix-postfix),
</span><span class="comment">;; our array accessor is a single infix @
</span>
<span class="paren1">(<span class="nonparen"><i><span class="symbol">definfix</span></i> @ <span class="keyword">:precedence</span> 10 <span class="keyword">:function-name</span> <a href="https://www.cliki.net/site/HyperSpec/Body/acc_aref.html" class="symbol">aref</a></span>)</span>
<span class="paren1">(<span class="nonparen"><i><span class="symbol">definfix</span></i> <a href="https://www.cliki.net/site/HyperSpec/Body/var_stcm_ststcm_ststst.html" class="symbol">**</a> <span class="keyword">:precedence</span> 20 <span class="keyword">:function-name</span> <a href="https://www.cliki.net/site/HyperSpec/Body/fun_expcm_expt.html" class="symbol">expt</a></span>)</span>
<span class="paren1">(<span class="nonparen"><i><span class="symbol">definfix</span></i> <a href="https://www.cliki.net/site/HyperSpec/Body/any_st.html" class="symbol">*</a> <span class="keyword">:precedence</span> 30</span>)</span>
<span class="paren1">(<span class="nonparen"><i><span class="symbol">definfix</span></i> / <span class="keyword">:precedence</span> 29</span>)</span>
<span class="paren1">(<span class="nonparen"><i><span class="symbol">definfix</span></i> % <span class="keyword">:precedence</span> 28 <span class="keyword">:function-name</span> <a href="https://www.cliki.net/site/HyperSpec/Body/any_mod.html" class="symbol">mod</a></span>)</span>
<span class="paren1">(<span class="nonparen"><i><span class="symbol">definfix</span></i> <a href="https://www.cliki.net/site/HyperSpec/Body/any_pl.html" class="symbol">+</a> <span class="keyword">:precedence</span> 40</span>)</span>
<span class="paren1">(<span class="nonparen"><i><span class="symbol">definfix</span></i> <a href="https://www.cliki.net/site/HyperSpec/Body/any_-.html" class="symbol">-</a> <span class="keyword">:precedence</span> 40</span>)</span>
<span class="paren1">(<span class="nonparen"><i><span class="symbol">definfix</span></i> &lt;= <span class="keyword">:precedence</span> 60</span>)</span>
<span class="paren1">(<span class="nonparen"><i><span class="symbol">definfix</span></i> &lt; <span class="keyword">:precedence</span> 60</span>)</span>
<span class="paren1">(<span class="nonparen"><i><span class="symbol">definfix</span></i> &gt;= <span class="keyword">:precedence</span> 60</span>)</span>
<span class="paren1">(<span class="nonparen"><i><span class="symbol">definfix</span></i> &gt; <span class="keyword">:precedence</span> 60</span>)</span>
<span class="paren1">(<span class="nonparen"><i><span class="symbol">definfix</span></i> = <span class="keyword">:precedence</span> 70 <span class="keyword">:fungible</span> <a href="https://www.cliki.net/site/HyperSpec/Body/any_nil.html" class="symbol">nil</a></span>)</span>
<span class="paren1">(<span class="nonparen"><i><span class="symbol">definfix</span></i> /= <span class="keyword">:precedence</span> 70</span>)</span>
<span class="comment">;; 80-100 should be for the bitwise operators (&amp;, |, ^),
</span><span class="comment">;; once I figure out how CL handles bitops.
</span>
<span class="paren1">(<span class="nonparen"><i><span class="symbol">definfix</span></i> &amp;&amp; <span class="keyword">:precedence</span> 110 <span class="keyword">:function-name</span> <a href="https://www.cliki.net/site/HyperSpec/Body/any_and.html" class="symbol">and</a></span>)</span>
<span class="paren1">(<span class="nonparen"><i><span class="symbol">definfix</span></i> || <span class="keyword">:precedence</span> 120 <span class="keyword">:function-name</span> <a href="https://www.cliki.net/site/HyperSpec/Body/any_or.html" class="symbol">or</a></span>)</span>
<span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_set-dispa_ro-character.html" class="symbol">set-dispatch-macro-character</a>
<span class="character">#\#</span> <span class="character">#\n</span>
#'<span class="paren2">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_lambda.html" class="symbol"><i><span class="symbol">lambda</span></i></a> <span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/syscla_stream.html" class="symbol">stream</a> c1 c2</span>)</span>
<span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/sym_declare.html" class="symbol">declare</a> <span class="paren4">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/dec_ignorecm_ignorable.html" class="symbol">ignorable</a> c1 c2</span>)</span></span>)</span>
<span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/speope_letcm_letst.html" class="symbol"><i><span class="symbol">let</span></i></a> <span class="paren4">(<span class="nonparen"><span class="paren5">(<span class="nonparen">rd <span class="paren6">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_readcm_re_g-whitespace.html" class="symbol">read</a> <a href="https://www.cliki.net/site/HyperSpec/Body/syscla_stream.html" class="symbol">stream</a> <a href="https://www.cliki.net/site/HyperSpec/Body/any_t.html" class="symbol">t</a> <a href="https://www.cliki.net/site/HyperSpec/Body/any_nil.html" class="symbol">nil</a> <a href="https://www.cliki.net/site/HyperSpec/Body/any_t.html" class="symbol">t</a></span>)</span></span>)</span></span>)</span>
<span class="paren4">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/speope_if.html" class="symbol"><i><span class="symbol">if</span></i></a> <span class="paren5">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_listp.html" class="symbol">listp</a> rd</span>)</span>
`<span class="paren5">(<span class="nonparen">nfx ,@rd</span>)</span>
<span class="paren5">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/speope_progn.html" class="symbol"><i><span class="symbol">progn</span></i></a>
<span class="paren6">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_writecm_p_rintcm_princ.html" class="symbol">print</a> 'invalid-#n-usage</span>)</span>
<span class="paren6">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_writecm_p_rintcm_princ.html" class="symbol">print</a> rd</span>)</span>
<span class="paren6">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_error.html" class="symbol">error</a> '<a href="https://www.cliki.net/site/HyperSpec/Body/any_error.html" class="symbol">error</a></span>)</span> </span>)</span></span>)</span></span>)</span></span>)</span></span>)</span>
<span class="comment">;; (nfx 55 - 3 * 4 + 2000000) used to give -1999957
</span><span class="comment">;; instead of the correct result 2000043. This is now corrected. -- Bruno Daniel</span></span></div><p>The program is in the <a href="public&#32;domain.html" class="category">public domain</a>.<p><hr>
<a href="macro&#32;example.html" class="category">macro example</a></div></div>
<div id="footer" class="buttonbar"><ul><li><a href="Infix.html">Current version</a></li>
<li><a href="https://www.cliki.net/site/history?article=Infix">History</a></li>
<li><a href="https://www.cliki.net/site/backlinks?article=Infix">Backlinks</a></li><li><a href="https://www.cliki.net/site/edit-article?title=Infix&amp;from-revision=3801186274">Edit</a></li><li><a href="https://www.cliki.net/site/edit-article?create=t">Create</a></li></ul></div>
</div>
<div id="header-buttons" class="buttonbar">
<ul>
<li><a href="https://www.cliki.net/">Home</a></li>
<li><a href="https://www.cliki.net/site/recent-changes">Recent Changes</a></li>
<li><a href="CLiki.html">About</a></li>
<li><a href="Text&#32;Formatting.html">Text Formatting</a></li>
<li><a href="https://www.cliki.net/site/tools">Tools</a></li>
</ul>
<div id="search">
<form action="https://www.cliki.net/site/search">
<label for="search_query" class="hidden">Search CLiki</label>
<input type="text" name="query" id="search_query" value="" />
<input type="submit" value="search" />
</form>
</div>
</div>
<div id="pageheader">
<div id="header">
<span id="logo">CLiki</span>
<span id="slogan">the common lisp wiki</span>
<div id="login"><form method="post" action="https://www.cliki.net/site/login">
<label for="login_name" class="hidden">Account name</label>
<input type="text" name="name" id="login_name" class="login_input" />
<label for= "login_password" class="hidden">Password</label>
<input type="password" name="password" id="login_password" class="login_input" />
<input type="submit" name="login" value="login" id="login_submit" /><br />
<div id="register"><a href="https://www.cliki.net/site/register">register</a></div>
<input type="submit" name="reset-pw" value="reset password" id="reset_pw" />
</form>
</div>
</div>
</div>
</body></html>