迭代器的真实含义

简介: 迭代器的真实含义

迭代器”这个词多少有点误导性,这是因为迭代器并没有进行实际的迭代:真正的迭代是 for 循环完成的,迭代器只不过为每次的迭代提供连续的值。或许,称其为“生成器”更好,表示为迭代生成元素;不过,“迭代器”这个名字已经在诸如 Java 等其他语言中被广泛使用了。


然而,还有一种创建迭代器的方式可以让迭代器进行实际的迭代操作。当使用这种迭代器时,就不需要编写循环了。相反,只需要调用这个迭代器,并传入一个描述了在每次迭代时迭代器需要做什么的参数即可。更准确的说,迭代器接收了一个函数作为参数,这个函数在循环的内部被调用,这种迭代器就被称为真正的迭代器


如下所示:

function allwords(f)
  for line in io.lines() do
    for word in string.gmatch(line, "%w+") do
      f(word)
    end
  end
end


使用这个迭代器时,我们必须传入一个函数作为循环体。如果我们只想输出每个单词,那么简单地使用函数 print 即可:

allwords(print)


通常,我们可以使用一个匿名函数作为循环体。例如,以下的代码用于计算单词"hello"在输入文本中出现的次数:

local count = 0
allwords(function (w)
  if w == "hello" then count = count + 1 end
end)
print(count)


同样的需求,如果采用之前的迭代器风格,差异也不是特别大:

local count = 0
for w in allwords() do
  if w == "hello" then count = count + 1 end
end
print(count)


真正的迭代器在老版本的 Lua 语言中曾经非常流行,那是还没有 for 语句。


真正的迭代器与生成器风格的迭代器想比怎么样呢?这两种风格都有大致相同的开销,即每次迭代都有一次函数调用。一方面,编写真正的迭代器比较容易。另一方面,生成器风格的迭代器则更加灵活。首先,生成器风格的迭代器允许两个或更多个并行的迭代。其次,生成器风格的迭代器允许在循环体重使用 breakreturn 语句。使用真正的迭代器, return 语句从匿名函数中返回而并非从进行迭代的函数中返回。基于这些原因,高级 Lua 语言中一般更喜欢生成器风格的迭代器

目录
相关文章
|
9月前
|
算法 编译器 C语言
【C++ 迭代器的空类类型 】深入理解C++迭代器类别与空类标签的奥秘
【C++ 迭代器的空类类型 】深入理解C++迭代器类别与空类标签的奥秘
97 0
|
开发框架 .NET C#
c#数组补充
c#数组的几个简单的补充
49 0
|
9月前
|
存储 Java API
Java数组元素的填充与替换技术详解
Java数组元素的填充与替换技术详解
103 1
|
9月前
|
存储 Java 索引
Java数组的地址值与元素访问技术
Java数组的地址值与元素访问技术
86 2
|
9月前
|
存储 编译器 C++
【C++/STL】list(常见接口、模拟实现、反向迭代器、)
【C++/STL】list(常见接口、模拟实现、反向迭代器、)
67 0
|
9月前
2020-10-10 数组和对象的区分方法
2020-10-10 数组和对象的区分方法
|
9月前
|
算法 数据处理 C语言
【C++迭代器深度解析】C++迭代器类型之间的继承关系与反向迭代器的独特性
【C++迭代器深度解析】C++迭代器类型之间的继承关系与反向迭代器的独特性
142 0
|
9月前
|
并行计算 算法 安全
【C++ 迭代器 】C++ 迭代器标签的使用场景
【C++ 迭代器 】C++ 迭代器标签的使用场景
108 0
|
9月前
|
C++
stl判断数据的类型
stl判断数据的类型
重生之我是孔乙己——查找数组缺失元素的几种方法
重生之我是孔乙己——查找数组缺失元素的几种方法
90 0