functional-programming - Racket协程实现中的死锁
问题描述
作为一个帮助我理解 Racket 中的延续的项目,我决定尝试编写一个不使用可变或全局变量的协程实现。这是我到目前为止所拥有的,但它似乎最终陷入了某种僵局。我错过了一些明显的东西吗?
#!/usr/bin/env racket
#lang racket
(define (make-proc-args args)
(let/cc cc
(cons cc args)))
(define (fork proc)
(let ([current (make-proc-args '())])
(proc current)))
(define (yield to args)
(let ([current (make-proc-args args)])
((car to) current)))
(define c
(fork
(lambda (p)
(let loop ([i 0]
[parent p])
(unless (> i 10)
(loop (+ i 1) (yield parent (list i))))))))
(let loop ([child c])
(println (car child))
(loop (yield child '())))
解决方案
(define (make-proc-args args)
(let/cc cc
(cons cc args)))
这在调用时返回它作为对象的延续。如果你看这段代码:
(define (fork proc)
(let ([current (make-proc-args '())])
(proc current)))
的延续(make-proc-args '())
是let
with current
bound和proc
called的应用。在以下情况下:
(fork
(lambda (p)
(let loop ([i 0]
[parent p])
(unless (> i 10)
(loop (+ i 1) (yield parent (list i)))))))
这意味着(yield parent (list i))
将时间旅行回来并调用并将(proc current)
再次调用.. let 以i
and开头0
.. 但是人们会期望存储的延续yield
,对吗?错误的!
(define (yield to args)
(let ([current (make-proc-args args)])
((car to) current)))
被捕获的延续是((car to) current)
一次又一次地碰巧是相同的。
解决此问题的最简单方法是使延续没有调用您存储的延续,因为它是自己的延续。因此,您需要执行以下操作:
(define (fork proc)
(let/cc cc
(let ([current (cons cc '())])
(proc current))))
(define (yield to args)
(let/cc cc
(let ([current (cons cc args)])
((car to) current))))
请注意,在这两种情况下,延续是在自然返回时发生的事情,yield
而fork
不是在 a 的主体let
完成时发生的事情。
还知道延续是在顶层分隔的,因此您可能应该使用let
块中的所有代码进行测试以捕获您可能遇到的错误,因为延续在顶层的行为不同。define
不允许顶级,但如果你把它放在你let
得到#<void>
的最后一个值,child
因为这是值define
形式,而不是你期望的对。
(define (worker p)
(let loop ([i 0]
[parent p])
(unless (> i 10)
(loop (+ i 1) (yield parent i)))))
(let ((c (fork worker)))
(let loop ([child c])
(when (pair? child)
(println child)
(loop (yield child '())))))
这打印:
(#<continuation> . 0)
(#<continuation> . 1)
(#<continuation> . 2)
(#<continuation> . 3)
(#<continuation> . 4)
(#<continuation> . 5)
(#<continuation> . 6)
(#<continuation> . 7)
(#<continuation> . 8)
(#<continuation> . 9)
(#<continuation> . 10)
作为最后一个提示。也许你应该为你的延续对象或至少抽象一个结构?
推荐阅读
- javascript - if else on array 但只运行 else 语句一次,而不是每次返回为 false
- c# - 网页抓取、C#、HTML 敏捷包、错误处理?
- python - 获取字符串中具有最常见数字长度的所有数字
- python - 将 casefold() 与数据框列名称和 .contains 方法一起使用
- .net - 在 netstandard2.0 和 4.7.2 的解决方案中,dotnet 构建失败并出现“类型或命名空间名称...不存在”
- iphone - Flutter应用程序卡在白屏iPhoneXS上
- android - 问题将 Xamarin Forms Android 应用程序作为捆绑包发布到 Play 商店 - 文档已过期
- javascript - 如何使嵌套插槽的道具(Vue 2)可以访问父数据?
- algorithm - 砖在墙上的排列方式有几种?
- javascript - 避免 React 功能组件中的代码重复