-- function_test.lua 脚本文件 functionfactorial1(n) if n == 0then return1 else return n * factorial1(n - 1) end end print(factorial1(5)) factorial2 = factorial1 print(factorial2(5))
脚本执行结果为:
1 2 3
$ lua function_test.lua 120 120
function 可以以匿名函数(anonymous function)的方式通过参数传递:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
-- function_test2.lua 脚本文件 functiontestFun(tab,fun) for k ,v inpairs(tab) do print(fun(k,v)); end end
tab={key1="val1",key2="val2"}; testFun(tab, function(key,val)--匿名函数 return key.."="..val; end );
> s, e = string.find("www.runoob.com", "runoob") > print(s, e) 510
Lua函数中,在return后列出要返回的值的列表即可返回多值,如:
1 2 3 4 5 6 7 8 9 10 11 12 13
functionmaximum(a) local mi = 1-- 最大值索引 local m = a[mi] -- 最大值 for i,val inipairs(a) do if val > m then mi = i m = val end end return m, mi end
print(maximum({8,10,23,12,5}))
以上代码执行结果为:
1
23 3
可变参数
Lua 函数可以接受可变数目的参数,和 C 语言类似,在函数参数列表中使用三点 … 表示函数有可变的参数。
1 2 3 4 5 6 7 8
functionadd(...) local s = 0 for i, v inipairs{...} do--> {...} 表示一个由所有变长参数构成的数组 s = s + v end return s end print(add(3,4,5,6,7)) --->25
通过 select("#",...) 来获取可变参数的数量:
1 2 3 4 5 6 7 8 9 10 11
functionaverage(...) result = 0 localarg={...} for i,v inipairs(arg) do result = result + v end print("总共传入 " .. select("#",...) .. " 个数") return result/select("#",...) end
print("平均值为",average(10,5,3,4,5,6))
以上代码执行结果为:
1 2
总共传入 6 个数 平均值为 5.5
如果是几个固定参数加上可变参数,固定参数必须放在变长参数之前
1 2 3 4 5 6
functionfwrite(fmt, ...)---> 固定的参数fmt returnio.write(string.format(fmt, ...)) end
# o 打开关闭文件或目录 # e 以文件管理的方式打开选中的目录 # t 在标签页中打开 # T 在标签页中打开,但光标仍然留在 NERDTree # r 刷新光标所在的目录 # R 刷新当前根路径 # X 收起所有目录 # p 小写,跳转到光标所在的上一级路径 # P 大写,跳转到当前根路径 # J 到第一个节点 # K 到最后一个节点 # I 显示隐藏文件 # m 显示文件操作菜单 # C 将根路径设置为光标所在的目录 # u 设置上级目录为根路径 # ctrl + w + w 光标自动在左右侧窗口切换 # ctrl + w + r 移动当前窗口的布局位置 # :tabc 关闭当前的 tab # :tabo 关闭所有其他的 tab # :tabp 前一个 tab # :tabn 后一个 tab # gT 前一个 tab # gt 后一个 tab
static Quadrant GetQuadrant(Point point) => point switch { (0, 0) => Quadrant.Origin, var (x, y) when x > 0 && y > 0 => Quadrant.One, var (x, y) when x < 0 && y > 0 => Quadrant.Two, var (x, y) when x < 0 && y < 0 => Quadrant.Three, var (x, y) when x > 0 && y < 0 => Quadrant.Four, var (_, _) => Quadrant.OnBorder, _ => Quadrant.Unknown };
using 声明
using 声明是前面带 using 关键字的变量声明。它指示编译器声明的变量应在封闭范围的末尾进行处理。
staticintWriteLinesToFile(IEnumerable<string> lines) { // 当到达方法的右括号时,将对该文件进行处理。 usingvar file = new System.IO.StreamWriter("WriteLines2.txt"); // Notice how we declare skippedLines after the using statement. int skippedLines = 0; foreach (string line in lines) { if (!line.Contains("Second")) { file.WriteLine(line); } else { skippedLines++; } } // Notice how skippedLines is in scope here. return skippedLines; // file is disposed here }
静态本地函数
1 2 3 4 5 6 7 8
intM() { int y = 5; int x = 7; return Add(x, y);
staticintAdd(int left, int right) => left + right; }
var words = newstring[] { // index from start index from end "The", // 0 ^9 "quick", // 1 ^8 "brown", // 2 ^7 "fox", // 3 ^6 "jumped", // 4 ^5 "over", // 5 ^4 "the", // 6 ^3 "lazy", // 7 ^2 "dog"// 8 ^1 }; // 9 (or words.Length) ^0
// 使用 ^1 索引检索最后一个词 Console.WriteLine($"The last word is {words[^1]}"); // writes "dog"
// 包括 words[1] 到 words[3] var quickBrownFox = words[1..4];
// 包括 words[^2] 和 words[^1] var lazyDog = words[^2..^0];
var allWords = words[..]; // contains "The" through "dog". var firstPhrase = words[..4]; // contains "The" through "fox" var lastPhrase = words[6..]; // contains "the", "lazy" and "dog"
publicstaticintSumPositiveNumbers(IEnumerable<object> sequence) { int sum = 0; foreach (var i in sequence) { switch (i) { case0: break; case IEnumerable<int> childSequence: { foreach(var item in childSequence) sum += (item > 0) ? item : 0; break; } caseint n when n > 0: sum += n; break; casenull: thrownew NullReferenceException("Null found in sequence"); default: thrownew InvalidOperationException("Unrecognized type"); } } return sum; }
case 0: 是常见的常量模式。
case IEnumerable childSequence: 是一种类型模式。
case int n when n > 0: 是具有附加 when 条件的类型模式。
case null: 是 null 模式。
default: 是常见的默认事例。
Ref 局部变量和返回结果
此功能允许使用并返回对变量的引用的算法,这些变量在其他位置定义。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
publicstaticrefintFind(int[,] matrix, Func<int, bool> predicate) { for (int i = 0; i < matrix.GetLength(0); i++) for (int j = 0; j < matrix.GetLength(1); j++) if (predicate(matrix[i, j])) returnref matrix[i, j]; thrownew InvalidOperationException("Not found"); }
public Task<string> PerformLongRunningWork(string address, int index, string name) { if (string.IsNullOrWhiteSpace(address)) thrownew ArgumentException(message: "An address is required", paramName: nameof(address)); if (index < 0) thrownew ArgumentOutOfRangeException(paramName: nameof(index), message: "The index must be non-negative"); if (string.IsNullOrWhiteSpace(name)) thrownew ArgumentException(message: "You must supply a name", paramName: nameof(name));
return longRunningWorkImplementation();
async Task<string> longRunningWorkImplementation() { var interimResult = await FirstWork(address); var secondResult = await SecondStep(index, name); return$"The results are {interimResult} and {secondResult}. Enjoy."; } }
更多的 expression-bodied 成员
C# 7.0 扩展了可作为表达式实现的允许的成员。 在 C# 7.0 中,你可以在属性和索引器上实现构造函数、终结器以及 get 和 set 访问器。 以下代码演示了每种情况的示例:
publicvoidChangeName(string newLastName) { // Generates CS0200: Property or indexer cannot be assigned to -- it is read only LastName = newLastName; } }
自动属性初始化
自动属性初始值设定项 可让你在属性声明中声明自动属性的初始值。
1
public ICollection<double> Grades { get; } = new List<double>();
publicstaticasync Task<string> MakeRequestAndLogFailures() { await logMethodEntrance(); var client = new System.Net.Http.HttpClient(); var streamTask = client.GetStringAsync("https://localHost:10000"); try { var responseText = await streamTask; return responseText; } catch (System.Net.Http.HttpRequestException e) when (e.Message.Contains("301")) { await logError("Recovered from redirect", e); return"Site Moved"; } finally { await logMethodExit(); client.Dispose(); } }
使用索引器初始化关联集合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// 原来语法 private Dictionary<int, string> messages = new Dictionary<int, string> { { 404, "Page not Found"}, { 302, "Page moved, but left a forwarding address."}, { 500, "The web server can't come out to play today."} };
// 新语法支持使用索引分配到集合中: private Dictionary<int, string> webErrors = new Dictionary<int, string> { [404] = "Page not Found", [302] = "Page moved, but left a forwarding address.", [500] = "The web server can't come out to play today." };
using MongoDB.Bson; using MongoDB.Driver; using System; using System.Collections.Generic; using System.Text.RegularExpressions; using System.Threading.Tasks;