neovim 0.5正式版本已经发布了,现在学习Lua语言还来的及吧。lua替换vim脚本渐渐成为了趋势了。
Lua学习下来,感觉与javascript特别的像。就是代码块不是使用{}分割,而是end,需要习惯一下。代码阅读问题不大,自己写代码还是要适应一下。
Lua中有一些好玩的语法,用起来比Java,Javascript简单,爽!
我学习的教程文档:
https://www.lua.org/pil/contents.html
文章写的简单明了,推荐阅读。
network = {
{name = "grauna", IP = "210.26.30.34"},
{name = "arraial", IP = "210.26.30.23"},
{name = "lua", IP = "210.26.23.12"},
{name = "derain", IP = "210.26.23.20"},
}
table.sort(network,function (a,b)
return (a.name > b.name)
end)
print("输出")
for _,line in ipairs(network) do
print(line.name)
end
names = {"Peter","Paul","Mary"}
grades= {Mary =10,Paul =7,Peter=8}
table.sort(names,function (n1, n2)
return grades[n1] > grades[n2]
end)
print("------输出排序结果------")
for _,line in ipairs(names) do
print(line)
end
示例中有趣的一点是给定的匿名函数sort 访问参数grades,该参数对于封闭函数来说是本地的sortbygrade。在这个匿名函数内部, grades既不是全局变量也不是局部变量。我们称它为外部局部变量或upvalue。(术语“upvalue”有点误导,因为它grades是一个变量,而不是一个值。然而,这个术语在 Lua 中有历史渊源,它比“外部局部变量”短。)
names = {"Peter","Paul","Mary"}
grades= {Mary =10,Paul =7,Peter=8}
function sortbygrade(names,grades)
table.sort(names,function(n1,n2)
return grades[n1] > grades[n2]
end)
end
sortbygrade(names,grades)
print("------输出排序结果------")
for _,line in ipairs(names) do
print(line)
end
https://www.lua.org/pil/6.1.html
这个特性跟我想像的不太一样。
So, c1 and c2 are different closures over the same function and each acts upon an independent instantiation of the local variable i. Technically speaking, what is a value in Lua is the closure, not the function. The function itself is just a prototype for closures. Nevertheless, we will continue to use the term “function” to refer to a closure whenever there is no possibility of confusion.
因此,c1和c2是同一函数上的不同闭包,每个闭包都作用于局部变量的独立实例化i。从技术上讲,Lua 中的值是闭包,而不是函数。函数本身只是闭包的原型。尽管如此,只要没有混淆的可能性,我们将继续使用术语“函数”来指代闭包。
function newCounter()
local i = 0
return function () --匿名函数
i = i + 1
return i
end
end
c1 = newCounter()
print(c1()) -->1
print(c1()) -->2
c2 = newCounter()
print(c2()) -->1
print(c1()) -->3
print(c2()) -->2
这样的写法我以前基本没用过,为了测试我的理解,我写了个javascript版本的。执行结果竟然一样的。看来是我一直理解的有问题。
结果与Lua版本一至。
function newCounter(){
let i = 0;
return function(){
i = i+1;
return i;
}
}
let c1 = newCounter()
console.log(c1()); //>1
console.log(c1()); //>2
let c2=newCounter()
console.log(c2());//>1
console.log(c1());//>3
console.log(c2());//>2
我就思考如何在java中写出类似的代码呢?Java中好像没有匿名方法吧?
public static void main(String[] args) {
System.out.println(newCounter());//>1
System.out.println(newCounter());//>1
System.out.println(newCounter());//>1
}
public static int newCounter() {
int i = 0;
return i + 1;
}
显然这样写是不对的,估计要用匿名内部类的方式处理吧。
为了模拟上面的逻辑,我使用java中的类实现。执行结果一至。
public class Main {
public static void main(String[] args) {
class NewCounter{
int i =0;
public NewCounter() {
}
@Override
public String toString() {
i = i+1;
return String.valueOf(i);
}
}
NewCounter c1 = new NewCounter();
System.out.println(c1);//>1
System.out.println(c1);//>2
NewCounter c2 = new NewCounter();
System.out.println(c2);//>1
System.out.println(c1);//>3
System.out.println(c2);//>2
}
}
总结:
Closures中的变量感觉类似与Java中的类属性,很个实例单独管理。
Lib = {}
Lib.foo = function (x,y) return x + y end
Lib.goo = function (x,y) return x - y end
或
Lib = {
foo = function (x,y) return x + y end,
goo = function (x,y) return x - y end
}
或
Lib = {}
function Lib.foo (x,y)
return x + y
end
function Lib.goo (x,y)
return x - y
end
错误的❌
local fact = function (n)
if n == 0 then return 1
else return n*fact(n-1) -- buggy
end
end
正确✅
local fact
fact = function (n)
if n == 0 then return 1
else return n*fact(n-1)
end
end
现在fact函数内部指的是局部变量。它在定义函数时的值无关紧要;到函数执行时, fact已经有了正确的值。这就是 Lua 为本地函数扩展其语法糖的方式,因此您可以将其用于递归函数而无需担心:
local function fact (n)
if n == 0 then return 1
else return n*fact(n-1)
end
end
https://www.lua.org/pil/contents.html#P1