Can now parse lambda lists

This commit is contained in:
FelixBrendel
2018-10-15 00:46:09 +02:00
parent 2006e3b45c
commit f6c2219bd5
15 changed files with 1013 additions and 48 deletions
+539
View File
@@ -0,0 +1,539 @@
<!doctype html>
<html lang="en">
<head>
<title></title>
<!-- 2018-10-14 So 16:55 -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="generator" content="Org-mode">
<meta name="author" content="Felix Brendel">
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.5/js/bootstrap.min.js"></script>
<style type="text/css">
/* org mode styles on top of twbs */
html {
position: relative;
min-height: 100%;
}
body {
font-size: 18px;
margin-bottom: 105px;
}
footer {
position: absolute;
bottom: 0;
width: 100%;
height: 101px;
background-color: #f5f5f5;
}
footer > div {
padding: 10px;
}
footer p {
margin: 0 0 5px;
text-align: center;
font-size: 16px;
}
#table-of-contents {
margin-top: 20px;
margin-bottom: 20px;
}
blockquote p {
font-size: 18px;
}
pre {
font-size: 16px;
}
.footpara {
display: inline-block;
}
figcaption {
font-size: 16px;
color: #666;
font-style: italic;
padding-bottom: 15px;
}
/* from twbs docs */
.bs-docs-sidebar.affix {
position: static;
}
@media (min-width: 768px) {
.bs-docs-sidebar {
padding-left: 20px;
}
}
/* All levels of nav */
.bs-docs-sidebar .nav > li > a {
display: block;
padding: 4px 20px;
font-size: 14px;
font-weight: 500;
color: #999;
}
.bs-docs-sidebar .nav > li > a:hover,
.bs-docs-sidebar .nav > li > a:focus {
padding-left: 19px;
color: #A1283B;
text-decoration: none;
background-color: transparent;
border-left: 1px solid #A1283B;
}
.bs-docs-sidebar .nav > .active > a,
.bs-docs-sidebar .nav > .active:hover > a,
.bs-docs-sidebar .nav > .active:focus > a {
padding-left: 18px;
font-weight: bold;
color: #A1283B;
background-color: transparent;
border-left: 2px solid #A1283B;
}
/* Nav: second level (shown on .active) */
.bs-docs-sidebar .nav .nav {
display: none; /* Hide by default, but at >768px, show it */
padding-bottom: 10px;
}
.bs-docs-sidebar .nav .nav > li > a {
padding-top: 1px;
padding-bottom: 1px;
padding-left: 30px;
font-size: 12px;
font-weight: normal;
}
.bs-docs-sidebar .nav .nav > li > a:hover,
.bs-docs-sidebar .nav .nav > li > a:focus {
padding-left: 29px;
}
.bs-docs-sidebar .nav .nav > .active > a,
.bs-docs-sidebar .nav .nav > .active:hover > a,
.bs-docs-sidebar .nav .nav > .active:focus > a {
padding-left: 28px;
font-weight: 500;
}
/* Nav: third level (shown on .active) */
.bs-docs-sidebar .nav .nav .nav {
padding-bottom: 10px;
}
.bs-docs-sidebar .nav .nav .nav > li > a {
padding-top: 1px;
padding-bottom: 1px;
padding-left: 40px;
font-size: 12px;
font-weight: normal;
}
.bs-docs-sidebar .nav .nav .nav > li > a:hover,
.bs-docs-sidebar .nav .nav .nav > li > a:focus {
padding-left: 39px;
}
.bs-docs-sidebar .nav .nav .nav > .active > a,
.bs-docs-sidebar .nav .nav .nav > .active:hover > a,
.bs-docs-sidebar .nav .nav .nav > .active:focus > a {
padding-left: 38px;
font-weight: 500;
}
/* Show and affix the side nav when space allows it */
@media (min-width: 992px) {
.bs-docs-sidebar .nav > .active > ul {
display: block;
}
/* Widen the fixed sidebar */
.bs-docs-sidebar.affix,
.bs-docs-sidebar.affix-bottom {
width: 213px;
}
.bs-docs-sidebar.affix {
position: fixed; /* Undo the static from mobile first approach */
top: 20px;
}
.bs-docs-sidebar.affix-bottom {
position: absolute; /* Undo the static from mobile first approach */
}
.bs-docs-sidebar.affix .bs-docs-sidenav,.bs-docs-sidebar.affix-bottom .bs-docs-sidenav {
margin-top: 0;
margin-bottom: 0
}
}
@media (min-width: 1200px) {
/* Widen the fixed sidebar again */
.bs-docs-sidebar.affix-bottom,
.bs-docs-sidebar.affix {
width: 263px;
}
}
</style>
<script type="text/javascript">
$(function() {
'use strict';
$('.bs-docs-sidebar li').first().addClass('active');
$(document.body).scrollspy({target: '.bs-docs-sidebar'});
$('.bs-docs-sidebar').affix();
});
</script>
</head>
<body>
<div id="content" class="container">
<div class="row"><div class="col-md-9"><h1 class="title"></h1>
<div id="outline-container-sec-1" class="outline-2">
<h2 id="sec-1"><span class="section-number-2">1</span> Arguments</h2>
<div class="outline-text-2" id="text-1">
<p>
In Emacs lisp, keyword arguments must be passed in the same order as they were
defined in, so <code>((lambda (a &amp;key b c) (+ a b c)) 1 3 :b 2)</code> will preduce an
error, because <code>b</code> was passed as last argument but was defined as second argument.
</p>
<div class="org-src-container">
<pre class="src src-emacs-lisp"><span style="color: #839496;">(</span><span style="color: #2aa198;">(</span><span style="color: #859900;">lambda</span> <span style="color: #b58900;">(</span>a b<span style="color: #b58900;">)</span> <span style="color: #b58900;">(</span>+ a b<span style="color: #b58900;">)</span><span style="color: #2aa198;">)</span> 1 2<span style="color: #839496;">)</span> <span style="color: #49974A; font-style: italic;">;; </span><span style="color: #49974A; font-style: italic;">3</span>
<span style="color: #839496;">(</span><span style="color: #2aa198;">(</span><span style="color: #859900;">lambda</span> <span style="color: #b58900;">(</span>a <span style="color: #268bd2;">&amp;key</span> b<span style="color: #b58900;">)</span> <span style="color: #b58900;">(</span>+ a b<span style="color: #b58900;">)</span><span style="color: #2aa198;">)</span> 1 <span style="color: #6c71c4;">:b</span> 2<span style="color: #839496;">)</span> <span style="color: #49974A; font-style: italic;">;; </span><span style="color: #49974A; font-style: italic;">3</span>
<span style="color: #839496;">(</span><span style="color: #2aa198;">(</span><span style="color: #859900;">lambda</span> <span style="color: #b58900;">(</span>a <span style="color: #268bd2;">&amp;key</span> b<span style="color: #b58900;">)</span> <span style="color: #b58900;">(</span>+ a b<span style="color: #b58900;">)</span><span style="color: #2aa198;">)</span> <span style="color: #6c71c4;">:b</span> 2 1<span style="color: #839496;">)</span> <span style="color: #49974A; font-style: italic;">;; </span><span style="color: #49974A; font-style: italic;">error</span>
</pre>
</div>
<p>
But if mulitiple keyword arguments are defined, their ordering does not matter.
</p>
<div class="org-src-container">
<pre class="src src-emacs-lisp"><span style="color: #839496;">(</span><span style="color: #2aa198;">(</span><span style="color: #859900;">lambda</span> <span style="color: #b58900;">(</span>a <span style="color: #268bd2;">&amp;key</span> b <span style="color: #268bd2;">&amp;key</span> c <span style="color: #268bd2;">&amp;key</span> d<span style="color: #b58900;">)</span> <span style="color: #b58900;">(</span>+ a b c d<span style="color: #b58900;">)</span><span style="color: #2aa198;">)</span> 1 <span style="color: #6c71c4;">:d</span> 4 <span style="color: #6c71c4;">:c</span> 3 <span style="color: #6c71c4;">:b</span> 2<span style="color: #839496;">)</span> <span style="color: #49974A; font-style: italic;">;; </span><span style="color: #49974A; font-style: italic;">10</span>
</pre>
</div>
<p>
It is even possible to have a non keyword argument bewtween keyword arguments
and when calling, switch the order.
</p>
<div class="org-src-container">
<pre class="src src-emacs-lisp"><span style="color: #839496;">(</span><span style="color: #2aa198;">(</span><span style="color: #859900;">lambda</span> <span style="color: #b58900;">(</span>a <span style="color: #268bd2;">&amp;key</span> b c <span style="color: #268bd2;">&amp;key</span> d<span style="color: #b58900;">)</span> <span style="color: #b58900;">(</span>+ a b c d<span style="color: #b58900;">)</span><span style="color: #2aa198;">)</span> 1 <span style="color: #6c71c4;">:d</span> 4 3 <span style="color: #6c71c4;">:b</span> 2<span style="color: #839496;">)</span> <span style="color: #49974A; font-style: italic;">;; </span><span style="color: #49974A; font-style: italic;">10</span>
<span style="color: #839496;">(</span><span style="color: #2aa198;">(</span><span style="color: #859900;">lambda</span> <span style="color: #b58900;">(</span>a <span style="color: #268bd2;">&amp;key</span> b c <span style="color: #268bd2;">&amp;key</span> d<span style="color: #b58900;">)</span> <span style="color: #b58900;">(</span>+ a b c d<span style="color: #b58900;">)</span><span style="color: #2aa198;">)</span> 1 <span style="color: #6c71c4;">:d</span> 4 <span style="color: #6c71c4;">:b</span> 2 3<span style="color: #839496;">)</span> <span style="color: #49974A; font-style: italic;">;; </span><span style="color: #49974A; font-style: italic;">error</span>
</pre>
</div>
<p>
However somehow it is not possible to flip the ordering at the first argument
</p>
<div class="org-src-container">
<pre class="src src-emacs-lisp"><span style="color: #839496;">(</span><span style="color: #2aa198;">(</span><span style="color: #859900;">lambda</span> <span style="color: #b58900;">(</span>a <span style="color: #268bd2;">&amp;key</span> b<span style="color: #b58900;">)</span> <span style="color: #b58900;">(</span>+ a b<span style="color: #b58900;">)</span><span style="color: #2aa198;">)</span> 2 <span style="color: #6c71c4;">:b</span> 1<span style="color: #839496;">)</span> <span style="color: #49974A; font-style: italic;">;; </span><span style="color: #49974A; font-style: italic;">3</span>
<span style="color: #839496;">(</span><span style="color: #2aa198;">(</span><span style="color: #859900;">lambda</span> <span style="color: #b58900;">(</span>a <span style="color: #268bd2;">&amp;key</span> b<span style="color: #b58900;">)</span> <span style="color: #b58900;">(</span>+ a b<span style="color: #b58900;">)</span><span style="color: #2aa198;">)</span> <span style="color: #6c71c4;">:b</span> 2 1<span style="color: #839496;">)</span> <span style="color: #49974A; font-style: italic;">;; </span><span style="color: #49974A; font-style: italic;">error</span>
<span style="color: #839496;">(</span><span style="color: #2aa198;">(</span><span style="color: #859900;">lambda</span> <span style="color: #b58900;">(</span><span style="color: #268bd2;">&amp;key</span> a b<span style="color: #b58900;">)</span> <span style="color: #b58900;">(</span>+ a b<span style="color: #b58900;">)</span><span style="color: #2aa198;">)</span> <span style="color: #6c71c4;">:a</span> 2 1<span style="color: #839496;">)</span> <span style="color: #49974A; font-style: italic;">;; </span><span style="color: #49974A; font-style: italic;">3</span>
<span style="color: #839496;">(</span><span style="color: #2aa198;">(</span><span style="color: #859900;">lambda</span> <span style="color: #b58900;">(</span><span style="color: #268bd2;">&amp;key</span> a b<span style="color: #b58900;">)</span> <span style="color: #b58900;">(</span>+ a b<span style="color: #b58900;">)</span><span style="color: #2aa198;">)</span> 1 <span style="color: #6c71c4;">:a</span> 2<span style="color: #839496;">)</span> <span style="color: #49974A; font-style: italic;">;; </span><span style="color: #49974A; font-style: italic;">error</span>
</pre>
</div>
<p>
So it seems, positional arguments have to be at the exact position they were
defined in, but keyword arguments can appear in any order, but at the places
where keyword arguments have been defined.
</p>
</div>
<div id="outline-container-sec-1-1" class="outline-3">
<h3 id="sec-1-1"><span class="section-number-3">1.1</span> Idea</h3>
<div class="outline-text-3" id="text-1-1">
<p>
Every argument can be set using keys, but keyword arguments always come strictly
after positional arguments
</p>
<div class="org-src-container">
<pre class="src src-emacs-lisp"><span style="color: #839496;">(</span><span style="color: #2aa198;">(</span><span style="color: #859900;">lambda</span> <span style="color: #b58900;">(</span>a b c d<span style="color: #b58900;">)</span><span style="color: #2aa198;">)</span> 1 2 3 4<span style="color: #839496;">)</span> <span style="color: #49974A; font-style: italic;">;; </span><span style="color: #49974A; font-style: italic;">ok</span>
<span style="color: #839496;">(</span><span style="color: #2aa198;">(</span><span style="color: #859900;">lambda</span> <span style="color: #b58900;">(</span>a b c d<span style="color: #b58900;">)</span><span style="color: #2aa198;">)</span> 1 2 <span style="color: #6c71c4;">:c</span> 2 <span style="color: #6c71c4;">:d</span> 1<span style="color: #839496;">)</span> <span style="color: #49974A; font-style: italic;">;; </span><span style="color: #49974A; font-style: italic;">ok</span>
<span style="color: #839496;">(</span><span style="color: #2aa198;">(</span><span style="color: #859900;">lambda</span> <span style="color: #b58900;">(</span>a b c d<span style="color: #b58900;">)</span><span style="color: #2aa198;">)</span> 1 2 <span style="color: #6c71c4;">:d</span> 1 <span style="color: #6c71c4;">:c</span> 2<span style="color: #839496;">)</span> <span style="color: #49974A; font-style: italic;">;; </span><span style="color: #49974A; font-style: italic;">ok</span>
<span style="color: #839496;">(</span><span style="color: #2aa198;">(</span><span style="color: #859900;">lambda</span> <span style="color: #b58900;">(</span>a b c d<span style="color: #b58900;">)</span><span style="color: #2aa198;">)</span> <span style="color: #6c71c4;">:d</span> 1 1 2 <span style="color: #6c71c4;">:c</span> 2<span style="color: #839496;">)</span> <span style="color: #49974A; font-style: italic;">;; </span><span style="color: #49974A; font-style: italic;">error, keyword arguments must come last</span>
<span style="color: #839496;">(</span><span style="color: #2aa198;">(</span><span style="color: #859900;">lambda</span> <span style="color: #b58900;">(</span>a b c d<span style="color: #b58900;">)</span><span style="color: #2aa198;">)</span> 1 2 <span style="color: #6c71c4;">:c</span> 2 <span style="color: #6c71c4;">:d</span> 1 <span style="color: #6c71c4;">:a</span> 2<span style="color: #839496;">)</span> <span style="color: #49974A; font-style: italic;">;; </span><span style="color: #49974A; font-style: italic;">error, 'a' was passed two times</span>
<span style="color: #839496;">(</span><span style="color: #2aa198;">(</span><span style="color: #859900;">lambda</span> <span style="color: #b58900;">(</span>a b c d<span style="color: #b58900;">)</span><span style="color: #2aa198;">)</span> 1 2 <span style="color: #6c71c4;">:d</span> 1<span style="color: #839496;">)</span> <span style="color: #49974A; font-style: italic;">;; </span><span style="color: #49974A; font-style: italic;">error, c was not passed, but does not have a default value</span>
<span style="color: #839496;">(</span><span style="color: #2aa198;">(</span><span style="color: #859900;">lambda</span> <span style="color: #b58900;">(</span>a b c <span style="color: #6c71c4;">:default</span> 10 d<span style="color: #b58900;">)</span><span style="color: #2aa198;">)</span> 1 2 <span style="color: #6c71c4;">:d</span> 1<span style="color: #839496;">)</span> <span style="color: #49974A; font-style: italic;">;; </span><span style="color: #49974A; font-style: italic;">okay again</span>
</pre>
</div>
<p>
The drawback then is that you can never pass a keyword as a positional argument,
because it will always try to assign the next argument to the variable defined
by the keyword. You could still pass it as a keyword argument though. This is
especially annoying because we want to use keywords as type identifiers.
</p>
<div class="org-src-container">
<pre class="src src-emacs-lisp"><span style="color: #839496;">(</span>= <span style="color: #2aa198;">(</span>type <span style="color: #2aa198;">"hello"</span><span style="color: #2aa198;">)</span> <span style="color: #6c71c4;">:string</span><span style="color: #839496;">)</span>
</pre>
</div>
<div class="org-src-container">
<pre class="src src-emacs-lisp"><span style="color: #839496;">(</span><span style="color: #2aa198;">(</span><span style="color: #859900;">lambda</span> <span style="color: #b58900;">(</span>i-wanna-get-a-kw<span style="color: #b58900;">)</span><span style="color: #2aa198;">)</span> <span style="color: #6c71c4;">:hey</span><span style="color: #839496;">)</span> <span style="color: #49974A; font-style: italic;">;; </span><span style="color: #49974A; font-style: italic;">error, unmatched value for keyword argument</span>
<span style="color: #839496;">(</span><span style="color: #2aa198;">(</span><span style="color: #859900;">lambda</span> <span style="color: #b58900;">(</span>i-wanna-get-a-kw<span style="color: #b58900;">)</span><span style="color: #2aa198;">)</span> <span style="color: #6c71c4;">:i-wanna-get-a-kw</span> <span style="color: #6c71c4;">:hey</span><span style="color: #839496;">)</span> <span style="color: #49974A; font-style: italic;">;; </span><span style="color: #49974A; font-style: italic;">this would work again</span>
</pre>
</div>
<p>
Other Idea is to mark the place in the parameter list where keyword argumetns
start and arguments before that are positional and will not be stuffed into
key-value pairs and arguments after that will be keyword arguments
</p>
<div class="org-src-container">
<pre class="src src-ebnf">&lt;lambda list&gt; -&gt; &lt;positional argument&gt;*
[:keys ( &lt;keyword arguments&gt; [:defaults-to &lt;value&gt;])*]
[(:rest &lt;rest argument&gt;)|(:body &lt;body argument&gt;)]
</pre>
</div>
<div class="org-src-container">
<pre class="src src-emacs-lisp"> <span style="color: #839496;">(</span>= <span style="color: #2aa198;">(</span>type <span style="color: #2aa198;">"hello"</span><span style="color: #2aa198;">)</span> <span style="color: #6c71c4;">:string</span><span style="color: #839496;">)</span> <span style="color: #49974A; font-style: italic;">;; </span><span style="color: #49974A; font-style: italic;">this will work again because (=) does</span>
<span style="color: #49974A; font-style: italic;">;; </span><span style="color: #49974A; font-style: italic;">not use keyword arguments</span>
<span style="color: #839496;">(</span><span style="color: #2aa198;">(</span><span style="color: #859900;">lambda</span> <span style="color: #b58900;">(</span>i-wanna-get-a-kw<span style="color: #b58900;">)</span><span style="color: #2aa198;">)</span> <span style="color: #6c71c4;">:hey</span><span style="color: #839496;">)</span> <span style="color: #49974A; font-style: italic;">;; </span><span style="color: #49974A; font-style: italic;">would work because of the same reason</span>
<span style="color: #839496;">(</span>define fun
<span style="color: #2aa198;">(</span><span style="color: #859900;">lambda</span> <span style="color: #b58900;">(</span><span style="color: #6c71c4;">:keys</span> a b c d<span style="color: #b58900;">)</span>
<span style="color: #b58900;">(</span>+ a b c d<span style="color: #b58900;">)</span><span style="color: #2aa198;">)</span><span style="color: #839496;">)</span>
<span style="color: #839496;">(</span>fun 1 2 3 4<span style="color: #839496;">)</span> <span style="color: #49974A; font-style: italic;">;; </span><span style="color: #49974A; font-style: italic;">okay</span>
<span style="color: #839496;">(</span>fun 1 2 <span style="color: #6c71c4;">:d</span> 3 <span style="color: #6c71c4;">:c</span> 4<span style="color: #839496;">)</span> <span style="color: #49974A; font-style: italic;">;; </span><span style="color: #49974A; font-style: italic;">okay</span>
<span style="color: #839496;">(</span>fun 1 2 <span style="color: #6c71c4;">:d</span> 3 <span style="color: #6c71c4;">:c</span> 4 <span style="color: #6c71c4;">:a</span> 2<span style="color: #839496;">)</span> <span style="color: #49974A; font-style: italic;">;; </span><span style="color: #49974A; font-style: italic;">error, 'a' was passed two times</span>
<span style="color: #839496;">(</span>fun <span style="color: #6c71c4;">:c</span> 1 <span style="color: #6c71c4;">:b</span> 2 <span style="color: #6c71c4;">:d</span> 3 <span style="color: #6c71c4;">:a</span> 4<span style="color: #839496;">)</span> <span style="color: #49974A; font-style: italic;">;; </span><span style="color: #49974A; font-style: italic;">okay</span>
<span style="color: #839496;">(</span>fun <span style="color: #6c71c4;">:c</span> 1 <span style="color: #6c71c4;">:b</span> 2 <span style="color: #6c71c4;">:d</span> 3 4<span style="color: #839496;">)</span> <span style="color: #49974A; font-style: italic;">;; </span><span style="color: #49974A; font-style: italic;">error, positional argument after keyword</span>
<span style="color: #49974A; font-style: italic;">;; </span><span style="color: #49974A; font-style: italic;">and fun does not accept rest parameter</span>
<span style="color: #839496;">(</span>define fun2
<span style="color: #2aa198;">(</span><span style="color: #859900;">lambda</span> <span style="color: #b58900;">(</span><span style="color: #6c71c4;">:quoted</span> op a b <span style="color: #6c71c4;">:keys</span> c d <span style="color: #6c71c4;">:rest</span> r<span style="color: #b58900;">)</span>
<span style="color: #b58900;">(</span>print r<span style="color: #b58900;">)</span>
<span style="color: #b58900;">(</span>op a b c d<span style="color: #b58900;">)</span><span style="color: #2aa198;">)</span><span style="color: #839496;">)</span>
&gt;&gt; <span style="color: #839496;">(</span>fun2 * 1 2 <span style="color: #6c71c4;">:c</span> 3 <span style="color: #6c71c4;">:d</span> 4 <span style="color: #2aa198;">"this"</span> <span style="color: #2aa198;">"can"</span> <span style="color: #6c71c4;">:be</span> <span style="color: #2aa198;">"whatever"</span><span style="color: #839496;">)</span>
<span style="color: #839496;">(</span><span style="color: #2aa198;">"this"</span> <span style="color: #2aa198;">"can"</span> <span style="color: #6c71c4;">:be</span> <span style="color: #2aa198;">"whatever"</span><span style="color: #839496;">)</span>
24
&gt;&gt; <span style="color: #839496;">(</span>define print-before-eval <span style="color: #2aa198;">(</span><span style="color: #859900;">lambda</span> <span style="color: #b58900;">(</span><span style="color: #6c71c4;">:body</span> expr<span style="color: #b58900;">)</span>
<span style="color: #b58900;">(</span>print expr<span style="color: #b58900;">)</span>
<span style="color: #b58900;">(</span>eval expr<span style="color: #b58900;">)</span><span style="color: #2aa198;">)</span><span style="color: #839496;">)</span>
&gt;&gt; <span style="color: #839496;">(</span>define r <span style="color: #2aa198;">(</span>print-before-eval <span style="color: #b58900;">(</span>+ 1 2 3<span style="color: #b58900;">)</span><span style="color: #2aa198;">)</span><span style="color: #839496;">)</span>
<span style="color: #839496;">(</span>+ 1 2 3<span style="color: #839496;">)</span>
&gt;&gt; r
6
</pre>
</div>
<p>
Wait this does not work either because you won't be able to pass keywords into
rest.
</p>
<p>
<b>Unrealated Idea: Distinguish between functions and macros</b>
</p>
<p>
The difference is really simple:
</p>
<dl class="org-dl">
<dt> Function </dt><dd>like a lambda, but no argument is automatically quoted
</dd>
<dt> Macro </dt><dd>like a lambda, but every argument is automatically quoted
</dd>
</dl>
<p>
This is important, because a macro should not introduce a new environment, but
use the one it lives in.
</p>
<div class="org-src-container">
<pre class="src src-emacs-lisp">&gt;&gt; <span style="color: #839496;">(</span>define print-before-eval <span style="color: #2aa198;">(</span>macro <span style="color: #b58900;">(</span><span style="color: #6c71c4;">:rest</span> expr<span style="color: #b58900;">)</span>
<span style="color: #b58900;">(</span>print expr<span style="color: #b58900;">)</span>
<span style="color: #b58900;">(</span>eval expr<span style="color: #b58900;">)</span><span style="color: #2aa198;">)</span>
</pre>
</div>
</div>
</div>
<div id="outline-container-sec-1-2" class="outline-3">
<h3 id="sec-1-2"><span class="section-number-3">1.2</span> the actual problem</h3>
<div class="outline-text-3" id="text-1-2">
<p>
We have some requirements to the arguments:
</p>
<ul class="org-ul">
<li>positional arguments (always required, no default value)
</li>
<li>keyword arguments (always come after positionals), can be not passed if there
is a default value
</li>
<li>We want to be able to have a rest paramter, where everything is dumped in to
that exceeds the other parameters
</li>
</ul>
<p>
<b>The problem is, we have no way of knowing if the current keyword we are
reading is still part of the keyword block or part of the rest paramter.</b>
</p>
<p>
Consider:
</p>
<div class="org-src-container">
<pre class="src src-emacs-lisp">&gt;&gt; <span style="color: #839496;">(</span>define fun <span style="color: #2aa198;">(</span><span style="color: #859900;">lambda</span> <span style="color: #b58900;">(</span>a b <span style="color: #6c71c4;">:key</span> c d <span style="color: #6c71c4;">:defaults-to</span> 4 <span style="color: #6c71c4;">:rest</span><span style="color: #b58900;">)</span> nil<span style="color: #2aa198;">)</span><span style="color: #839496;">)</span>
&gt;&gt; <span style="color: #839496;">(</span>fun 1 2 <span style="color: #6c71c4;">:c</span> 3 <span style="color: #6c71c4;">:d</span> 5<span style="color: #839496;">)</span>
</pre>
</div>
<p>
What should this be evaluated to?
</p>
<table class="table table-striped table-bordered table-hover table-condensed">
<colgroup>
<col class="left">
<col class="right">
<col class="right">
<col class="right">
<col class="right">
<col class="left">
</colgroup>
<thead>
<tr>
<th scope="col" class="text-left">&#xa0;</th>
<th scope="col" class="text-right">a</th>
<th scope="col" class="text-right">b</th>
<th scope="col" class="text-right">c</th>
<th scope="col" class="text-right">d</th>
<th scope="col" class="text-left">rest</th>
</tr>
</thead>
<tbody>
<tr>
<td class="text-left">v1</td>
<td class="text-right">1</td>
<td class="text-right">2</td>
<td class="text-right">3</td>
<td class="text-right">5</td>
<td class="text-left">nil</td>
</tr>
<tr>
<td class="text-left">v2</td>
<td class="text-right">1</td>
<td class="text-right">2</td>
<td class="text-right">3</td>
<td class="text-right">4</td>
<td class="text-left">(:d 5)</td>
</tr>
</tbody>
</table>
<p>
It is ambiguous. It is however important to note that this can only happen when
there are optinal keyword arguments (keyword arguments with default values).
Otherwise we could always know which variables are set and wich have not been
set to see if we are in an errornious state.
</p>
</div>
</div>
<div id="outline-container-sec-1-3" class="outline-3">
<h3 id="sec-1-3"><span class="section-number-3">1.3</span> Solution</h3>
<div class="outline-text-3" id="text-1-3">
<p>
We can resolve that problem by always making the the decision of chosing <code>v1</code>
between <code>v1</code> and <code>v1</code>. This means, when we are expecting to read kwargs, and we
encounter an kwarg, try to apply it (this can fail, for two reasons:
</p>
<ol class="org-ol">
<li>The keyword has no following value
</li>
<li>The keyword is not a keyword argument in the funciton
</li>
</ol>
<p>
), if it fails treat it as part of the rest arguments, and read all the
following arguments into the rest arguments, or if it works, use it as the
keyword argument.
</p>
</div>
</div>
<div id="outline-container-sec-1-4" class="outline-3">
<h3 id="sec-1-4"><span class="section-number-3">1.4</span> Implementation</h3>
<div class="outline-text-3" id="text-1-4">
<div class="org-src-container">
<pre class="src src-c"><span style="color: #859900;">typedef</span> <span style="color: #859900;">struct</span> <span style="color: #839496;">{</span>
<span style="color: #268bd2;">char</span>* <span style="color: #6c71c4;">docstring</span>;
<span style="color: #268bd2;">char</span>** <span style="color: #6c71c4;">positional_arguments</span>;
<span style="color: #859900;">struct</span> <span style="color: #2aa198;">{</span>
<span style="color: #268bd2;">char</span>* <span style="color: #6c71c4;">identifier</span>;
<span style="color: #268bd2;">Ast_node</span>* <span style="color: #6c71c4;">default_value</span>; <span style="color: #49974A; font-style: italic;">// </span><span style="color: #49974A; font-style: italic;">will be nullptr if no defalut value was declared</span>
<span style="color: #2aa198;">}</span>* <span style="color: #6c71c4;">keyword_arguments</span>;
<span style="color: #268bd2;">char</span>* <span style="color: #6c71c4;">rest_argument</span>; <span style="color: #49974A; font-style: italic;">// </span><span style="color: #49974A; font-style: italic;">will be nullptr if no rest argument is declared</span>
<span style="color: #268bd2;">Ast_Node_array_list</span> <span style="color: #6c71c4;">body</span>;
<span style="color: #839496;">}</span> <span style="color: #268bd2;">lambda</span>;
</pre>
</div>
</div>
</div>
</div>
</div><div class="col-md-3"><nav id="table-of-contents">
<div id="text-table-of-contents" class="bs-docs-sidebar">
<ul class="nav">
<li><a href="#sec-1">1. Arguments</a>
<ul class="nav">
<li><a href="#sec-1-1">1.1. Idea</a></li>
<li><a href="#sec-1-2">1.2. the actual problem</a></li>
<li><a href="#sec-1-3">1.3. Solution</a></li>
<li><a href="#sec-1-4">1.4. Implementation</a></li>
</ul>
</li>
</ul>
</div>
</nav>
</div></div></div>
<footer id="postamble" class="">
<div><p class="author">Author: Felix Brendel</p>
<p class="date">Created: 2018-10-14 So 16:55</p>
<p class="creator"><a href="http://www.gnu.org/software/emacs/">Emacs</a> 26.0.91 (<a href="http://orgmode.org">Org-mode</a> 9.1.13)</p>
</div>
</footer>
</body>
</html>