|
|
|
@@ -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 &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;">&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;">&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;">&key</span> b <span style="color: #268bd2;">&key</span> c <span style="color: #268bd2;">&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;">&key</span> b c <span style="color: #268bd2;">&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;">&key</span> b c <span style="color: #268bd2;">&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;">&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;">&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;">&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;">&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"><lambda list> -> <positional argument>* |
|
|
|
[:keys ( <keyword arguments> [:defaults-to <value>])*] |
|
|
|
[(:rest <rest argument>)|(:body <body argument>)] |
|
|
|
</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> |
|
|
|
|
|
|
|
>> <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 |
|
|
|
|
|
|
|
|
|
|
|
>> <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> |
|
|
|
>> <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> |
|
|
|
>> 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">>> <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">>> <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> |
|
|
|
>> <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"> </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> |