posts - 6,  comments - 2,  trackbacks - 0
对于一个编程语言来说,定制各种需要的数据结构是一项重要的能力,如果定制的手段非常精简,将会获得极大的开发效率提升,而构建的手段针对当前计算机底层很贴合,则可以有机会获得非常高的性能。
对于定制数据结构来说,最基础的一项操作就是,遍历所有内容,因为有了遍历,基本上就有了“读”的功能。
大家都知道,不同的数据结构无论是外在形态还是内部结构都相差甚远,有什么办法能提供一个统一的接口对内部所有数据进行便利呢?这就是所谓“迭代器”。
以C++为例,遍历一个vector:
#include <iostream>
#include 
<vector>

int main(int argc, char *argv[])
{
    std::vector
<int> a = {123};
    
for (std::vector<int>::iterator iter = a.begin(); iter != a.end(); ++iter)
    {
        std::cout 
<< *iter << std::endl;
    }
    
return 0;
}


我们可以看到,它定义了一个新类型,叫std::vector<int>::iterator,这么个类型就是迭代器类型。从直觉上看他就是给访问数据提供个类似指针的接口而已,实际上这个迭代器变量还有另一个重要功能,就是“保存状态”,有了这个状态,才能知道下一次迭代能得到什么结果。
后来C++11标准出来后在语法方面进行了加强,淡化了保存状态这么个过程,写出的代码显得更加简洁:
#include <iostream>
#include 
<vector>

int main(int argc, char *argv[])
{
    std::vector
<int> a = {123};
    
for (auto iter : a)
    {
        std::cout 
<< iter << std::endl;
    }
    
return 0;
}

当然底层该有的操作是不会少的。

有了“保存状态”这个概念,实现编程语言的时候,就可以快速排除掉一些不靠谱的方案。
比如,不要迭代器而把状态保存在数据结构内部行不行?当然不行,考虑以下代码:
#include <iostream>
#include 
<vector>

int main(int argc, char *argv[])
{
    std::vector
<int> a = {123};
    
for (std::vector<int>::iterator iter = a.begin(); iter != a.end(); ++iter)
    {
        std::cout 
<< *iter << "";
        
for (std::vector<int>::iterator iter2 = a.begin(); iter2 != a.end(); ++iter2)
        {
            std::cout 
<< *iter2 << " ";
        }
        std::cout 
<< std::endl;
    }
    
return 0;
}

我们就知道,访问状态有时候是需要保存多份的,而对于引用类型的对象来说,状态要想在内部保存多份会更加复杂,还不如用显式的状态保存。
直接修改数据结构内部呢?比如用类似car和cdr循环赋值的方式进行遍历。这一样行不通,如果复制保存的引用类型真实数据,则代价太大,看不出引用类型的好处,而直接修改则会破坏数据本身,而数据可能之后还要使用。

以下Python作为例子如何创建一个可迭代的,Range对象:
class Range:
    
def __init__(self, low, high):
        self.cur 
= low
        self.high 
= high
        
    
def __iter__(self):
        
return self

    
def next(self):
        
if self.cur >= self.high:
            
raise StopIteration
        
else:
            v 
= self.cur
            self.cur 
+= 1
            
return v

for item in Range(13):
    
print item

创建对象的时候,执行了初始化方法和__iter__方法,在迭代的过程中则执行了和next方法,并且以StopIteration异常作为迭代结束的标志。
posted on 2014-10-11 17:10 呜呜 阅读(679) 评论(2)  编辑 收藏 引用

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理