import{_ as e,c as a,o as t,a4 as r}from"./chunks/framework.Cy9JvDAg.js";const c=JSON.parse('{"title":"2.1 - 值和类型","description":"","frontmatter":{"title":"2.1 - 值和类型","footer":true,"lastUpdated":true,"outline":false},"headers":[],"relativePath":"2.1.md","filePath":"2.1.md"}'),n={name:"2.1.md"},s=r('<h2 id="_2-1-值和类型" tabindex="-1">2.1 - 值和类型 <a class="header-anchor" href="#_2-1-值和类型" aria-label="Permalink to &quot;2.1 - 值和类型&quot;">​</a></h2><p>首先，Lua是动态类型语言。这意味着变量没有类型，只有值才有。语言中没有类型定义。所有的值保管着自己的类型。</p><p>Lua中所有的值都是“一等公民（ <em>first-class</em> ）“，即所有的值都可以被保存在变量中，可以作为函数参数以及被作为结果返回。</p><p><em><strong>一等公民 first-class 的概念由 <a href="https://zh.wikipedia.org/wiki/%E5%85%8B%E9%87%8C%E6%96%AF%E6%89%98%E5%BC%97%C2%B7%E6%96%AF%E7%89%B9%E9%9B%B7%E5%A5%87" target="_blank" rel="noreferrer">Christopher Strachey</a> 提出，其内容可参考《<a href="https://www.cs.rochester.edu/~scott/pragmatics/" target="_blank" rel="noreferrer">Programming Language Pragmatics</a>》中的一段：</strong></em></p><blockquote><p><em>In general, a value in a programming language is said to have ﬁrst-class status if it can be passed as a parameter, returned from a subroutine, or assigned into a variable.</em></p></blockquote><p>Lua有八种基本类型：<em>nil</em>、<em>boolean</em>、<em>string</em>、<em>function</em>、<em>userdata</em>、<em>thread</em>和<em>table</em>。 <em>nil</em> 类型是一个单独的值 <strong>nil</strong> ，主要特质就是不同于其他任何值，通常表示一个没有用的值。 <em>boolean</em> 类型有两种值—— <strong>false</strong> 和 <strong>true</strong> 。 <strong>nil</strong> 和 <strong>false</strong> 都可以使得条件为假，他们统称为假值（ <em>false values</em> ）。其他值都使得条件为真。尽管他们都叫假值， <strong>false</strong> 也常常用来替代 <strong>nil</strong> ，但是关键的区别在于: <strong>false</strong> 在表（table）中是个常规值，而 <strong>nil</strong> 表示一个缺失的键。</p><p><em>number</em> 类型使用两种子类型—— <em>integer</em> 和 <em>float</em> ，以表示整数和浮点数。标准Lua使用64位整数和双精度浮点数，但也可以编译出使用32位整数和单精度浮点数的版本。32位整数和浮点数的选项对于小型机和嵌入式系统来说很有吸引力。（参见 <strong>luaconf.h</strong> 文件中的 <strong>LUA_32BITS</strong> 宏定义）</p><p>若非另有说明，任何在整数操作时的溢出，都遵循一般的双补码算术规则。（换言之，其结果都是单一可表示整数，即2<sup>n</sup>的算术模，这里的n为整数类型的位数）</p><p>Lua对于每个子类型的使用都有明确的规则，但是也会按需在它们之间做自动转换（参见<a href="/lua5.4-manual-zh/3.4.3.html">3.4.3</a>）。因此，编程人员可以选择忽略整数和浮点数的差异亦或者完全控制每个数的表示形式。</p><p><em>string</em> 类型表示不可变的字节序。Lua字符串是纯8位形式——可以存储任意8位值，包括零值“\\0”。Lua字符串也是编码无关的——不关心字符串的内容。字符串的长度必须是个Lua整数。</p><p>Lua可以同时调用由Lua或C编写（参见<a href="/lua5.4-manual-zh/3.4.10.html">3.4.10</a>）的函数，它们都表示为 <em>function</em> 类型。</p><p><em>userdata</em> 类型提供将任意C数据存储在Lua变量中的能力。一个userdata值表示一块原始内存。由两种userdata： <em>full userdata</em> ——表示一块对象的内存并由Lua管理，以及 <em>light userdata</em> ——一个简单的C指针。userdata在Lua中除了赋值与相等判断外没有任何其他的预定义的操作。编程人员可以使用元表 <em>metatables</em> 来给 <em>full userdata</em> 来定义操作（参见<a href="/lua5.4-manual-zh/2.4.html">2.4</a>）。userdata值不可以在Lua中被创建或更改，只能用C接口操作。这保证了宿主程序和C库的数据只为其所有。</p><p><em>thread</em> 类型表示一个独立执行的线程，其用于实现协程（参见<a href="/lua5.4-manual-zh/2.6.html">2.6</a>）。Lua线程与操作系统的线程没关系。Lua在所有系统上都支持协程，即便是那些本身不支持线程的平台。</p><p><em>table</em> 类型实现了关联数组，即除了 <strong>nil</strong> 和NaN（ <em>Not a Number</em> 是一个特殊的浮点值，被用于IEEE 754标准中，表示一个未定义的数值结果，例如除零运算）之外的值都可以作为索引，而不只是数字。表可以是 <em>异构（heterogeneous）</em> 的，即可以存储所有类型的值（除了 <strong>nil</strong> ）。任何关联了<strong>nil</strong>值的键都被视为不存在于表中。换句话说，对于表中任意不存在的键，其值都是 <strong>nil</strong> 。</p><p>表是Lua中唯一的组织数据结构的机制，它可以用于表示一般数组、列表、符号表、集合、记录、图、树……等等。对于表示记录，Lua使用属性名来作为索引。语言支持用 a.name 来替代表示 a[&quot;name&quot;] 的语法糖。同时也有些创建表的方法（参见<a href="/lua5.4-manual-zh/3.4.9.html">3.4.9</a>）。</p><p>和索引一样，表的值也可以是任意类型。尤其是<em>function</em>，因其也是<em>一等公民（first-class）</em> 的值，所以也可以被表包含。因此表同样可以保管<em>函数</em>（参见<a href="/lua5.4-manual-zh/3.4.11.html">3.4.11</a>）。</p><p>表、函数、线程、以及（full）userdata都是对象，因此变量其实并不是 <em>包含（contain）</em> 它们的值，而只是 <em>引用（reference）</em> 了它们。赋值、传递参数和函数返回都是在操作这些值的引用，这些操作不涉及任何复制。</p><p>可使用库函数<a href="/lua5.4-manual-zh/6.1.html#type">type</a>来获得给定值的类型描述（参见<a href="/lua5.4-manual-zh/6.1.html#type">type</a>）。</p>',18),m=[s];function o(l,u,p,i,g,h){return t(),a("div",null,m)}const d=e(n,[["render",o]]);export{c as __pageData,d as default};
