lazy ideas in programming(编程中的惰性思想)

目录
lazy ideas:singleton
proxy:
Short-circuit evaluation:
generator:
函数式编程语言中的应用:

cache:
Dirty Flag:
CopyOnWrite:
web开发中的惰性加载与惰性预加载:

总结:

正文
  lazy形容词,懒惰的,毫无疑问是一个贬义词。但是,对于计算机领域,lazy却是非常重要的优化思想:把任务推迟到必须的时刻,好处是避免重复计算,甚至不计算。本文的目的是抛砖引玉,总结一些编程中的lazy idea,以期有一些启发。google “lazy”这个单词,在计算机领域高频出现三个词:lazy loading(惰性加载)、lazy initializing(惰性初始化)、lazy evaluation(惰性求值),本文并不刻意区分,因为不管是loading、initializing还是evaluation都需要耗费计算机的运算资源,而且,loading(initializing)也是某种意义上的evaluation。

lazy ideas:
回到顶部
  在GOF的设计模式中,并没有一个叫“lazy loading”之类的设计模式,但是其思想贯穿在很多设计模式中。其中比较明显的就是singleton和proxy模式。
singleton
  单例模式的实现一般都有两种方式,要么在调用之前就创建好单例对象(eager way),要么在第一次调用的时候生成单例对象(lazy way),两者对象的代码大致是这样的:

PS:在python中,这样使用单例模式不是很pythonic,更好的办法可见在stackoverflow上的这篇文章《creating-a-singleton-in-python》。另外在多线程环境下,要实现线程安全的单例还是很复杂的,具体讨论可参见iteye上的分析。

proxy:
  代理模式属于责任型模式, 使得一个对象代表另一个对象进行各种操作,常用场景包括remote proxy(远程代理),如RMI, RPC

virtual proxy(虚代理),根据需要创建开销很大的对象,如文档中图片的加载

(保护代理):控制对原始对象的访问, 如智能指针

其中 viatual proxy是使用lazy loading很好的例子

Short-circuit evaluation:
  短路求值在绝大多数编程语言都有实现,比较常见的语法如下:
    x and y(x && y)
    x or y(x || y)
    x if bool else y(bool? x : y )
  短路求值基本上都是数学逻辑的体现,如果第一个参数已经能推导出这个表达式的意义,那么后面的参数是无需计算的。短路求值非常有用,不仅能避免无用的计算,对于逻辑判断也非常有用。比如在python中,判断一个对象的is_ok属性为True,我们一般这么写
  if(obj.is_ok)
  如果obj被赋值成了None,那么就会报一个异常,所以可以写成
  if(obj is not None and obj.is_ok)

python中,一些函数也有短路求值的特性,比如在这篇文章中提到的any函数:

本意是希望对所有的element都计算,然后返回一个结果,但事实上由于短路求值, 可能后面很多的元素都不会再调用calc_and_ret

generator:
  在python和javascript语言中都有generator,generator与普通的函数相比,可以多次(甚至无限次)返回,而且返回值是在需要的时候才生成。在python中,下面两段代码非常相似,但事实上差异非常大:
1     for x in [ii for i in xrange(10000)]2       # do sth with i3 4     for x in (ii for i in xrange(10000)]5       # do sth with i

generator更广泛的应用可以参见《python yield generator 详解》。javascript中generator的语法和使用与python都非常类似,可以参见这篇文章

函数式编程语言中的应用:
  lazy evaluation在函数式编程语言中使用得非常频繁,python也可以当做函数式编程语言来使用,而更为明显的是haskell,在其首页的features介绍里面就有大大的“lazy”

cache:
  cache也是一种lazy思想,如果之前有计算结果,那么直接复用之前的结果就行了,干嘛还要重新计算呢?而且最开始的缓存内容, 也是在需要的时候才计算的,而不是一开始就计算好。wiki上有python实现的简单例子:

Dirty Flag:
  在《Dirty Flag模式及其应用》一文中,列举了Dirty Flag模式的诸多应用场景。Dirty Flag显然也是很明显的lazy evaluation。比如《game programming pattern》中的例子:子模型的世界坐标取决于父模型的世界坐标以及子模型在父模型坐标空间的相对坐标,如果父模型的世界坐标变化时就主动去重新计算子模型的坐标,因为两帧之间父模型的坐标可能多次变换,往往会造成冗余的计算。所以Dirty Flag只是在父模型坐标变化的时候标记,绘制的时候再计划所有受影响的模型的世界坐标。

CopyOnWrite:
  CopyOnWrite即写时复制,如果大家对一份资源只有读请求时,那么资源是可以共享的,当某个访问者需要修改资源(写操作)时,就将资源拷贝一份给该访问者使用。即资源的拷贝被延迟到了第一次"写"的时候。CopyOnWrite最广为人知的两个应用场景,一个是Unix like系统fork调用产生的子进程共享父进程的地址空间,知道写操作才会拷贝一份。另一个是java中的copyonwrite容器,用于多线程并发情况下的高效访问,cookshell上有对copyonwrite容器的详细介绍。

web开发中的惰性加载与惰性预加载:
  在web前端和APP开发中,当提到惰性加载或者动态加载,大家往往会想到分页、轮播图、瀑布流,这些都体现了惰性加载的思想。其中,瀑布流在出诸多图片分享网站中使用非常广泛,比如花瓣网,当滑动到屏幕底部的时候才会去加载新的内容。为什么要使用惰性加载,第一个是用户体验的问题,图片资源流量比较大,一次加载太多对服务器和浏览器压力都很大,对带宽要求也很高;另外,可能用户根本就不会滑动到最下面,多加载的内容就白白浪费了。
  当然太”Lazy”了也是不好的,总不能让玩家滑动到底部才一边显示loading icon,一边开始加载。为了提高用户体验,这类网站也会做预加载(predictive loading),即多准备一两页的内容,或者在滑屏到一定程度时开始加载新的一页,不过这样的预加载也是惰性预加载(lazy predictive loading)。

总结:
回到顶部
  本文列举了惰性计算在编程中的一些具体例子,希望能给自己以及大家有所启发,在以后遇到问题的时候多一种解决思路。由于本人编程领域以及编程语言的局限性,肯定还有诸多遗漏,欢迎大家在评论里补充。

references:
lazy loading
lazy initializing
lazy evaluation
Short-circuit_evaluation
CopyOnWrite
Dirty Flag模式及其应用
python yield generator 详解
Dirty Flag
Lazy initialization

本文版权归作者xybaby(博文地址:http://www.cnblogs.com/xybaby/)所有,欢迎转载和商用,请在文章页面明显位置给出原文链接并保留此段声明,否则保留追究法律责任的权利,其他事项,可留言咨询。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容

  • 在此处先列下本篇文章的主要内容 简介 next方法的参数 for...of循环 Generator.prototy...
    醉生夢死阅读 1,436评论 3 8
  • 背景:惰性求值? 来看一个 lazy.js 主页提供的示例: 上例中,要在非常非常多的人里面,找出 5 个以 Sm...
    NARUTO_86阅读 3,618评论 0 9
  • Generator 函数的语法 简介 基本概念 Generator 函数是 ES6 提供的一种异步编程解决方案,语...
    站在大神的肩膀上看世界阅读 4,162评论 0 6
  • 简介 基本概念 Generator函数是ES6提供的一种异步编程解决方案,语法行为与传统函数完全不同。本章详细介绍...
    呼呼哥阅读 1,067评论 0 4
  • 初见魂迷,杏眼柳眉戴镜,樱点小唇,青丝却凌不乱。 邀伊长论,月从无中且生残,许佳人诺,隔江南北盈月恋。 ...
    清涧骚人阅读 240评论 0 0