Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
查看clojure中是否有部分数据是惰性的_Clojure_Lazy Evaluation_Lazy Sequences - Fatal编程技术网

查看clojure中是否有部分数据是惰性的

查看clojure中是否有部分数据是惰性的,clojure,lazy-evaluation,lazy-sequences,Clojure,Lazy Evaluation,Lazy Sequences,clojure中是否有检查数据是否包含某些惰性部分的函数 背景: 我正在clojure建立一个小型服务器。每个连接都有一个状态、一个输入流和一个输出流 服务器从输入流中读取一个字节,并根据该值调用几个函数中的一个(以状态、输入和输出流作为参数)。这些函数可以决定从输入流读取更多内容,向输出流写入回复,并返回状态。这部分循环 只要状态不包含任何惰性部分,这一切都可以正常工作。如果状态中存在某个惰性部分,则在对其求值时(稍后,在另一个函数中),可能会开始从输入流读取并写入输出流 所以基本上我想给所有

clojure中是否有检查数据是否包含某些惰性部分的函数

背景:

我正在clojure建立一个小型服务器。每个连接都有一个状态、一个输入流和一个输出流

服务器从输入流中读取一个字节,并根据该值调用几个函数中的一个(以状态、输入和输出流作为参数)。这些函数可以决定从输入流读取更多内容,向输出流写入回复,并返回状态。这部分循环

只要状态不包含任何惰性部分,这一切都可以正常工作。如果状态中存在某个惰性部分,则在对其求值时(稍后,在另一个函数中),可能会开始从输入流读取并写入输出流


所以基本上我想给所有这些函数添加一个post条件,声明返回状态的任何部分都不可能是惰性的。是否有检查惰性序列的函数。我认为很容易检查状态本身是否是一个惰性序列,但我想检查例如状态是否有一个包含哈希映射的向量,其中一个值是惰性的。

通过强制使用
doall


几年前,我在一个流处理加密应用程序中遇到了这个问题,并尝试了几种方法,直到我最终接受了懒惰的一面,并将输入流包装成一个懒惰的序列,当没有更多数据可用时,该序列在输入流中关闭。有效地将关闭流的关注点与流包含的内容的关注点分开。你正在跟踪的状态听起来比打开与关闭的状态要复杂一些,尽管你可以用类似的方式将其分开。

正如阿尔瑟明智地建议的那样,你当然可以强制进行评估

然而,我建议改为重构来解决真正的问题,即处理函数有副作用(从输入读取,从输出写入)

如果执行以下操作,则可以将其转换为纯函数:

  • 将输入流包装为惰性序列
  • 使用[input sequence state]作为处理程序函数的输入
  • 使用[list of writes new state rest of input sequence]作为输出,其中写入列表是随后需要写入输出流的内容

如果你这样做,你的处理函数是纯的,你只需要在一个简单的循环中运行它(在每次迭代中向输出流发送写操作列表),直到所有的输入都被消耗和/或达到一些其他终止条件。

doall不能递归地工作,不幸的是:
(count(doall[1 2 3 4(range)])
将返回5,而不是stack/heapoverflow.Ah,在第二部分:我考虑了用惰性序列包装inputstream,并且它是有效的(尽管您松散了java DataInputStream之类的东西)。但对于outputstream,这不起作用,这是一个实际需要副作用的地方。(计数(映射doall(筛选序列?[1 2 3 4(范围)]))如果需要进一步嵌套,请查看使用拉链递归遍历结构。@Claude-通常这是您想要的。如果你想让
范围
成为同一序列的一部分,那么你可以做
(count(doall(concat[1 2 3 4](范围10))
(给出14;并且你实际上不需要
范围
,因为
计数
会扩展…)任何涉及懒惰的事情都会变得懒惰:)@Ankur-这是真的(假设你不强制评估)虽然我认为最重要的一点是,如果你坚持纯粹的功能,懒惰永远不重要。在过去一天左右的时间里,我对这个建议进行了很多思考。一方面我喜欢纯函数。然而,在我看来,使用序列消除了代码的干净性。如果我有一个流,我需要先从中读取一个长的(a),然后读取一个字节(b),然后读取(b)多个整数,这将很容易做到(并且对于任何阅读代码的人来说都很容易理解)
(让[a(.readInt I)b(.readByte I)c(重复读取b#(.readInt I))…
。如何用一个序列干净利落地做到这一点…@Claude-你肯定需要在某个时候编写这种代码,但我建议将其包装到一个
读取消息
函数中。然后您可以执行
(重复读取消息)
,并获得传入消息的延迟序列。这就是您想要处理的惰性输入序列(即,您希望在稍微高一点的抽象级别上操作),这看起来是一个干净的解决方案,特别是如果您将消息包装为某种标准格式(例如google协议缓冲区)。但你确实失去了一些灵活性;例如,在收到完整消息之前,您无法开始处理消息(问题是您需要此功能的频率有多高…)。谢谢你的见解!