个人建立一个网站要多少钱,乔拓云h5制作,个人网站名,怎样用8uftp做网站Lua
1.Lua是什么#xff1f;
1.1 Lua的历史
Lua是由Roberto Ierusalimschy、Luiz Henrique de Figueiredo和Waldemar Celes于1993年创建的#xff0c;当时他们是巴西里约热内卢天主教大学计算机图形技术组#xff08;Tecgraf#xff09;的成员。在开发Lua之前#xff0…Lua
1.Lua是什么
1.1 Lua的历史
Lua是由Roberto Ierusalimschy、Luiz Henrique de Figueiredo和Waldemar Celes于1993年创建的当时他们是巴西里约热内卢天主教大学计算机图形技术组Tecgraf的成员。在开发Lua之前他们曾参与过数据描述/配置语言SOL简单对象语言和DEL数据录入语言的工作。这两种语言是他们独立开发的两个不同项目的一部分旨在增强工程应用的交互式图形程序。然而SOL和DEL缺乏许多控制流结构因此需要增加完整的编程能力。因此为了满足这个需求他们创建了Lua。
在《The Evolution of Lua》中Lua的作者写道在1993年Tcl是Lua的唯一真正竞争者但Tcl的语法相对较为陌生且只能在Unix平台上运行不太适合数据描述。此外LISP和Scheme的语法也不够友好Python还处于起步阶段。在Tecgraf的自由、自主的氛围下他们自然而然地尝试开发自己的脚本语言。考虑到这门语言的潜在用户不一定是专业程序员因此他们希望语言避免复杂的语法和语义。另外由于Tecgraf的客户使用各种不同的计算机平台他们希望新语言的实现能够高度可移植。最后考虑到Tecgraf的其他产品也需要嵌入脚本语言他们决定让新语言像SOL一样提供带有C API的库。
1.2 Lua的特点
Lua 作为一种脚本语言具有多种特点以下是其中一些主要的特点
轻量级和可嵌入性Lua 的核心非常小巧可以轻松地嵌入到其他应用程序中作为脚本语言使用。这使得 Lua 在游戏开发、嵌入式系统和其他领域中得到广泛应用。简洁清晰的语法Lua 的语法简洁明了易于学习和使用。它没有过多的冗余符号采用基于表达式的语法没有大括号使用 end 关键字来结束块使得代码更加清晰易读。动态类型和自动内存管理Lua 是一种动态类型语言运行时进行变量类型检查和解析变量不需要显式声明类型。它还具有自动内存管理通过垃圾回收机制来管理内存简化了开发者的工作。强大的数据描述能力Lua 支持多种基本数据类型包括数字、字符串、布尔值、表类似于字典或关联数组、函数等。表是 Lua 中最重要的数据结构之一可以灵活地表示复杂的数据集合。灵活的扩展能力Lua 提供了丰富的扩展接口可以通过 C/C 编写扩展模块并与 Lua 脚本进行交互。这种可扩展性使得 Lua 可以与其他语言轻松集成满足不同应用场景的需求。高性能Lua 的解释器经过优化执行速度较快适合用于处理大规模的数据和复杂的逻辑。动态代码执行Lua 支持动态代码执行可以通过 load 和 loadfile 函数动态加载并执行 Lua 脚本灵活性很高。适用于嵌入式系统由于 Lua 的轻量级和可嵌入性它在嵌入式系统中得到广泛应用可以用于控制设备、配置参数等任务。
Ps:
1、什么是脚本语言
脚本语言是一种用于编写脚本的编程语言。
脚本是一系列按照特定顺序执行的命令或指令通常用于自动化任务、配置文件、批处理处理、快速原型开发等场景。脚本语言通常被设计为易于编写和理解其语法和结构往往更加简单直观。
脚本语言与编译型语言的主要区别在于脚本语言不需要经过编译成机器代码的过程而是由解释器逐行解释执行。这使得脚本语言的开发和调试更加快速和灵活因为开发者可以立即看到代码的效果而不需要额外的编译步骤。
脚本语言通常用于各种不同的领域包括
自动化任务例如批处理处理、系统管理任务、自动化测试等。Web 开发许多 Web 应用程序的后端和前端都使用脚本语言编写如 Python、JavaScript、PHP 等。游戏开发脚本语言在游戏开发中也得到广泛应用用于编写游戏逻辑、AI、用户界面等。配置文件许多软件和系统使用脚本语言编写配置文件以便用户可以轻松地配置和定制软件的行为。
总的来说脚本语言是一种简单、灵活且功能强大的编程语言适用于各种不同的应用场景能够大大提高开发效率和灵活性。
2、什么是解释性语言什么是编译性语言
解释性语言和编译性语言是两种不同类型的编程语言
解释性语言
解释性语言的代码由解释器逐行执行并在运行时进行解释和执行。在执行程序时解释器会逐行读取源代码并将其转换为计算机可理解的指令然后立即执行。由于解释器直接执行源代码因此解释性语言的开发和调试更加灵活可以动态地修改和查看代码的效果。常见的解释性语言包括 Lua、Python、Ruby、JavaScript、PHP 等。
编译性语言
编译性语言的代码需要先经过编译器将源代码转换为机器代码或者中间代码然后再由计算机执行。编译器在编译阶段将源代码转换为目标代码这个目标代码是针对特定硬件平台的可执行文件或者中间代码。一旦编译完成生成的可执行文件可以在没有编译器的情况下独立运行而不需要再次编译源代码。编译性语言的执行速度通常比解释性语言更快因为代码已经被预先转换为机器代码。常见的编译性语言包括 C、C、Java等。
2. 解释器的安装
2.1 下载压缩包
https://www.lua.org/download.htmllua-5.4.6.tar.gz2.2 解压
tar -xzf lua-5.4.6.tar.gzlua-5.4.62.3 安装
cd lua-5.4.6 //进入目录
make //编译
sudo make install //安装2.4 确认安装结果
lua -vLua 5.4.6ps. lua 在线模拟器
https://wiki.luatos.com/3.基本语法
3.1 第一个Lua 程序
3.1.1 交互式编程
Lua 提供了交互式编程模式。我们可以在命令行中输入程序并立即查看效果。
Lua 交互式编程模式可以通过命令 lua -i 或 lua 来启用
$ lua
$ Lua 5.4.6 Copyright (C) 1994-2023 Lua.org, PUC-Rio在命令行中输入以下命令: print(Hello World)接着我们按下回车键输出结果如下 print(Hello World)
Hello World3.1.2 脚本式编程
我们可以将 Lua 程序代码保存到一个以 lua 结尾的文件并执行该模式称为脚本式编程如我们将如下代码存储在名为 hello.lua 的脚本文件中
vim hello.luaprint(Hello world!)终端运行
$ lua hello.luahello world!3.2 注释
3.2.1 单行注释
两个减号是单行注释:
--3.2.2 多行注释
--[[多行注释多行注释
]]--3.3 标识符
在 Lua 中标识符是用于命名变量、函数、以及其他用户定义的东西的名称。Lua 中的标识符遵循以下规则
标识符可以由字母、数字和下划线 _ 组成。标识符必须以字母包括大小写或下划线 _ 开始不能以数字开头。Lua 是大小写敏感的因此 myVariable 和 MyVariable 是两个不同的标识符。Lua 的关键字例如 if、then、else、while、function 等不能用作标识符。Lua 中允许使用 UTF-8 编码的字母作为标识符因此也可以使用非拉丁字母作为标识符。
例如以下是一些合法的 Lua 标识符
myVar_counttable1变量名
而以下是一些不合法的 Lua 标识符
3abc以数字开头if关键字my-variable包含连字符 -#table包含特殊字符 #
注意
最好不要使用下划线加大写字母的标示符因为Lua的保留字也是这样的
3.4 关键字
andbreakdoelseelseifendfalseforfunctionifinlocalnilnotorrepeatreturnthentrueuntilwhilegoto
4.数据类型
Lua 是动态类型语言变量不要类型定义,只需要为变量赋值。 值可以存储在变量中作为参数传递或结果返回。
Lua 中有 8 个基本类型分别为nil、boolean、number、string、userdata、function、thread 和 table。
数据类型描述nil用于表示空或未初始化的值。boolean只有两个值true 和 false用于表示逻辑值。number用于表示数值包括整数和浮点数。string字符串由一对双引号或单引号来表示function由 C 或 Lua 编写的函数userdata表示任意存储在变量中的C数据结构thread表示执行的独立线路用于执行协同程序table是 Lua 中最重要的数据结构用于表示数组、字典、集合等复杂数据结构
5.变量
5.1 动态类
Lua 是一种动态类型语言变量的类型是根据赋给它们的值自动确定的。
a 1;5.2 全局变量
在默认情况下变量总是认为是全局的。
全局变量不需要声明给一个变量赋值后即创建了这个全局变量访问一个没有初始化的全局变量也不会出错只不过得到的结果是nil。 print(b)
nilb10print(b)
10如果你想删除一个全局变量只需要将变量赋值为nil。
b nil
print(b) -- nil这样变量b就好像从没被使用过一样。换句话说, 当且仅当一个变量不等于nil时这个变量即存在。
5.3 局部变量
如果想使用局部变量在变量前加 local 关键字
局部变量的作用域通常是从声明处到当前语句块结束。
local c 10 -- 这是一个局部变量5.4 多重赋值
a,b 1,2
print(a,b)1 2a,b,c 1,2
print(a,b)1 2 nil5.5 数值型变量
-- 整型
a 1-- 浮点型
b 2.1-- 科学计数法
c 1e3-- 十六进制
d 0x11print(a,b,c,d)1 2.1 1000.0 17-- 获取字符 A 的 ASCII 码值
asciiValue string.byte(A)-- 输出 ASCII 码值
print(asciiValue) -- 输出 655.6 字符串型变量
字符串由一对双引号或单引号来表示
a hello
b worldprint(a,b) -- hello world支持在字符串中插入转义字符
c hello\nworld
print(c) -- helloworld长字符串
d [[hello
world
!]]print(d)获取字符串长度(#)
a hello world
print(#a) --11字符串合并(…)
a hello
b world
c a..b
print(c) -- helloworld数值字符可以和数值直接进行运算
a 10 1
print(a) -- 11.0tostring() 和 tonumber()
a tostring(10)
print(type(a)) --stringb tonumber(10)
print(type(b)) --number-- 转换失败 nil
c tonumber(abc)
print(type(c)) --nil6.运算符
Lua 和 C 中的对比
赋值运算符:
Lua: (单等号)C:
算术运算符:
Lua: , -, *, /, %C: , -, *, /, %
关系运算符:
Lua: , ~, , , , C: , !, , , ,
逻辑运算符:
Lua: and, or, notC: , ||, !
位运算符:
Lua: , |, ~, , C: , |, ~, ,
连接运算符:
Lua: ..用于连接字符串C: 用于连接字符串
其他运算符:
Lua: #取长度、:用于对象方法调用C: sizeof取大小
7. 控制流语句
7.1 选择语句
7.1.1 if then else
if condition then-- 当 condition 为 true 时执行这里的代码
else-- 当 condition 为 false 时执行这里的代码
end-- 定义一个变量
local temperature 25-- 判断温度是否超过 20 度
if temperature 20 thenprint(天气很热建议穿短袖)
elseprint(天气不算太热可以穿长袖)
end7.1.2 if then elseif then end
if condition1 then-- 当 condition1 为 true 时执行这里的代码
elseif condition2 then-- 当 condition1 不满足而 condition2 为 true 时执行这里的代码
else-- 当上述条件都不满足时执行这里的代码
end-- 定义一个变量
local hour 15-- 判断当前时间段
if hour 12 thenprint(现在是上午)
elseif hour 12 and hour 18 thenprint(现在是下午)
elseprint(现在是晚上)
end7.1.3 三目运算符
local result condition and value1 or value2--如果 condition 为 true则返回 value1否则返回 value2-- 定义一个变量
local score 85-- 使用三元运算符判断成绩是否及格
local result score 60 and 及格 or 不及格-- 输出结果
print(成绩 .. score .. 考试结果 .. result)ps 无 switch/case
注意Lua 中没有直接的 switch/case 语句。但你可以使用多个 if-elseif-else 结构来模拟类似的行为
local choice 2
if choice 1 then-- 处理选择 1 的情况
elseif choice 2 then-- 处理选择 2 的情况
elseif choice 3 then-- 处理选择 3 的情况
else-- 处理其他情况
end7.2 循环语句
7.2.1.for 循环
7.2.1.1 数值型for 循环
for var startValue, endValue, stepValue do-- 循环体
endvar 是循环变量它从 startValue 开始递增直到达到或超过 endValue每次递增 stepValue。startValue、endValue 和 stepValue 是可选的默认值分别为 1、endValue、1。循环体会在每次迭代时执行循环结束后循环变量 var 的值会保留在循环作用域中(追踪循环结束时的变量值、利用循环变量的最终值进行后续操作、利用循环变量的最终值进行条件判断)。
for i 1, 5 doprint(数值型 for 循环第 .. i .. 次迭代)
end7.2.1.2 泛型 for 循环
for index, value in ipairs(iterable) do-- 循环体
enditerable 是一个可迭代的对象例如数组或表。在每次迭代时index 和 value 分别表示当前元素的索引和值。ipairs() 函数用于迭代数组类型的表它返回三个值迭代函数、表、初始值。
local fruits {apple, banana, orange}
for index, fruit in ipairs(fruits) doprint(泛型 for 循环第 .. index .. 个水果是 .. fruit)
end7.2.2 while 循环
while condition do-- 循环体
endwhile 循环会在 condition 为 true 时执行循环体直到 condition 为 false 才停止循环。
local j 1
while j 5 doprint(while 循环第 .. j .. 次迭代)j j 1
end7.2.3 repeat until 循环
repeat-- 循环体
until conditionrepeat until 循环会先执行一次循环体然后检查 condition如果 condition 为 true则继续执行循环体直到 condition 为 false 才停止循环。
local k 1
repeatprint(repeat until 循环第 .. k .. 次迭代)k k 1 -- lua 没有 k 也可以 k 1
until k 58.函数
8.1 函数定义
optional_function_scope function function_name( argument1, argument2, argument3..., argumentn)function_bodyreturn result_params_comma_separated
endoptional_function_scope: 该参数是可选的指定函数是全局函数还是局部函数未设置该参数默认为全局函数如果你需要设置函数为局部函数需要使用关键字 local。function_name: 指定函数名称。argument1, argument2, argument3…, argumentn: 函数参数多个参数以逗号隔开函数也可以不带参数。function_body: 函数体函数中需要执行的代码语句块。result_params_comma_separated: 函数返回值Lua语言函数可以返回多个值每个值以逗号隔开。
--函数返回两个值的最大值
function max(num1, num2)if (num1 num2) thenresult num1;elseresult num2;endreturn result;
end8.2 函数调用
函数调用可以通过函数名加上一对圆括号来完成可以传入函数定义中所需的参数。
-- 调用函数
print(两值比较最大值为 ,max(10,4))
print(两值比较最大值为 ,max(5,6))8.3 多返回值
在 Lua 中函数可以返回多个值。调用函数时可以使用逗号分隔多个返回值。
function f()return 1, 2, 3
endlocal a, b, c f()
print(a, b, c) -- 输出: 1 2 38.4 匿名函数
匿名函数在 Lua 中是一种特殊的函数它们不需要显式地命名通常用于一次性的、简单的操作或作为其他函数的参数。
local double function(x)return x * 2
endprint(double(5)) -- 输出: 108.5 函数作为参数和返回值
在 Lua 中函数可以作为参数传递给其他函数也可以作为其他函数的返回值。
function applyFunction(func, value)return func(value)
endprint(applyFunction(double, 5)) -- 输出: 108.6 变长参数
在 Lua 中函数可以接受变长参数可以通过 ... 表示。可以使用 select() 函数获取变长参数的值
function sum(...)local result 0for i 1, select(#, ...) doresult result select(i, ...)endreturn result
endprint(sum(1, 2, 3, 4, 5)) -- 输出: 15ps : select
在 Lua 中select 是一个用于操作可变数量参数的函数。它可以用于获取可变参数的数量和值。
select 函数的一般形式为
select(index, ...)其中
index 是一个索引值用于选择可变参数列表中的参数。... 是可变参数列表。
select 函数有两种主要用法 获取可变参数的数量 当 index 的值为 # 时select 函数返回可变参数的数量。 示例 luaCopy codelocal count select(#, 1, 2, 3, 4, 5)
print(count) -- 输出: 5获取可变参数的值 当 index 的值为一个整数时select 函数返回可变参数列表中对应索引位置的参数值。 示例 luaCopy codelocal value select(3, a, b, c, d)
print(value) -- 输出: c在这个示例中select(3, a, b, c, d) 返回可变参数列表中第 3 个参数的值即 c。
需要注意的是select 函数只能用于处理从 1 开始的索引位置而不支持负数索引。如果 index 大于可变参数的数量select 函数返回 nil。
8.数组
数组就是相同数据类型的元素按一定顺序排列的集合可以是一维数组和多维数组。在 Lua 中数组不是一种特定的数据类型而是一种用来存储一组值的数据结构。实际上Lua 中并没有专门的数组类型而是使用一种被称为 “table” 的数据结构来实现数组的功能。Lua 数组的索引键值可以使用整数表示数组的大小不是固定的。在 Lua 索引值是以 1 为起始。
-- 创建一个数组
local myArray {10, 20, 30, 40, 50}-- 访问数组元素
print(myArray[1]) -- 输出 10
print(myArray[3]) -- 输出 30
print(myArray[-1]) -- 输出 50要计算数组的长度即数组中元素的个数你可以使用 # 操作符
local myArray {10, 20, 30, 40, 50}-- 计算数组长度
local length #myArrayprint(length) -- 输出 5一维数组可以用 for 循环出数组中的元素
-- 创建一个数组
local myArray {10, 20, 30, 40, 50}-- 循环遍历数组
for i 1, #myArray doprint(myArray[i])
end9.table(表)
在 Lua 中table 是一种用来保存多个值的数据结构它类似于其他编程语言中的数组、列表、字典或哈希表。table 是 Lua 中最重要的数据结构之一也是 Lua 的核心之一。
9.1 数字下标
数字下标的表是 Lua 中常见的数据结构通常用来表示数组或列表。在这样的表中键是从 1 开始的整数索引对应的值可以是任意类型的 Lua 值。
9.1.1 元素组成
在 Lua 的数字下标表中每个元素可以是任何 Lua 支持的数据类型包括但不限于
数字number整数或浮点数。
字符串string任意长度的文本字符串。
布尔值booleantrue 或 false。
表table嵌套的表用来表示更复杂的数据结构。
函数function可执行的代码块。
线程threadLua 的协程用于实现轻量级并发。 用户数据userdataC 语言中的数据类型通常由 Lua 扩展库创建。 这意味着你可以将任何 Lua 支持的数据类型存储在数字下标表中的元素中。例如你可以创建一个包含字符串、数字和表的数组或者将函数作为数组的元素以及其他更复杂的数据组合。
local myArray {10, hello, true, {20, 30}, function() print(This is a function) end}9.1.2 元素访问
在 Lua 中数组的索引从 1 开始所以第一个元素的索引是 1第二个元素的索引是 2以此类推。
print(myArray[1]) -- 输出: 10
print(myArray[2]) -- 输出: hello
print(myArray[3]) -- 输出: true
print(myArray[4][1]) -- 输出: 20
myArray[5]() -- 输出: This is a function如果在数字下标表中某个索引位置没有存储任何值Lua 会返回 nil。
print(myArray[5]) --输出: nil 9.1.3 添加元素
以下是几种常见的往数字下标表中添加元素的方法
①直接赋值
可以直接通过索引赋值的方式往表中添加元素。
luaCopy codelocal myArray {10, 20, 30}-- 直接赋值给新的索引位置
myArray[4] 40②使用 table.insert() 函数
可以使用 table.insert() 函数往数组末尾添加新元素。
luaCopy codelocal myArray {10, 20, 30}-- 使用 table.insert() 函数往数组末尾添加新元素
table.insert(myArray, 40)pstable.insert()
table.insert (table, [pos,] value)
在table的数组部分指定位置(pos)插入值为value的一个元素. pos参数可选, 默认为数组部分末尾.
luaCopy codelocal myArray {10, 20, 30}-- 使用 table.insert() 函数往数组第二个位置添加新元素
table.insert(myArray,2, 40)--myArray {10, 40,20, 30}③使用 # 操作符
可以使用 # 操作符来获取数组长度然后在长度加一的位置赋值。
luaCopy codelocal myArray {10, 20, 30}-- 在数组长度加一的位置赋值
myArray[#myArray 1] 409.1.4 删除元素
①使用 table.remove() 函数
table.remove() 函数用于删除数组中的元素。它接受两个参数数组和要删除的元素的索引。删除元素后后续的元素会向前移动填补空缺。如果不指定索引则默认删除数组的最后一个元素。
luaCopy codelocal myArray {10, 20, 30, 40}
table.remove(myArray) -- 删除最后一个元素luaCopy codelocal myArray {10, 20, 30, 40}
table.remove(myArray, 2) -- 删除索引为 2 的元素第二个元素 20 将被删除数组变成 {10, 30, 40}。
pstable.remove() 返回值
table.remove() 函数在删除元素后会返回被删除的元素的值。如果指定了要删除的元素的索引则返回该索引位置上的元素值如果没有指定索引则默认删除数组的最后一个元素并返回该元素的值。
local myArray {10, 20, 30, 40}
local removedValue table.remove(myArray, 2) -- 删除索引为 2 的元素
print(removedValue) -- 输出: 20local myArray {10, 20, 30, 40}
local removedValue table.remove(myArray) -- 删除数组的最后一个元素
print(removedValue) -- 输出: 40②将要删除的元素赋值为 nil
直接将要删除的元素的位置赋值为 nil这会将该位置上的元素删除但不会改变数组的长度或索引。
luaCopy codelocal myArray {10, 20, 30, 40}
myArray[2] nil -- 删除索引为 2 的元素在这个示例中第二个元素 20 将被删除数组变成 {10, nil, 30, 40}。 注意虽然元素被删除了但数组长度仍然保持不变。
9.2 键值对
local myTable {key1 value1, key2 value2}9.2.1 键值组成
在 Lua 中表的键key和值value可以是任何类型的 Lua 值包括但不限于
字符串string可以作为键和值的类型字符串是 Lua 中最常见的数据类型之一。数字number同样可以作为键和值的类型包括整数和浮点数。布尔值boolean可以作为键和值的类型表示逻辑上的真true和假false。表table可以作为值的类型允许嵌套表以构建复杂的数据结构。函数function可以作为值的类型表示可执行的代码块。用户数据userdata一种特殊的数据类型通常由 Lua 扩展库创建。线程thread用于实现轻量级并发的数据类型通常用于协程。nil表示空值或无效值的特殊类型可以作为键和值的类型。
local myTable {[name] John, -- 字符串作为键[42] answer, -- 数字作为键[true] yes, -- 布尔值作为键[{}] empty table, -- 表作为键[function() return key end] computed key, -- 函数作为键[array] {1, 2, 3}, -- 数组作为值[nestedTable] { -- 嵌套表作为值[key1] value1,[key2] value2},[nilValue] nil -- nil 作为值
}Lua 中键和值可以不带方括号。当键是字符串或者符合 Lua 变量命名规则的标识符时可以直接使用键名来定义键值对而无需使用方括号
local myTable {name John, -- 字符串作为键age 30, -- 字符串作为键isAdult true, -- 字符串作为键hobbies {reading, swimming}, -- 字符串作为键, 表作为值greet function() print(Hello, Lua!) end, -- 字符串作为键, 函数作为值
}9.2.2 值访问
要访问 Lua 表中的值可以使用下标键来获取对应的值。在 Lua 中可以使用表的键来访问表中的值这可以通过使用方括号加上键名或者直接使用键名来完成。
local myTable {name John,age 30,isAdult true,hobbies {reading, swimming},greet function() print(Hello, Lua!) end,
}-- 使用方括号加上键名来访问表中的值
print(myTable[name]) -- 输出: John
print(myTable[age]) -- 输出: 30-- 直接使用键名来访问表中的值
print(myTable.name) -- 输出: John
print(myTable.age) -- 输出: 309.2.3 添加元素
直接赋值
直接通过赋值操作来向表中添加新元素如果键不存在则会创建新的键值对
local myTable {} -- 创建一个空表-- 直接赋值给新的键
myTable[name] John
myTable[age] 309.2.4 删除元素
将要删除的元素赋值为 nil
local myTable {name John, age 30, city New York}-- 删除键为 age 的整个键值对
myTable[age] nil9.2.5 遍历元素
pairs() 遍历表中所有的键值对
pairs()的使用格式:
for key, value in pairs(table) do-- 在这里处理 key 和 value
end其中table 是要迭代的表key 和 value 分别是每次迭代中表中的键和对应的值。
local myTable {name John, age 30, city New York}for key, value in pairs(myTable) doprint(key, value)
end