Chinaunix首页 | 论坛 | 博客
  • 博客访问: 103548
  • 博文数量: 17
  • 博客积分: 42
  • 博客等级: 上尉
  • 技术积分: 180
  • 用 户 组: 普通用户
  • 注册时间: 2008-03-24 01:27
文章分类
文章存档

2011年(1)

2010年(16)

分类:

2010-04-14 23:35:00

我: 你知道惰性求值么
2:09 
另一个人: IEnumerable的yield return?
 
我: 额 那个也是
  
我不知道yield的机理
2:10 
惰性求值有2个关键
  
1个是延迟到第一次使用的时候才求值,
  
2是第二次用到的时候直接把上次算过得结果返回,也就是缓存。
2:11 
这样能减少大量的计算和时间
 
另一个人: 嗯。。那用属性也是容易做到的
  
单个值的话
 
我: 恩 oop的语言是最容易做到的
 
另一个人: 如果多个值就用yield return了
 
我: scheme里面是用delay 和force两个关键字做到的
2:12 
另一个人: c# 4.0貌似有多了一个lazy的东西。。
  
是干这个的
 
我: 额 我现在用yield的地方都没一个 真汗
2:13 
另一个人: 呵呵,可以用yield return构造一个list,但我不确定它是不是只被调用一次
2:14 
IEnumberable Numbers{}
 
我: 你这样的话是用来遍历的吧?
  
如果是随机读取容器中的一个要怎样做到?
2:15 
另一个人: IEnumberable Numbers{
get{
yield return 1;
yield return 2;
}
}
 
我: 这样是有顺序的吧
 
另一个人: 嗯。。那应该只能自己实现了。。
2:16 
我: 我感觉用yield return的话就只能按顺序取出来使用
 
另一个人: 对
 
我: 并且用完了就没得用了?
2:17 
另一个人: 那你可以在它用的时候copy一份到list里面
  
第二次就取list的
2:18 
我: IEnumberable
  
是个什么东西?
  
不是容器吧
 
另一个人: 多打了个b。。
  
IEnumerable
2:19 
我: 这样需要外部去copy一个混存
  
有没办法内部封装下
  
外部没感觉呢
 
另一个人: 嗯,当然可以封装啊
2:20 
我: 我这几天看一本好书
  
叫冒号课堂
  
讲各种各样的范式 模式 很好玩
2:21 
另一个人: 好像有看过这个博客。。不知道是不是同一个人
 
我: 还有一种语言类型叫逻辑式
 
另一个人: 用讲故事的方式,对吗?
 
我: Prolog
  
恩 一条条断言
 
另一个人: 嗯,这个我们学人工智能的时候学过。。。
 
我: 很有意思
2:22 
另一个人: 不过挺难的。。
 
我: 它关注的不是命令 也不是函数 而是关系
 
另一个人: 嗯
 
我: 额 我感觉如果习惯了那种思维写起来很爽
2:23 
另一个人: 嗯,做复杂逻辑很方便。。。
 
我: 跟数学表达式几乎没什么区别。。。
  
哈哈
 
另一个人: 当时好像我们老师写了一下那个经典的坐船过河的。。就几行。。
 
我: quiksort 它也就几行搞定。。
2:24 
另一个人: 呵呵
 
我: 呵呵 不过效率可能跟函数式差不多
  
因为是解释的吧?
  
对了 说函数式语言是无状态的
  
我感觉不怎么好理解
2:25 
什么叫无状态
2:26 
另一个人: 我也说不好。。我的理解就是相互之间没有关联,要自己来建立关联
2:27 
我: 我的感觉是
  
函数是没有状态的
2:28 
也就是函数是可重入的
  
如果c里面的函数都写成可重入的话
 
另一个人: 嗯
 
我: 那就是也具备了无状态的特点
  
但显然我们在命令式代码里面几乎很少写可重入函数
2:29 
不同时刻调用的时候状态不一样
  
但是我感觉,函数式语言里面的变量应该是有状态的吧?
2:30 
另一个人: 嗯,函数就是依靠变量来控制状态的。。
 
我: 那就奇怪了
2:31 
如果它的函数使用了外部变量 不就具有状态了么?
 
另一个人: 得使用全局变量,才能说它是有状态的
2:32 
我: 恩 局部变量是没有 额 是这样理解的么,我感觉它也会使用全局变量的
  
http://blog.upsuper.org/erlang-implementation-of-0-1-knapsack-algorithm/
  
看这个Erlang语言 好难理解
2:33 
另一个人: 好晕。。
2:36 
我: Erlang因为是函数语言 没有状态 所以可以大量使用并行 很牛逼
  
Unix的管道思想也是这个 但是我还是没理解好状态
2:37 
另一个人: 无状态应该就是,这次进来是这样,下次进来还是这样,只跟参数有关,跟时间无关
2:38 
我: 那岂不是都不能使用外部变量。。。
2:39 
一旦使用外部变量就没法不跟时间无关
 
另一个人: 是啊
 
我: 可是
  
为什么说函数语言里面没有赋值?
2:40 
另一个人: 没有赋值?
 
我: 哦 我理解了
  
你看
  
(define a ....)
  
在定义的时候就被求值了
  
所以即使其他函数使用a 也跟时间无关
2:41 
不管什么地方使用 a 如果是个列表 的话 因为定义的时候就被求值 所以跟世界无关
2:42 
然后如果a是个函数 递归的 没有状态 跟时间无关
 
另一个人: 嗯,被调用的时候要重新做里面的计算
2:43 
我: 恩
  
重新计算的话 如果有用到外部的变量 递归重新计算?
  
直到(define b 2)这种为止
  
但是这种显然是时间无关的
 
另一个人: 嗯
 
我: 所以整体是时间无关的
  
呵呵
2:44 
另一个人: 嗯
 
我: 那看来 惰性求值是一种变相打破无状态的工具
 
另一个人: 应该也不算打破,只是改变其中一些工作方式吧。。
 
我: (define (delay (f a) ...))
2:45 
恩 我感觉惰性求值就具备了状态吧?
  
不过很微弱的状态
2:46 
另一个人: 也没有,这样返回的时候把整个式子返回出来,而不是直接返回结果
 
我: 因为它第二次调用的话是直接返回上次计算的结果 这明显具备了时间!
  
额 因为是整个式子
2:47 
所以如果要用就一定要 (force f)强迫求值
  
但是这个关键字是会在第二次调用的时候直接返回上次结果的
 
另一个人: 嗯,把计算的时间分散开
 
我: 那就具备了时间性
2:48 
计算的时间被延迟到第一次force
  
额 那如果没有用force岂不是每次都是重新计算?
2:49 
没有用delay
 
另一个人: 嗯。。应该是
  
如果第二次直接返回上次的结果。。那应该是具备了时间性
2:50 
我: 尾递归你还记得么
  
原始的递归是无状态的 所以每次都要递归入栈到底再出栈计算
  
这样很低效
2:51 
我记得尾递归是每次递归的时候就直接求值
 
另一个人: 嗯,对
 
我: 为什么能直接求值
 
另一个人: 把求值放到递归外面来做
2:52 
递归通过参数接受每次的结果
 
我: 恩 想起来了!
  
真有意思
 
另一个人: 不过你上面举的delay的例子
 
我: 看来要理解函数语言就得一定要理解它的无状态
2:53 
另一个人: 如果f带的参数不同,应该要重新force吧?
  
如果不重新force也会得到上一次的结果吗?
 
我: 额 我马上实验下
  
我有drscheme
 
另一个人: 嘿嘿,好
7 分钟
3:01 
我: (define (square x) (delay (* x x)))
(display (force (square 2)))
(newline)
(display (force (square 2)))
(newline)
(display (force (square 3)))
  
-----------------------------------
  
4
4
9
  
额 跟没有用delay有什么区别?
3:02 
另一个人: 呃。。你不是说第二次可以不用force吗?
 
我: 没有啊
  
不用force它就只是返回表达式
  
要force才求值
3:03 
http://www.ibm.com/developerworks/cn/linux/l-lazyprog.html
 
另一个人: 噢。。那可能是内部建了个cache之类的吧。。
3:04 
我: 恩 应该是类似一个散列表的cache
  
如果参数已存在就直接返回对应的结果
3:05 
跟动态规划的技术一样
 
另一个人: 嗯,这样的话,因为无状态的函数,传入同样的参数,一定返回同样的结果
  
还是不违反无状态的原则
 
我: 恩 很牛
  
整个语言就是无状态的
 
另一个人: 嘿嘿
 
我: 嘿嘿 搞懂了 睡觉去啦 呵呵
3:06 
我把我们记录群发吧 也许有人会看 呵呵
 
另一个人: 嗯,我也要睡啦~~鸡都叫了。。呵呵

阅读(3724) | 评论(0) | 转发(0) |
0

上一篇:编程之殇

下一篇:界面设计

给主人留下些什么吧!~~