<div dir="ltr"><div>Ughh, my bad, let me withdraw this idea:</div><div><br></div><div><pre style="box-sizing:border-box;font-family:SFMono-Regular,Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:11.9px;margin-top:0px;margin-bottom:0px;font-stretch:normal;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(246,248,250);border-radius:3px;word-break:normal;color:rgb(36,41,46)"><span class="gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">func</span> <span class="gmail-pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">saveAndRestore</span><<span class="gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">T</span>, <span class="gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">R</span>>(<span class="gmail-pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">_</span> <span class="gmail-pl-smi" style="box-sizing:border-box">variable</span>: <span class="gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">inout</span> T, <span class="gmail-pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">_</span> <span class="gmail-pl-smi" style="box-sizing:border-box">tmpVal</span>: T, <span class="gmail-pl-smi" style="box-sizing:border-box"><span class="gmail-pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">body</span></span>: () <span class="gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">-></span> R) <span class="gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">-></span> R {
<span class="gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">let</span> savedVal <span class="gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">=</span> variable
variable <span class="gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">=</span> tmpVal
<span class="gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">defer</span> { variable <span class="gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">=</span> savedVal }
<span class="gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">return</span> <span class="gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">body</span>()
}
<span class="gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">var</span> contextVal<span class="gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">:</span> <span class="gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">Int</span> <span class="gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">=</span> <span class="gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">0</span>
<span class="gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">saveAndRestore</span>(<span class="gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">&</span>contextVal, <span class="gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">1</span>) {
<span class="gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">print</span>(contextVal)
}</pre></div><div><br></div><div>I don't think this is guaranteed to work.</div><div><br></div><div><br></div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">2017-07-03 11:48 GMT+09:00 rintaro ishizaki via swift-evolution <span dir="ltr"><<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote"><span class="">2017-07-03 11:23 GMT+09:00 rintaro ishizaki via swift-evolution <span dir="ltr"><<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>></span>:<br></span><div><div class="h5"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote"><span class="m_6068872179046533889gmail-">2017-06-28 21:33 GMT+09:00 Dimitri Racordon via swift-evolution <span dir="ltr"><<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>></span>:<br></span><span class="m_6068872179046533889gmail-"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div style="word-wrap:break-word">
<div>Hello community!</div>
<div><br>
</div>
<div>I’d like to pitch an idea for a user-friendly way for functions to pull values from an arbitrary environment. Let me introduce the concept with a motivational example before I dig into dirty syntax and semantics. Note that I intentionally removed
many pieces of code from my examples, but I guess everybody will be able to understand the context.<br>
<br>
Say you are writing a visitor (with the pattern of the same name) for an AST to implement an interpreter:<br>
<br>
</div>
<div><span style="font-variant-ligatures:no-common-ligatures">
<div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo">
<span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">class</span><span style="font-variant-ligatures:no-common-ligatures"> Interpreter: </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(112,61,170)">Visitor</span><span style="font-variant-ligatures:no-common-ligatures"> {</span></div>
<div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo">
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)"> func</span><span style="font-variant-ligatures:no-common-ligatures"> visit(</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">_</span><span style="font-variant-ligatures:no-common-ligatures"> node: </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(112,61,170)">BinExpr</span><span style="font-variant-ligatures:no-common-ligatures">)
{ </span><span style="color:rgb(0,132,0)">/* ... */ </span>}</div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)"> func</span><span style="font-variant-ligatures:no-common-ligatures"> visit(</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">_</span><span style="font-variant-ligatures:no-common-ligatures"> node: </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(112,61,170)">Literal</span><span style="font-variant-ligatures:no-common-ligatures">)
{ </span><span style="color:rgb(0,132,0)">/* ... */ </span>}</div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)"> func</span><span style="font-variant-ligatures:no-common-ligatures"> visit(</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">_</span><span style="font-variant-ligatures:no-common-ligatures"> node: </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(112,61,170)">Scope</span><span style="font-variant-ligatures:no-common-ligatures">)
{ </span><span style="color:rgb(0,132,0)">/* ... */ </span>}</div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)"> func</span><span style="font-variant-ligatures:no-common-ligatures"> visit(</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">_</span><span style="font-variant-ligatures:no-common-ligatures"> node: </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(112,61,170)">Identifier</span><span style="font-variant-ligatures:no-common-ligatures">)
{ </span><span style="color:rgb(0,132,0)">/* ... */ </span>}</div>
</div>
<div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo">
<span style="font-variant-ligatures:no-common-ligatures">}</span></div>
<div><span style="font-variant-ligatures:no-common-ligatures"><br>
</span></div>
<div>Although this design pattern is often recommended for AST processing, managing data as we go down the tree can be cumbersome. The problem is that we need to store all intermediate results as we climb up the tree in some instance member, because
we can’t use the return type of the <font face="Menlo" style="font-size:11px">visit(_:)</font> method, as we would do with a recursive function:</div></span></div></div></blockquote><div><br></div><div><br></div></span><span class="m_6068872179046533889gmail-"><div>Why you can't use the return type? associatedtype doesn't solve the problem?</div><div><br></div></span><div><pre style="box-sizing:border-box;font-family:SFMono-Regular,Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:11.9px;margin-top:0px;margin-bottom:0px;font-stretch:normal;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(246,248,250);border-radius:3px;word-break:normal;color:rgb(36,41,46)"><span class="m_6068872179046533889gmail-"><span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">protocol</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">Visitor</span> {
<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">associatedtype</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">VisitResult</span>
<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">func</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">visit</span>(<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">_</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-smi" style="box-sizing:border-box">node</span>: BinExpr) <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">throws</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">-></span> VisitResult
<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">func</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">visit</span>(<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">_</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-smi" style="box-sizing:border-box">node</span>: Literal) <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">throws</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">-></span> VisitResult
<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">func</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">visit</span>(<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">_</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-smi" style="box-sizing:border-box">node</span>: Scope) <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">throws</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">-></span> VisitResult
<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">func</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">visit</span>(<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">_</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-smi" style="box-sizing:border-box">node</span>: Identifier) <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">throws</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">-></span> VisitResult
}
<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">extension</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">BinExpr</span> {
<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">func</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">accept</span><<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">V</span> : <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-e" style="box-sizing:border-box;color:rgb(111,66,193)">Visitor</span>>(<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">_</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-smi" style="box-sizing:border-box">visitor</span>: V) <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">throws</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">-></span> V.VisitResult { <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">return</span> visitor.<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">visit</span>(<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">self</span>) }
}
<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">extension</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">Literal</span> {
<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">func</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">accept</span><<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">V</span> : <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-e" style="box-sizing:border-box;color:rgb(111,66,193)">Visitor</span>>(<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">_</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-smi" style="box-sizing:border-box">visitor</span>: V) <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">throws</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">-></span> V.VisitResult { <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">return</span> visitor.<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">visit</span>(<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">self</span>) }
}
<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">extension</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">Scope</span> {
<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">func</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">accept</span><<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">V</span> : <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-e" style="box-sizing:border-box;color:rgb(111,66,193)">Visitor</span>>(<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">_</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-smi" style="box-sizing:border-box">visitor</span>: V) <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">throws</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">-></span> V.VisitResult { <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">return</span> visitor.<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">visit</span>(<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">self</span>) }
}
<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">extension</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">Identifier</span> {
<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">func</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">accept</span><<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">V</span> : <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-e" style="box-sizing:border-box;color:rgb(111,66,193)">Visitor</span>>(<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">_</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-smi" style="box-sizing:border-box">visitor</span>: V) <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">throws</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">-></span> V.VisitResult { <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">return</span> visitor.<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">visit</span>(<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">self</span>) }
}
</span><span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">class</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">Interpreter</span> : <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-e" style="box-sizing:border-box;color:rgb(111,66,193)">Visitor </span>{
<span class="m_6068872179046533889gmail-"><span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">func</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">visit</span>(<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">_</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-smi" style="box-sizing:border-box">node</span>: BinExpr) <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">-></span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">Int</span> {
<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">let</span> lhsResult <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">=</span> node.<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-smi" style="box-sizing:border-box">lhs</span>.<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">accept</span>(<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">self</span>)
<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">let</span> rhsResult <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">=</span> node.<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-smi" style="box-sizing:border-box">rhs</span>.<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">accept</span>(<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">self</span>)
<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-c" style="box-sizing:border-box;color:rgb(106,115,125)"><span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-c" style="box-sizing:border-box">/*</span> ... <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-c" style="box-sizing:border-box">*/</span></span>
<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">return</span> result
}
<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-c" style="box-sizing:border-box;color:rgb(106,115,125)"><span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-c" style="box-sizing:border-box">/*</span> ... <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-c" style="box-sizing:border-box">*/</span></span>
}</span></pre></div><div><br></div><div><br></div><div><br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><div><span style="font-variant-ligatures:no-common-ligatures">
<div><br>
</div><span class="m_6068872179046533889gmail-">
<div>
<div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo">
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">class</span><span style="font-variant-ligatures:no-common-ligatures"> Interpreter: </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(112,61,170)">Visitor</span><span style="font-variant-ligatures:no-common-ligatures"> {</span></div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">func</span><span style="font-variant-ligatures:no-common-ligatures"> visit(</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">_</span><span style="font-variant-ligatures:no-common-ligatures"> node: </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(112,61,170)">BinExpr</span><span style="font-variant-ligatures:no-common-ligatures">)
{</span></div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"> node.lhs.accept(</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">self</span><span style="font-variant-ligatures:no-common-ligatures">)</span></div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">let</span><span style="font-variant-ligatures:no-common-ligatures"> lhs
= accumulator!</span></div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"> node.rhs.accept(</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">self</span><span style="font-variant-ligatures:no-common-ligatures">)</span></div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">let</span><span style="font-variant-ligatures:no-common-ligatures"> rhs
= accumulator!</span></div>
<div style="margin:0px;line-height:normal;min-height:13px"><span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-m_78181763072270954gmail-m_-2776003668669580947Apple-tab-span" style="white-space:pre-wrap"></span><span style="color:rgb(0,132,0)">/* ... */</span><span style="font-variant-ligatures:no-common-ligatures"></span></div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"> }</span></div>
<div style="margin:0px;line-height:normal;min-height:13px"><span style="font-variant-ligatures:no-common-ligatures"></span><br>
</div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">func</span><span style="font-variant-ligatures:no-common-ligatures"> visit(</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">_</span><span style="font-variant-ligatures:no-common-ligatures"> node: </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(112,61,170)">Literal</span><span style="font-variant-ligatures:no-common-ligatures">)
{ </span><span style="color:rgb(0,132,0)">/* ... */ </span>}</div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)"> func</span><span style="font-variant-ligatures:no-common-ligatures"> visit(</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">_</span><span style="font-variant-ligatures:no-common-ligatures"> node: </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(112,61,170)">Scope</span><span style="font-variant-ligatures:no-common-ligatures">)
{ </span><span style="color:rgb(0,132,0)">/* ... */ </span>}</div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)"> func</span><span style="font-variant-ligatures:no-common-ligatures"> visit(</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">_</span><span style="font-variant-ligatures:no-common-ligatures"> node: </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(112,61,170)">Identifier</span><span style="font-variant-ligatures:no-common-ligatures">)
{ </span><span style="color:rgb(0,132,0)">/* ... */ </span>}</div>
<div style="margin:0px;line-height:normal;min-height:13px"><span style="font-variant-ligatures:no-common-ligatures"></span><br>
</div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">var</span><span style="font-variant-ligatures:no-common-ligatures"> accumulator: </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(112,61,170)">Int</span><span style="font-variant-ligatures:no-common-ligatures">?
= </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">nil</span></div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)"><br>
</span></div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)"> </span><span style="color:rgb(0,132,0)">/* ... */</span></div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures">}</span></div>
</div>
</div>
<div><br>
</div>
<div>As our interpreter will grow and need more visitors to “return” a value, we’ll be forced to add more and more stored properties to its definition. Besides, the state of those properties is difficult to debug, as it can quickly become unclear what
depth of the tree they should be associated to. In fact, it is as if all these properties acted as global variables.</div>
<div><br>
</div>
<div>The problem gets even bigger when we need to <i>pass</i> variables to a particular execution of a <span style="font-family:Menlo;font-size:11px">visit(_:)</span>. Not only do we need to add a stored property to represent
each “argument”, but we also have to store them in stacks so that a nested calls to a particular visit can get their own “evaluation context”. Consider for instance the implementation of the <font face="Menlo" style="font-size:11px">visit(</font><span style="color:rgb(186,45,162);font-family:Menlo;font-size:11px">_</span><font face="Menlo" style="font-size:11px"> node: </font><span style="color:rgb(112,61,170);font-family:Menlo;font-size:11px">Identifier</span><font face="Menlo" style="font-size:11px">)</font>,
assuming that the language our AST represents would support lexical scoping.</div></span></span></div></div></blockquote><div><br></div><span class="m_6068872179046533889gmail-"><div><br></div><div>How about returning curried function from visitor?</div><div><br></div><div><br></div><div><pre style="box-sizing:border-box;font-family:SFMono-Regular,Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:11.9px;margin-top:0px;margin-bottom:0px;font-stretch:normal;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(246,248,250);border-radius:3px;word-break:normal;color:rgb(36,41,46)"><span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">class</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">Interpreter</span> : <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-e" style="box-sizing:border-box;color:rgb(111,66,193)">Visitor </span>{
<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">typealias</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">VisitResult</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">=</span> ([<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">String</span>:<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">Int</span>]) throws <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">-></span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">Int</span>
<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">func</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">visit</span>(<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">_</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-smi" style="box-sizing:border-box">node</span>: Identifier) throws <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">-></span> VisitResult {
<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">return</span> { symbols <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">in</span>
<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">guard</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">let</span> result <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">=</span> symbols[node.<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-smi" style="box-sizing:border-box">name</span>] {
<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">throws</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">UndefinedIdentifierError</span>(node.<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-smi" style="box-sizing:border-box"><wbr>name</span>)
}
<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">return</span> result
}
}
<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-c" style="box-sizing:border-box;color:rgb(106,115,125)"><span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-c" style="box-sizing:border-box">/*</span> ... <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-c" style="box-sizing:border-box">*/</span></span>
}</pre></div><div><br></div><div><br></div></span><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><div><span style="font-variant-ligatures:no-common-ligatures">
<div><br>
</div><div><div class="m_6068872179046533889gmail-h5">
<div>
<div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo">
<span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">class</span><span style="font-variant-ligatures:no-common-ligatures"> Interpreter: </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(112,61,170)">Visitor</span><span style="font-variant-ligatures:no-common-ligatures"> {</span></div>
<div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo">
<span style="color:rgb(0,132,0)">/* ... */</span></div>
<div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px">
<span style="font-variant-ligatures:no-common-ligatures"></span><br>
</div>
<div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px">
<span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)"> func</span><span style="font-variant-ligatures:no-common-ligatures"> visit(</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">_</span><span style="font-variant-ligatures:no-common-ligatures"> node: </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(112,61,170)">Scope</span><span style="font-variant-ligatures:no-common-ligatures">)
{</span></div>
<div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px">
<span style="font-variant-ligatures:no-common-ligatures"> symbols.append([:])</span></div>
<div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px">
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)"> for</span><span style="font-variant-ligatures:no-common-ligatures"> child </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">in</span><span style="font-variant-ligatures:no-common-ligatures"> node.children
{</span></div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"> child.accept(</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">self</span><span style="font-variant-ligatures:no-common-ligatures">)</span></div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"> }</span></div>
</div>
<div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px">
<span style="font-variant-ligatures:no-common-ligatures"> symbols.removeLast()</span></div>
<div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px">
}</div>
<div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px">
<br>
</div>
<div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo">
<span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">func</span><span style="font-variant-ligatures:no-common-ligatures"> visit(</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">_</span><span style="font-variant-ligatures:no-common-ligatures"> node: </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(112,61,170)">Identifie<wbr>r</span><span style="font-variant-ligatures:no-common-ligatures">)
{</span></div>
<div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo">
<span style="font-variant-ligatures:no-common-ligatures"> accumulator = symbols.last![<a href="http://node.name" target="_blank">node.name</a>]!</span></div>
<div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo">
<span style="font-variant-ligatures:no-common-ligatures"> }</span></div>
<div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px">
<br>
<span style="font-variant-ligatures:no-common-ligatures"></span></div>
<div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo">
<span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">var</span><span style="font-variant-ligatures:no-common-ligatures"> symbols
= [[String: Int]]()</span></div>
<div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo">
<span style="font-variant-ligatures:no-common-ligatures">}</span></div>
</div>
</div></div></span></div><div><div class="m_6068872179046533889gmail-h5">
<div><br>
</div>
<div>We could instead create another instance of our visitor to set manage those evaluation contexts. But that would require us to explicitly copy all the variables associated to those contexts, which could potentially be inefficient and error prone.</div>
<div><br>
</div>
<div>In fact, this last point is also true when dealing with recursive functions. For instance, our <span style="font-family:Menlo;font-size:11px">visit(</span><span style="color:rgb(186,45,162);font-family:Menlo;font-size:11px">_</span><span style="font-family:Menlo;font-size:11px"> node: </span><span style="color:rgb(112,61,170);font-family:Menlo;font-size:11px">Identifier</span><span style="font-family:Menlo;font-size:11px">)</span> <wbr>method
could be rewritten as:</div>
<div><br>
</div>
<div>
<div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo">
<span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">func</span><span style="font-variant-ligatures:no-common-ligatures"> interpret(</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">_</span><span style="font-variant-ligatures:no-common-ligatures"> identifier: </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(112,61,170)">I<wbr>dentifier</span><span style="font-variant-ligatures:no-common-ligatures">, symbols:
[</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(112,61,170)">String</span><span style="font-variant-ligatures:no-common-ligatures">: </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(112,61,170)">Value</span><span style="font-variant-ligatures:no-common-ligatures">])
-> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(112,61,170)">Int</span><span style="font-variant-ligatures:no-common-ligatures"> { </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(0,132,0)">/*
... */</span><span style="font-variant-ligatures:no-common-ligatures"> }</span></div>
</div>
<div><br>
</div>
<div>so that its evaluation context is passed as a parameter. But this also requires all other functions to also pass this argument, even if their execution does not require the parameter.</div>
<div><br>
</div>
<div><span style="font-family:Menlo;font-size:11px;font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">func</span><span style="font-family:Menlo;font-size:11px;font-variant-ligatures:no-common-ligatures"> interpret(</span><span style="font-family:Menlo;font-size:11px;font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">_</span><span style="font-family:Menlo;font-size:11px;font-variant-ligatures:no-common-ligatures"> binExpr: </span><span style="font-family:Menlo;font-size:11px;font-variant-ligatures:no-common-ligatures;color:rgb(112,61,170)">BinE<wbr>xpr</span><span style="font-family:Menlo;font-size:11px;font-variant-ligatures:no-common-ligatures">,
symbols: [</span><span style="font-family:Menlo;font-size:11px;font-variant-ligatures:no-common-ligatures;color:rgb(112,61,170)">String</span><span style="font-family:Menlo;font-size:11px;font-variant-ligatures:no-common-ligatures">: </span><span style="font-family:Menlo;font-size:11px;font-variant-ligatures:no-common-ligatures;color:rgb(112,61,170)">Value</span><span style="font-family:Menlo;font-size:11px;font-variant-ligatures:no-common-ligatures">])
-> </span><span style="font-family:Menlo;font-size:11px;font-variant-ligatures:no-common-ligatures;color:rgb(112,61,170)">Int</span><span style="font-family:Menlo;font-size:11px;font-variant-ligatures:no-common-ligatures"> {</span></div>
<div style="font-family:Menlo;font-size:11px;margin:0px;line-height:normal">
<span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">let</span><span style="font-variant-ligatures:no-common-ligatures"> lhs =
interpret(</span><span style="font-variant-ligatures:no-common-ligatures">node.lhs.accept, </span>sym<wbr>bols: symbols)</div>
<div style="font-family:Menlo;font-size:11px;margin:0px;line-height:normal">
<span style="color:rgb(0,132,0)">/* ... */</span></div>
<div><span style="font-family:Menlo;font-size:11px;font-variant-ligatures:no-common-ligatures">}</span></div>
<div><br>
</div>
<div>This technique consisting of passing parameters through a function just so that another function called deeper in the stack can get its variable is actually quite common. Sadly, it clouds all signatures with many parameters, which make it more
difficult to reason about what a particular function actually needs from its caller. Note also that this overuses the running stack, putting many unnecessary values in all execution frames.</div>
<div><br>
</div>
<div>The idea I’d like to pitch is to offer a mechanism to address this issue. Namely, I’d like a way to provide a function with an environment when using its parameter and/or return type is not an option, or when doing so would add unnecessary complexity
to its signature (like illustrated above). While this mechanism would share similarities with how functions (and closures) are able to capture variables when they are declared, it would differ in the fact that these environment would depend on the execution
frame prior to that of a particular function call rather than the function declaration/definition.</div>
<div><br>
</div>
<div>First, one would declare a <i>contextual variable:</i></div>
<div><br>
</div>
<div><span style="font-family:Menlo;font-size:11px;font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">context var</span><span style="font-family:Menlo;font-size:11px;font-variant-ligatures:no-common-ligatures"> symbols:
[String: Int]?</span></div>
<div><span style="font-family:Menlo;font-size:11px;font-variant-ligatures:no-common-ligatures"><br>
</span></div>
<div>Such contextual variables could be seen as stacks, whose values are typed with that of the variable. In that particular example, the type of the context <font face="Menlo" style="font-size:11px">symbols</font> would be <font face="Menlo" style="font-size:11px">[String:
Int]</font>. The optional is needed to explicitly represent the fact that a context may not always be set, but this could be inferred as well. One would be able to set the value a contextual variable, effectively pushing a value on the stack it represent,
before entering a new execution frame:</div>
<div><br>
</div>
<div><span style="font-family:Menlo;font-size:11px;color:rgb(186,45,162)">set</span><span style="font-family:Menlo;font-size:11px"> symbols = [:] </span><span style="color:rgb(186,45,162);font-family:Menlo;font-size:11px">in</span><span style="font-family:Menlo;font-size:11px"> {</span></div>
<div>
<div style="font-family:Menlo;font-size:11px;margin:0px;line-height:normal">
<span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">for</span><span style="font-variant-ligatures:no-common-ligatures"> child </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">in</span><span style="font-variant-ligatures:no-common-ligatures"> node.children
{</span></div>
<div style="font-family:Menlo;font-size:11px;margin:0px;line-height:normal">
<span style="font-variant-ligatures:no-common-ligatures"> child.accept(</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">self</span><span style="font-variant-ligatures:no-common-ligatures">)</span></div>
<div style="font-family:Menlo;font-size:11px;margin:0px;line-height:normal">
<span style="font-variant-ligatures:no-common-ligatures"> }</span></div>
</div>
<div><span style="font-family:Menlo;font-size:11px">}</span></div>
<div><span style="font-family:Menlo;font-size:11px"><br>
</span></div>
<div>In the above example, the contextual variable <span style="font-family:Menlo;font-size:11px">symbols</span> would represent an empty dictionary for all execution frames above that of the context scope (delimited by braces). Extracting
a value from a context would boils down to reading an optional value:</div>
<div><br>
</div>
<div>
<div style="font-family:Menlo;font-size:11px;margin:0px;line-height:normal">
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">guard</span><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">let</span><span style="font-variant-ligatures:no-common-ligatures"> val
= symbols?[<a href="http://node.name" target="_blank">node.name</a>] <span style="color:rgb(186,45,162)">else</span> {</span></div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"> fatalError(</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(209,47,27)">"undefined symbol: </span><span style="font-variant-ligatures:no-common-ligatures">\</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(209,47,27)">(</span><span style="font-variant-ligatures:no-common-ligatures"><a href="http://node.name" target="_blank">node.name</a></span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(209,47,27)">)</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(209,47,27)">"</span><span style="font-variant-ligatures:no-common-ligatures">)</span></div>
<div style="margin:0px;line-height:normal">}</div>
<div style="margin:0px;line-height:normal">accumulator = val</div>
</div>
</div>
<div><br></div></div></div></div></blockquote><div><br></div><span class="m_6068872179046533889gmail-"><div><br></div><div>You can do something like this:</div><div><br></div></span><div><pre style="box-sizing:border-box;font-family:SFMono-Regular,Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:11.9px;margin-top:0px;margin-bottom:0px;font-stretch:normal;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(246,248,250);border-radius:3px;word-break:normal;color:rgb(36,41,46)"><span class="m_6068872179046533889gmail-"><span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">func</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">saveAndRestore</span><<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">T</span>, <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">R</span>>(<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">_</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-smi" style="box-sizing:border-box">variable</span>: <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">inout</span> T, <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">_</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-smi" style="box-sizing:border-box">tmpVal</span>: T, <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-smi" style="box-sizing:border-box"><span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">body</span></span>: () <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">-></span> R) <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">-></span> R {
<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">let</span> savedVal <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">=</span> variable
variable <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">=</span> tmpVal
<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">defer</span> { variable <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">=</span> savedVal }
<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">return</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">body</span>()
}
<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">class</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">Interpreter</span> : <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-e" style="box-sizing:border-box;color:rgb(111,66,193)">Visitor </span>{
<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">var</span> symbols<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">:</span> [<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">String</span><span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">:</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">Int</span>] <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">=</span> [<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">:</span>]
<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">func</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">visit</span>(<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">_</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-smi" style="box-sizing:border-box">node</span>: Scope) <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">throws</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">-></span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">Int</span></span> {
<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">return</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">saveAndRestore</span>(symbols, [<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">:</span>]) {</pre></div></div></div></div></blockquote><div><br></div><div><br></div></div></div><span class=""><div>Ah, this must be `<font face="monospace, monospace">saveAndRestore(&symbols, [:]) {</font>` of course.</div><div><br></div><div> </div></span><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div><pre style="box-sizing:border-box;font-family:SFMono-Regular,Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:11.9px;margin-top:0px;margin-bottom:0px;font-stretch:normal;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(246,248,250);border-radius:3px;word-break:normal;color:rgb(36,41,46)"> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">for</span> child <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">in</span> node.<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-smi" style="box-sizing:border-box">children</span> {
child.<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">accept</span>(this)
}
<span class="m_6068872179046533889gmail-"><span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">return</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">0</span><div><div class="h5">
}
}
<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">func</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">visit</span>(<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-en" style="box-sizing:border-box;color:rgb(111,66,193)">_</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-smi" style="box-sizing:border-box">node</span>: Identifier) <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">throws</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">-></span> Int {<br> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">guard</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">let</span> result <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">=</span> symbols[node.<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-smi" style="box-sizing:border-box">name</span>] {
<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">throws</span> <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">UndefinedIdentifierError</span>(node.<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-smi" style="box-sizing:border-box"><wbr>name</span>)
}
<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">return</span> result
}
<span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-c" style="box-sizing:border-box;color:rgb(106,115,125)"><span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-c" style="box-sizing:border-box">/*</span> ... <span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-pl-c" style="box-sizing:border-box">*/</span></span>
}</div></div></span></pre></div><div><div class="h5"><div><br></div><div><div class="m_6068872179046533889gmail-h5"><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><div>
</div>
<div>And as contextual variables would actually be stacks, one could push another value on the top of them to setup for another evaluation context. Hence, would we call <span style="font-family:Menlo;font-size:11px;color:rgb(186,45,162)">set</span><span style="font-family:Menlo;font-size:11px"> symbols
= [:] </span><span style="color:rgb(186,45,162);font-family:Menlo;font-size:11px">in </span><span style="font-family:Menlo;font-size:11px">{ </span><span style="color:rgb(0,132,0);font-family:Menlo;font-size:11px">/*
... */</span><span style="font-family:Menlo;font-size:11px"> }</span> again, the contextual variable <span style="font-family:Menlo;font-size:11px">symbols</span> would represent another empty dictionary as long as our new context
would be alive:</div>
<div><br>
</div>
<div>
<div><span style="font-family:Menlo;font-size:11px;color:rgb(186,45,162)">set</span><span style="font-family:Menlo;font-size:11px"> symbols = </span><span style="font-family:Menlo;font-size:11px;font-variant-ligatures:no-common-ligatures">[</span><span style="color:rgb(209,47,27);font-family:Menlo;font-size:11px;font-variant-ligatures:no-common-ligatures">"foo"</span><span style="font-family:Menlo;font-size:11px;font-variant-ligatures:no-common-ligatures">: </span><span style="font-family:Menlo;font-size:11px;font-variant-ligatures:no-common-ligatures;color:rgb(39,42,216)">1</span><span style="font-family:Menlo;font-size:11px;font-variant-ligatures:no-common-ligatures">]</span><span style="font-family:Menlo;font-size:11px"> </span><span style="color:rgb(186,45,162);font-family:Menlo;font-size:11px">in</span><span style="font-family:Menlo;font-size:11px"> {</span></div>
<div>
<div style="font-family:Menlo;font-size:11px;margin:0px;line-height:normal">
<span style="color:rgb(186,45,162)">set</span> symbols = <span style="font-variant-ligatures:no-common-ligatures">[</span><span style="color:rgb(209,47,27);font-variant-ligatures:no-common-ligatures">"foo</span><span style="color:rgb(209,47,27)">"</span><span style="font-variant-ligatures:no-common-ligatures">: </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(39,42,216)">2</span><span style="font-variant-ligatures:no-common-ligatures">]</span> <span style="color:rgb(186,45,162)">in</span> {</div>
</div>
<div style="margin:0px;line-height:normal"><font face="Menlo"><span style="font-size:11px"> print(symbols![</span></font><span style="font-family:Menlo;font-size:11px;color:rgb(209,47,27);font-variant-ligatures:no-common-ligatures">"foo</span><font color="#d12f1b" face="Menlo"><span style="font-size:11px">”</span></font><font face="Menlo"><span style="font-size:11px">]!)</span></font></div>
<div style="font-family:Menlo;font-size:11px;margin:0px;line-height:normal">
<span style="color:rgb(0,132,0)">// Prints 2</span></div>
<div style="font-family:Menlo;font-size:11px;margin:0px;line-height:normal">
}</div>
<div style="font-family:Menlo;font-size:11px;margin:0px;line-height:normal">
print(<font face="Menlo" style="font-size:12px"><span style="font-size:11px">symbols![</span></font><span style="color:rgb(209,47,27);font-variant-ligatures:no-common-ligatures">"foo</span><font color="#d12f1b" face="Menlo" style="font-size:12px"><span style="font-size:11px">”</span></font><font face="Menlo" style="font-size:12px"><span style="font-size:11px">]!</span></font>)</div>
<div style="font-family:Menlo;font-size:11px;margin:0px;line-height:normal">
<span style="color:rgb(0,132,0)">// Prints 1</span></div>
<div><span style="font-family:Menlo;font-size:11px">}</span></div>
</div>
<div><span style="font-family:Menlo;font-size:11px"><br>
</span></div>
<div>The advantage of that approach is threefold.</div>
<div>
<ol class="m_6068872179046533889gmail-m_-3999935715993199406gmail-m_78181763072270954gmail-m_-2776003668669580947MailOutline">
<li>It lets us provide an environment to functions that can’t receive more parameters or return custom values. This is particularly useful when dealing with libraries that provide an entry to define custom behaviour, but fix the API of the functions
they expect (e.g. a visitor protocol). In those instances, capture by closure is not always possible/desirable.</li><li>In large function hierarchy, it lets us provide deep functions with variables, without the need to pass them in every single function call just in the off chance one function may need it deeper in the call graph.</li><li>It better defines the notion of stacked environment, so that one can “override” an execution context, which is often desirable when processing recursive structures such as trees or graphs. In particular, it is very useful when not all functions
require all data that are passed down the tree.</li></ol>
<div><br>
</div>
</div>
<div>Using our contextual variables, one could rewrite our motivational example as follows:</div>
<div><br>
</div>
<div><span style="font-family:Menlo;font-size:11px;font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">class</span><span style="font-family:Menlo;font-size:11px;font-variant-ligatures:no-common-ligatures"> Interpreter: </span><span style="font-family:Menlo;font-size:11px;font-variant-ligatures:no-common-ligatures;color:rgb(112,61,170)">Visitor</span><span style="font-family:Menlo;font-size:11px;font-variant-ligatures:no-common-ligatures"> {</span></div>
<div>
<div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo">
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">func</span><span style="font-variant-ligatures:no-common-ligatures"> visit(</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">_</span><span style="font-variant-ligatures:no-common-ligatures"> node: </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(112,61,170)">BinExpr</span><span style="font-variant-ligatures:no-common-ligatures">)
{</span></div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"> <span style="color:rgb(186,45,162)">let</span> lhs, rhs : </span><span style="color:rgb(112,61,170)">Int</span></div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"><span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-m_78181763072270954gmail-m_-2776003668669580947Apple-tab-span" style="white-space:pre-wrap"></span><span style="color:rgb(186,45,162)">set</span> accumulator
= <span style="color:rgb(186,45,162)">nil</span> <font color="#ba2da2">in</font> {</span></div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures">node.lhs.accept(</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">self</span><span style="font-variant-ligatures:no-common-ligatures">)</span></div>
<div style="margin:0px;line-height:normal"> lhs = accumulator!</div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"> }</span></div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures">
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"><span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-m_78181763072270954gmail-m_-2776003668669580947Apple-tab-span" style="white-space:pre-wrap"></span><span style="color:rgb(186,45,162)">set</span> accumulator
= <span style="color:rgb(186,45,162)">nil</span> </span><font color="#ba2da2">in </font>{</div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures">node.lhs.accept(</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">self</span><span style="font-variant-ligatures:no-common-ligatures">)</span></div>
<div style="margin:0px;line-height:normal"> rhs = accumulator!</div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"> }</span></div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"><br>
</span></div>
<div style="margin:0px;line-height:normal">
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">switch</span><span style="font-variant-ligatures:no-common-ligatures"> node.op
{</span></div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">case</span><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(209,47,27)">"+"</span><span style="font-variant-ligatures:no-common-ligatures">:</span></div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"> accumulator = lhs + rhs</span></div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">case</span><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(209,47,27)">"-"</span><span style="font-variant-ligatures:no-common-ligatures">:</span></div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"> accumulator = lhs - rhs</span></div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">default</span><span style="font-variant-ligatures:no-common-ligatures">:</span></div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"> fatalError(</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(209,47,27)">"unexpected
operator </span><span style="font-variant-ligatures:no-common-ligatures">\</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(209,47,27)">(</span><span style="font-variant-ligatures:no-common-ligatures">node.op</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(209,47,27)">)"</span><span style="font-variant-ligatures:no-common-ligatures">)</span></div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"> }</span></div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"> }</span></div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"><br>
</span></div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures">
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">func</span><span style="font-variant-ligatures:no-common-ligatures"> visit(</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">_</span><span style="font-variant-ligatures:no-common-ligatures"> node: </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(112,61,170)">Literal</span><span style="font-variant-ligatures:no-common-ligatures">)
{</span></div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"> accumulator = node.val</span></div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"> }</span></div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"><br>
</span></div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures">
<div style="margin:0px;line-height:normal;min-height:13px"><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)"> func</span><span style="font-variant-ligatures:no-common-ligatures"> visit(</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">_</span><span style="font-variant-ligatures:no-common-ligatures"> node: </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(112,61,170)">Scope</span><span style="font-variant-ligatures:no-common-ligatures">)
{</span></div>
<div style="margin:0px;line-height:normal;min-height:13px">
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"><span class="m_6068872179046533889gmail-m_-3999935715993199406gmail-m_78181763072270954gmail-m_-2776003668669580947Apple-tab-span" style="white-space:pre-wrap"></span><span style="color:rgb(186,45,162)">set</span> symbols = [:]</span> <font color="#ba2da2">in</font> {</div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">for</span><span style="font-variant-ligatures:no-common-ligatures"> child </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">in</span><span style="font-variant-ligatures:no-common-ligatures"> node.children
{</span></div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"> child.accept(</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">self</span><span style="font-variant-ligatures:no-common-ligatures">)</span></div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"> }</span></div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"> }</span></div>
</div>
<div style="margin:0px;line-height:normal;min-height:13px"> }</div>
</span></div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"><br>
</span></div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures">
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">func</span><span style="font-variant-ligatures:no-common-ligatures"> visit(</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">_</span><span style="font-variant-ligatures:no-common-ligatures"> node: </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(112,61,170)">Identifie<wbr>r</span><span style="font-variant-ligatures:no-common-ligatures">)
{</span></div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">guard</span><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">let</span><span style="font-variant-ligatures:no-common-ligatures"> val
= symbols?[<a href="http://node.name" target="_blank">node.name</a>] <span style="color:rgb(186,45,162)">else</span> {</span></div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures">fatalError(</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(209,47,27)">"undefined
symbol</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(209,47,27)">: </span><span style="font-variant-ligatures:no-common-ligatures">\</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(209,47,27)">(</span><span style="font-variant-ligatures:no-common-ligatures"><a href="http://node.name" target="_blank">node.name</a></span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(209,47,27)">)</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(209,47,27)">"</span><span style="font-variant-ligatures:no-common-ligatures">)</span></div>
<div style="margin:0px;line-height:normal"> }</div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"> </span>accumulator = val</div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"> }</span></div>
</span></div>
</span></div>
</div>
</span></div>
<div style="margin:0px;line-height:normal;min-height:13px"><span style="font-variant-ligatures:no-common-ligatures"></span><br>
</div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">context var</span><span style="font-variant-ligatures:no-common-ligatures"> accumulator: </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(112,61,170)">Int</span><span style="font-variant-ligatures:no-common-ligatures">?</span></div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)"> context</span></span><span style="color:rgb(186,45,162)"> </span><span style="color:rgb(186,45,162)">var</span> symbols:
[String: Int]?</div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures">}</span></div>
<div><span style="font-variant-ligatures:no-common-ligatures"><br>
</span></div>
</div>
</div>
<div>It is no longer unclear what depth of the tree the <font face="Menlo" style="font-size:11px">accumulator</font> variable should be associated with. The mechanism is handled automatically, preventing the programmer from incorrectly reading
a value that was previously set for another descent. It is no longer needed to manually handle the stack management of the <span style="font-family:Menlo;font-size:11px">symbols</span> variable, which was error prone in our previous implementation.</div>
<div><br>
</div>
<div>The scope of contextual variables should not be limited to type declarations. One may want to declare them in the global scope of a module, so that they would be part of the API of a library. Imagine for instance a web framework library, using
contextual variables to provide the context of a request handler:</div>
<div><br>
</div>
<div>
<div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)">
<span style="font-variant-ligatures:no-common-ligatures">// In the framework ...</span></div>
</div>
<div>
<div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo">
<span style="font-variant-ligatures:no-common-ligatures"><span style="color:rgb(186,45,162)">public context</span> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">var</span><span style="font-variant-ligatures:no-common-ligatures"> authInfo: </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(112,61,170)">AuthInfo</span></div>
<div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px">
<span style="font-variant-ligatures:no-common-ligatures"></span><br>
</div>
<div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px">
<div style="margin:0px;line-height:normal;color:rgb(0,132,0)"><span style="font-variant-ligatures:no-common-ligatures">// In the user code ...</span></div>
</div>
<div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo">
<span style="font-variant-ligatures:no-common-ligatures">framework.addHandler(for: URL(</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(209,47,27)">"/index"</span><span style="font-variant-ligatures:no-common-ligatures">))
{</span></div>
<div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo">
<span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">guard</span><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">let</span><span style="font-variant-ligatures:no-common-ligatures"> user
= authInfo?.user </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">else</span><span style="font-variant-ligatures:no-common-ligatures"> {</span></div>
<div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo">
<span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">return</span><span style="font-variant-ligatures:no-common-ligatures"> Redirect(to:
URL(</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(209,47,27)">"/login"</span><span style="font-variant-ligatures:no-common-ligatures">))</span></div>
<div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo">
<span style="font-variant-ligatures:no-common-ligatures"> }</span></div>
<div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px">
<span style="font-variant-ligatures:no-common-ligatures"></span><br>
</div>
<div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo">
<span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">return</span><span style="font-variant-ligatures:no-common-ligatures"> Response(</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(209,47,27)">"Welcome
back </span><span style="font-variant-ligatures:no-common-ligatures">\</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(209,47,27)">(</span><span style="font-variant-ligatures:no-common-ligatures"><a href="http://user.name" target="_blank">user.name</a></span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(209,47,27)">)!"</span><span style="font-variant-ligatures:no-common-ligatures">)</span></div>
<div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo">
<span style="font-variant-ligatures:no-common-ligatures">}</span></div>
</div>
<div><br>
</div>
<div>In that example, one could imagine that the framework would set the contextual <font face="Menlo" style="font-size:11px">authInfo</font> variable with the authentication information it would parse from the request before calling the
registered handlers.</div>
<div><br>
</div>
<div>This idea is not exactly new. In fact, people familiar with Python may recognise some similarities with how "<font face="Menlo" style="font-size:11px">with</font> statements" work. Hence, it is not surprising that things one is able
to do with Python’s contexts would be possible to do with contextual variables as presented above. Consider for instance the following class:</div>
<div><br>
</div>
<div>
<div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo">
<span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">class</span><span style="font-variant-ligatures:no-common-ligatures"> Connexion {</span></div>
<div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo">
<span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">init</span><span style="font-variant-ligatures:no-common-ligatures">(to: </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(112,61,170)">URL</span><span style="font-variant-ligatures:no-common-ligatures">)
{ </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(0,132,0)">/* ... */</span><span style="font-variant-ligatures:no-common-ligatures"> }</span></div>
<div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo">
<span style="font-variant-ligatures:no-common-ligatures"><br>
</span></div>
<div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo">
<span style="font-variant-ligatures:no-common-ligatures">
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">deinit</span><span style="font-variant-ligatures:no-common-ligatures"> {</span></div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">self</span><span style="font-variant-ligatures:no-common-ligatures">.disconnect()</span></div>
<div style="margin:0px;line-height:normal"><span style="font-variant-ligatures:no-common-ligatures"> }</span></div>
</span></div>
<div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px">
<span style="font-variant-ligatures:no-common-ligatures"></span><br>
</div>
<div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo">
<span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">func</span><span style="font-variant-ligatures:no-common-ligatures"> disconnect()
{ </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(0,132,0)">/* ... */</span><span style="font-variant-ligatures:no-common-ligatures"> }</span></div>
<div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px">
}<span style="font-variant-ligatures:no-common-ligatures"></span></div>
</div>
<div><span style="font-variant-ligatures:no-common-ligatures"><br>
</span></div>
<div>Thanks to Swift’s memory lifecycle, instantiating an instance of <span style="font-family:Menlo;font-size:11px">Connexion</span> as a contextual variable would automatically call its destructor when the context would get popped out.</div>
<div><br>
</div>
<div><span style="font-family:Menlo;font-size:11px;font-variant-ligatures:no-common-ligatures"><span style="color:rgb(186,45,162)">context</span> </span><span style="font-family:Menlo;font-size:11px;font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">var</span><span style="font-family:Menlo;font-size:11px;font-variant-ligatures:no-common-ligatures"> conn: </span><span style="font-family:Menlo;font-size:11px;font-variant-ligatures:no-common-ligatures;color:rgb(112,61,170)">Connexion</span></div>
<div>
<div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo">
<span style="font-variant-ligatures:no-common-ligatures"><span style="color:rgb(186,45,162)">set</span> conn = Connexion(to: URL(</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(209,47,27)">"<a href="http://some.url.com" target="_blank">http://some.url.com</a>"</span><span style="font-variant-ligatures:no-common-ligatures">)) </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)">in</span><span style="font-variant-ligatures:no-common-ligatures"><wbr> {</span></div>
<div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)">
<span style="font-variant-ligatures:no-common-ligatures;color:rgb(0,0,0)"> </span><span style="font-variant-ligatures:no-common-ligatures">/* ... */</span></div>
<div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)">
<span style="font-variant-ligatures:no-common-ligatures;color:rgb(0,0,0)">} </span><span style="font-variant-ligatures:no-common-ligatures">// the first connection is disconnected here</span></div>
</div>
<div><br>
</div>
<div>I see many other applications for such contextual variables, but I think this email is long enough.</div>
<div>I’m looking forward to your thought and feedbacks.</div></div></blockquote></div></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><div class="m_6068872179046533889gmail-h5"><div style="word-wrap:break-word"><div><br>
</div>
<div>Best regards,</div>
<div><br>
</div>
<br>
<div>
<div style="word-wrap:break-word">
Dimitri Racordon<br>
CUI, Université de Genève<br>
7, route de Drize, CH-1227 Carouge - Switzerland<br>
Phone: <a href="tel:+41%2022%20379%2001%2024" value="+41223790124" target="_blank">+41 22 379 01 24</a></div>
</div>
<br>
</div>
<br></div></div><span class="m_6068872179046533889gmail-">______________________________<wbr>_________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailma<wbr>n/listinfo/swift-evolution</a><br>
<br></span></blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br></blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br></blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br></blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br></blockquote></div></div></div></div></div><div><div class="h5">
<br>______________________________<wbr>_________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailma<wbr>n/listinfo/swift-evolution</a><br>
<br></div></div></blockquote></div><br></div></div>
<br>______________________________<wbr>_________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/<wbr>mailman/listinfo/swift-<wbr>evolution</a><br>
<br></blockquote></div><br></div>