|
锁定老贴子 主题:关于函数式编程中函数不产生副作用的困惑
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
|---|---|
| 作者 | 正文 |
|
最后更新时间:2006-12-21
因为函数式编程的每一个符号都是 final 的,没有函数产生过副作用。因为从未在某个地方修改过值,也没有函数修改过在其作用域之外的量并被其他函数使用(如类成员或全局变量)。
我对这点有不理的地方。比如对于生产者,消费者问题,用函数式编程如何解决?因为没有类成员或全局变量可以被改变,那么用什么功能来表示那个容纳生产者生产出来的产品的容器呢? 最起码生产者身产了产品后需要改变容器的值,而消费者读取了容器的产品后也要改变容器的值。函数式编程的每一个符号都是 final 的是否意味着这个容器也是不可改变的?如果不可改变那么用函数式编程如何实现生产者,消费者问题? 声明:JavaEye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
|
|
| 返回顶楼 | |
|
最后更新时间:2006-12-21
这两种概念是正交的.
|
|
| 返回顶楼 | |
|
最后更新时间:2006-12-21
虽然已知lambda等价图灵机,试试写一个出来还是很有意思的:
Producter.createProducter("producter 1").notify(message,Consumer.create("No.1"),Consumer.create("No.2")....) define producter.nofiy: params.ifExist().next().invokeConsumeMessage(message).ifExist().next().invokeConsumMessage(message)...好变态! |
|
| 返回顶楼 | |
|
最后更新时间:2006-12-21
wolfsquare 写道 这两种概念是正交的.
麻烦讲的再清楚一些,木有看懂,谁和:函数不产生副作用是正交的。 你的代码也木有看懂:( 可以讲清楚点么? |
|
| 返回顶楼 | |
|
最后更新时间:2007-06-16
消息通信机制实现一个简单的生产者消费者问题,貌似复杂了点
-module(demo).
-export([main/0]).
-export([producer/2,consumer/1,queue/2]).
producer(QueuePid, Id) ->
timer:sleep(500),
QueuePid ! {produce, Id},
io:format("Producer:Put Produce ~p~n", [Id]),
producer(QueuePid, Id+1).
consumer(QueuePid) ->
QueuePid ! {get_produce, self()},
receive
{produce, ProduceId} ->
io:format("Consumer:Get Produce ~p~n", [ProduceId]);
any -> ok
end,
timer:sleep(600),
consumer(QueuePid).
queue(List, []) ->
io:format("Queue:List is ~p~n", [List]),
receive
{produce, ProduceId} -> queue(List ++ [ProduceId], []);
{get_produce, ConsumerPid} ->
case List of
[] ->
queue([], [ConsumerPid]);
[H|T] ->
ConsumerPid ! {produce,H},
queue(T, [])
end
end;
queue([], WaitingConsumerPids) ->
io:format("Queue:Waiting consumers size is ~p~n", [length(WaitingConsumerPids)]),
receive
{produce, ProduceId} ->
[H|T] = WaitingConsumerPids,
H ! {produce, ProduceId},
queue([],T);
{get_produce, ConsumerPid} -> queue([], WaitingConsumerPids ++ [ConsumerPid])
end.
main() ->
QueuePid = spawn(?MODULE, queue, [[], []]),
spawn(?MODULE, consumer, [QueuePid]),
spawn(?MODULE, producer, [QueuePid, 0]).
|
|
| 返回顶楼 | |
|
最后更新时间:2006-12-21
这就是传说中的Erlang?
|
|
| 返回顶楼 | |
|
最后更新时间:2006-12-22
对于命令式的优点,函数语言当然不会做事不管。在Haskel中,通过构造monad可以获得普通命令式的副作用功能。其中state monad就是很好的例子。
可以看看这里,描述state monad,且有一个示列程序:http://bbs.btant.com/thread-409-1-1.html |
|
| 返回顶楼 | |
|
最后更新时间:2006-12-29
没有副作用也就是不改变世界
|
|
| 返回顶楼 | |
|
最后更新时间:2007-06-07
靠monad是一个有效率保证的手段。其实,在解决必须要改变状态的问题时,FP 采取的手段是:不停的产生新的、拥有已改变过属性的对象(此时原对象不变),然后利用函数的参数为此对象添加与原对象相同的名字(但二者不再同一层空间中),再去操作这个对象,如此反复(所以,正则尾递归是至关重要的)。
看起来这样做效率低下,但如果使用编译型的FP语言时会发现几乎没有性能损失(具体优化措施见《现代编译原理》一书),差别仅在于是用栈分配还是堆分配。 在解决IO问题上,Haskell为方便起见还是用了monad。但真正应该作的是,使用延续(不停地用上文中的方法绑定函数的编程风格):每一次I/O都返回下一次IO要用到的另一个函数。这样每个函数的状态都不变(支持等式推理,即函数的参数->值维持数学映射),整个IO过程却完成了。 |
|
| 返回顶楼 | |
|
最后更新时间:2007-07-18
javavsnet 写道 因为函数式编程的每一个符号都是 final 的,没有函数产生过副作用。因为从未在某个地方修改过值,也没有函数修改过在其作用域之外的量并被其他函数使用(如类成员或全局变量)。
我对这点有不理的地方。比如对于生产者,消费者问题,用函数式编程如何解决?因为没有类成员或全局变量可以被改变,那么用什么功能来表示那个容纳生产者生产出来的产品的容器呢? 最起码生产者身产了产品后需要改变容器的值,而消费者读取了容器的产品后也要改变容器的值。函数式编程的每一个符号都是 final 的是否意味着这个容器也是不可改变的?如果不可改变那么用函数式编程如何实现生产者,消费者问题? 容器不可改变,但是可以被丢弃的,然后用新的容器替代它。 这个方式的关键是确定什么时候完全丢弃旧容器,这比较影响时间和空间效率。 |
|
| 返回顶楼 | |











