import{_ as s,c as a,o as i,a4 as e}from"./chunks/framework.Cy9JvDAg.js";const u=JSON.parse('{"title":"3.4.10 - 函数调用","description":"","frontmatter":{"title":"3.4.10 - 函数调用","footer":true,"lastUpdated":true,"outline":false},"headers":[],"relativePath":"3.4.10.md","filePath":"3.4.10.md"}'),t={name:"3.4.10.md"},n=e(`<h3 id="_3-4-10-函数调用" tabindex="-1">3.4.10 - 函数调用 <a class="header-anchor" href="#_3-4-10-函数调用" aria-label="Permalink to &quot;3.4.10 - 函数调用&quot;">​</a></h3><p>函数调用的语法如下：</p><div class="language- vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code"><code><span class="line"><span>functioncall ::= prefixexp args</span></span></code></pre></div><p>在函数调用中，首先会计算打头的前缀表达式（prefixexp）和后边的参数（args）。如果前缀表达式的值是<em>function</em>类型的，那么这个值对应的函数就通过所给参数来调用。否则，如果前缀表达式其值有__call元函数的话，会这样调用此元函数：第一个参数是前缀表达式的值，后跟原本的调用参数（参见<a href="/lua5.4-manual-zh/2.4.html">2.4</a>）。</p><div class="language- vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code"><code><span class="line"><span>functioncall ::= prefixexp ‘:’ Name args</span></span></code></pre></div><p>这种形式被用来调用成员函数。v:name(<em>args</em>) 其实是 v.name(v, <em>args</em>) 的语法糖，不同之处在于v只被计算一次。</p><p>调用参数的语法如下：</p><div class="language- vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki shiki-themes github-light github-dark vp-code"><code><span class="line"><span>args ::= ‘(’ [explist] ‘)’</span></span>
<span class="line"><span>args ::= tableconstructor</span></span>
<span class="line"><span>args ::= LiteralString</span></span></code></pre></div><p>所有参数表达式会在调用之前被计算。f{<em>fields</em>}调用形式其实就是f({<em>fields</em>})的语法糖；即此参数列表是一个表。 f&#39;<em>string</em>&#39;（或者 f&quot;<em>string</em>&quot; 有或者 f[[<em>string</em>]]）调用形式其实就是 f(&#39;<em>string</em>&#39;)的语法糖；即此参数列表是一个字符串。</p><p>所有在非待关闭变量的作用域下的 return <em>functioncall</em> 调用形式被称为<em>尾调用（tail call）</em>。Lua实现了<em>尾调用优化 proper tail calls</em>（或称为<em>尾递归优化 proper tail recursion</em>）：在尾部调用中的调用函数会重复使用调用栈。因此程序可以执行无限制的内嵌尾调用。然而，尾调用会擦除所有其调用函数的调试信息。注意尾调用只发生于特定的语法中：<strong>return</strong>语句只有一个函数调用作为其参数，且这个函数在任何待关闭变量的作用域之外。此语法使得调用函数时直接返回其函数的返回值，其中没有任何多余动作。所以，以下都不是尾调用：</p><div class="language-lua vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">lua</span><pre class="shiki shiki-themes github-light github-dark vp-code"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(x))        </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">-- 返回值后还有一步操作，非直接的函数调用</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 2</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> *</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(x)      </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">-- 返回值后有两步操作，也是非直接的函数调用</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> x, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(x)       </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">-- 多个返回值</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(x); </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">return</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">         -- 返回值被全局丢弃</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> x </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">or</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> f</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(x)     </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">-- 计算返回值前还有一步操作，非直接的函数调用</span></span></code></pre></div>`,11),p=[n];function l(h,r,k,d,c,o){return i(),a("div",null,p)}const m=s(t,[["render",l]]);export{u as __pageData,m as default};
