82 lines
No EOL
12 KiB
HTML
82 lines
No EOL
12 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
|
<title>CLiki: COMPOSE</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=COMPOSE">
|
|
<link rel="stylesheet" href="static/css/style.css">
|
|
<link rel="stylesheet" href="static/css/colorize.css">
|
|
</head>
|
|
|
|
<body>
|
|
<span class="hidden">CLiki - COMPOSE</span>
|
|
<div id="content"><div id="content-area"><div id="article-title">COMPOSE</div><div id="article">This is one of the hypothetical <a href="Common Lisp Utilities.html" class="category">Common Lisp Utilities</a>.<p><i>Function</i> <b>COMPOSE</b><p><b>Syntax:</b><p><b>compose</b> <i><tt>&rest</tt> functions</i> => <i>composite-function</i><p><b>Arguments and Values:</b><p><i>functions</i>---a list of <i>designators</i> for <i>function</i>s.<p><i>composite-function</i>---a function created by composing <i>functions</i>.<p><b>Description:</b><p><b>compose</b> returns a <i>function</i> which is created by composing <i>functions</i> right-associatively.<p><b>Examples:</b><p><div class="code"><span class="nonparen"><span class="comment">;; Just to illustrate order of operations
|
|
</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> 2* <span class="paren2">(<span class="nonparen">x</span>)</span> <span class="paren2">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_st.html" class="symbol">*</a> 2 x</span>)</span></span>)</span>
|
|
|
|
<span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_funcall.html" class="symbol">funcall</a> <span class="paren2">(<span class="nonparen">compose #'<a href="https://www.cliki.net/site/HyperSpec/Body/fun_1plcm_1-.html" class="symbol">1+</a> #'<a href="https://www.cliki.net/site/HyperSpec/Body/fun_1plcm_1-.html" class="symbol">1+</a></span>)</span> 1</span>)</span> => 3
|
|
<span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_funcall.html" class="symbol">funcall</a> <span class="paren2">(<span class="nonparen">compose '<a href="https://www.cliki.net/site/HyperSpec/Body/fun_1plcm_1-.html" class="symbol">1+</a> '2*</span>)</span> 5</span>)</span> => 11
|
|
<span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_funcall.html" class="symbol">funcall</a> <span class="paren2">(<span class="nonparen">compose #'<a href="https://www.cliki.net/site/HyperSpec/Body/fun_1plcm_1-.html" class="symbol">1+</a> '2* '<a href="https://www.cliki.net/site/HyperSpec/Body/fun_1plcm_1-.html" class="symbol">1+</a></span>)</span> 6</span>)</span> => 15</span></div><p><b>Reference implementation:</b><p><div class="code"><span class="nonparen"><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> compose <span class="paren2">(<span class="nonparen">&rest functions</span>)</span>
|
|
<span class="string">"Compose FUNCTIONS right-associatively, returning a function"</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">x</span>)</span>
|
|
<span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_reduce.html" class="symbol">reduce</a> #'<a href="https://www.cliki.net/site/HyperSpec/Body/fun_funcall.html" class="symbol">funcall</a> functions
|
|
<span class="keyword">:initial-value</span> x
|
|
<span class="keyword">:from-end</span> <a href="https://www.cliki.net/site/HyperSpec/Body/any_t.html" class="symbol">t</a></span>)</span></span>)</span></span>)</span></span></div><p>This implementation is fairly straightforward, but very inefficient. In my benchmarks, I found it to be orders of magnitude slower than writing out an equivalent lambda function. However, a compiler macro speeds up some common cases immensely:<p><div class="code"><span class="nonparen"><span class="comment">;; Converts calls to COMPOSE to lambda forms with everything written
|
|
</span><span class="comment">;; out and some things written as direct function calls.
|
|
</span><span class="comment">;; Example: (compose #'1+ #'2* #'-) => (LAMBDA (X) (1+ (2* (- X))))
|
|
</span><span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/mac_define-compiler-macro.html" class="symbol"><i><span class="symbol">define-compiler-macro</span></i></a> compose <span class="paren2">(<span class="nonparen">&rest functions</span>)</span>
|
|
<span class="paren2">(<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="paren3">(<span class="nonparen"><span class="paren4">(<span class="nonparen">sharp-quoted-p <span class="paren5">(<span class="nonparen">x</span>)</span>
|
|
<span class="paren5">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_and.html" class="symbol">and</a> <span class="paren6">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_listp.html" class="symbol">listp</a> x</span>)</span>
|
|
<span class="paren6">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_eql.html" class="symbol">eql</a> <span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_firstcm_s_inthcm_tenth.html" class="symbol">first</a> x</span>)</span> '<a href="https://www.cliki.net/site/HyperSpec/Body/any_function.html" class="symbol"><i><span class="symbol">function</span></i></a></span>)</span>
|
|
<span class="paren6">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_symbolp.html" class="symbol">symbolp</a> <span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_firstcm_s_inthcm_tenth.html" class="symbol">second</a> x</span>)</span></span>)</span></span>)</span></span>)</span></span>)</span>
|
|
`<span class="paren3">(<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="paren4">(<span class="nonparen">x</span>)</span> ,<span class="paren4">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_reduce.html" class="symbol">reduce</a> #'<span class="paren5">(<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="paren6">(<span class="nonparen">fun arg</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">sharp-quoted-p fun</span>)</span>
|
|
<span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_list.html" class="symbol">list</a> <span class="paren2">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/acc_firstcm_s_inthcm_tenth.html" class="symbol">second</a> fun</span>)</span> arg</span>)</span>
|
|
<span class="paren1">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/any_list.html" class="symbol">list</a> '<a href="https://www.cliki.net/site/HyperSpec/Body/fun_funcall.html" class="symbol">funcall</a> fun arg</span>)</span></span>)</span></span>)</span>
|
|
functions
|
|
<span class="keyword">:initial-value</span> 'x
|
|
<span class="keyword">:from-end</span> <a href="https://www.cliki.net/site/HyperSpec/Body/any_t.html" class="symbol">t</a></span>)</span></span>)</span></span>)</span></span>)</span></span></div><p>This compiler macro shouldn't be considered part of the reference implementation, but it may be useful anyway. I, <a href="Peter Scott.html" class="internal">Peter Scott</a>, place this code in the <a href="public domain.html" class="category">public domain</a>.<p><hr><p>This version allows composition of functions with multiple arguments and return values.<p><div class="code"><span class="nonparen"><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> compose2 <span class="paren2">(<span class="nonparen">f1 f2</span>)</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">&rest args</span>)</span>
|
|
<span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/speope_multiple-value-call.html" class="symbol"><i><span class="symbol">multiple-value-call</span></i></a> f1 <span class="paren4">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_apply.html" class="symbol">apply</a> f2 args</span>)</span></span>)</span></span>)</span></span>)</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> compose <span class="paren2">(<span class="nonparen">&rest functions</span>)</span>
|
|
<span class="paren2">(<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> functions
|
|
<span class="paren3">(<span class="nonparen"><a href="https://www.cliki.net/site/HyperSpec/Body/fun_reduce.html" class="symbol">reduce</a> #'compose2 functions</span>)</span>
|
|
#'<a href="https://www.cliki.net/site/HyperSpec/Body/any_values.html" class="symbol">values</a></span>)</span></span>)</span></span></div><p><a href="Alexandria.html" class="category">Alexandria</a> contains this function. (likely nonexhaustive)</div></div>
|
|
<div id="footer" class="buttonbar"><ul><li><a href="COMPOSE.html">Current version</a></li>
|
|
<li><a href="https://www.cliki.net/site/history?article=COMPOSE">History</a></li>
|
|
<li><a href="https://www.cliki.net/site/backlinks?article=COMPOSE">Backlinks</a></li><li><a href="https://www.cliki.net/site/edit-article?title=COMPOSE&from-revision=3803579604">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 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> |