- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我一直在研究禁止 use-before-def 并且没有可变单元格(没有 set!
或 setq
)的语言如何仍然可以提供递归.我当然遇到了(著名的?臭名昭著的?)Y 组合器和 friend ,例如:
当我以这种方式实现“letrec”语义时(也就是说,允许定义一个局部变量,这样它就可以是一个递归函数,在幕后它永远不会引用它自己的名字) ,我最终编写的组合器如下所示:
Y_letrec = λf . (λx.x x) (λs . (λa . (f ((λx.x x) s)) a))
或者,分解出 U 组合子:
U = λx.x x
Y_letrec = λf . U (λs . (λa . (f (U s)) a))
读作:Y_letrec 是一个接受待递归函数 f
的函数。f
必须是接受 s
的单参数函数,其中 s
是函数f
可以调用实现自递归。 f
应该定义并返回执行“真实”操作的“内部”功能。该内部函数接受argument a
(或者在一般情况下是一个参数列表,但是不能表达在传统符号中)。调用 Y_letrec 的结果是调用的结果f
,它被假定为一个“内部”函数,准备好被调用。
我这样设置的原因是我可以使用直接将要递归的函数,不做任何修改,只是包装一个额外的在处理 letrec 的转换过程中围绕它的功能层。例如,如果原代码为:
(letrec ((foo (lambda (a) (foo (cdr a))))))
那么转换后的形式将是:
(define foo (Y_letrec (lambda (foo) (lambda (a) (foo (cdr a))))))
请注意,两者的内部函数体是相同的。
我的问题是:
注意:上面的第一个链接指的是与“应用顺序 Y 组合器”类似的函数(在“第 5 步”中),尽管我找不到该命名的权威来源。
2013 年 4 月 28 日更新:
我意识到上面定义的 Y_letrec 与维基百科中定义的 Z 组合器非常接近但不完全相同。根据维基百科,Z 组合子和“按值调用 Y 组合子”是同一回事,看起来这确实是更常被称为“应用顺序 Y 组合子”的东西。
因此,我上面的内容与通常编写的应用顺序 Y 组合子不相同,但几乎可以肯定它们之间存在关联。这是我进行比较的方式:
开始于:
Y_letrec = λf . (λx.x x) (λs . (λa . (f ((λx.x x) s)) a))
应用内U:
Y_letrec = λf . (λx.x x) (λs . (λa . (f (s s)) a))
应用外层U:
Y_letrec = λf . (λs . (λa . (f (s s)) a)) (λs . (λa . (f (s s)) a))
重命名以匹配维基百科对 Z 组合子的定义:
Y_letrec = λf . (λx . (λv . (f (x x)) v)) (λx . (λv . (f (x x)) v))
将其与维基百科的 Z 组合器进行比较:
Z = λf . (λx . f (λv . ((x x) v))) (λx . f (λv . ((x x) v)))
显着的区别在于应用函数 f
的地方。有关系吗?尽管存在差异,这两个功能是否等效?
最佳答案
是的,它是一个应用顺序 Y 组合器。在里面使用 U 是完全可以的,我也这样做了(参见 fixed point combinator in lisp )。 U 用于缩短代码的用法是否有名称,我不这么认为。它只是 lambda 项的应用,是的,它也使 IMO 更清晰。
有一个名字,是 eta-conversion,在您的代码中用于延迟应用顺序下的评估,其中参数的值必须在功能应用之前已知。
通过不断应用 U 并对代码执行 eta 缩减 ( (λa.(f (s s)) a)
==> f (s s)
),它变成了熟悉的正常顺序 Y 组合子 - 即在正常顺序评估下工作,其中在功能应用程序之前不需要参数的值,毕竟最终可能不需要它们(或其中的一些):
Y = λf . (λs.f (s s)) (λs.f (s s))
顺便说一句,延迟可以以稍微不同的方式应用,
Y_ = λf . (λx.x x) (λs.f (λa.(s s) a))
它也适用于应用顺序评估规则。
有什么区别?让我们比较减少序列。你的版本,
Y_ = λf . (λx . (λv . (f (x x)) v)) (λx . (λv . (f (x x)) v))
((Y_ f) a) =
= ((λx . (λv . (f (x x)) v)) (λx . (λv . (f (x x)) v))) a
= (λv . (f (x x)) v) a { x := (λx . (λv . (f (x x)) v)) }
= (f (x x)) a
= | ; here (f (x x)) application must be evaluated, so
| ; the value of (x x) is first determined
| (x x)
| = ((λx . (λv . (f (x x)) v)) (λx . (λv . (f (x x)) v)))
| = (λv . (f (x x)) v) { x := (λx . (λv . (f (x x)) v)) }
这里输入了f
。所以在这里,行为良好的函数 f
也接收到它的第一个参数,并且它不应该对它做任何事情。所以也许两者完全等价。
但实际上,当涉及到真正的实现时,lambda 表达式定义的细节并不重要,因为真正的实现语言会有指针,我们只需操纵它们正确地指向包含表达式的主体,而不是它的副本。 Lambda 演算毕竟是用铅笔和纸完成的,作为文本复制和替换。 lambda 演算中的 Y 组合器仅模拟递归。真正的递归是真正的自引用;不是接收副本,通过 self 应用(无论多么聪明)。
TL;DR:虽然被定义的语言可能没有赋值和指针相等性等有趣的东西,但我们定义它的语言肯定会有这些东西,因为我们需要它们来提高效率。至少,它的实现会将它们隐藏起来。
另请参阅:fixed point combinator in lisp , 特别是In Scheme, how do you use lambda to create a recursive function? .
关于scheme - 两层 "Y-style"组合子。这很常见吗?这个有正式名称吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16258308/
我有这个 html 代码: HELLO WORLD! X V HELLO WORLD! X V 我想按 X(类关闭)将父 div 的高度更改为 20px 并显示 V(类打开),但在每个 d
在会计应用程序的许多不同实现中,有两种主要的数据库设计方法来保存日志和分类帐数据。 只保留 Journal 信息,然后 Ledger 只是 Journal 的一个 View (因为 journal 总
我想在另一个子里面有一个子, sub a { sub b { } } 我想为每次调用 sub b 创建一个新的 sub a 实例。有没有办法在 Perl 中做到这一点? 当我运行上面的
我有一些代码正在查找重复项并突出显示单元格: Private Sub cmdDups_Click() Dim Rng As Range Dim cel As Range Set Rng = ThisW
可能有一个简单的解决方案,但我很难过。 我有一个包含一个 ID 字段的主表。在两个可能的字段中有一个具有该 ID 的子表。想象一个由选手 A 和选手 B 组成的 double 队。Master 表将有
假设我有一个包含对象的数组: [ { "id": "5a97e047f826a0111b754beb", "name": "Hogwarts", "parentId": "
我正在尝试对 MySQL 数据库表执行一对父/子模型的批量插入,但似乎无法使用标准的 ActiveRecord 功能来完成。所以,我尝试了 activerecord-import gem,但它也不支持
我有一个带有多个子类的父抽象类。最终,我希望通过 GUI 中的进度条显示子类中完成的进度。 我目前所做的,我意识到这是行不通的,是在父类中声明为每个子类将覆盖的虚拟方法的事件方法定义。所以像: pub
是否可以通过键数组在对象中设置变量?例如我有这个对象: var obj = {'outer': {'inner': 'value'} }; 并希望设置由键数组选择的值: var keys = ['ou
我有一个名为 companies 的 MySQL 表,如下所示: +---------+-----------+-----------+ | id_comp | comp_name | id_pare
我正在尝试使用 sublime text 在 sublime text 上的 ionic 上打开我的第一个应用程序。它给了我一个“找不到命令”的错误。如何修复? 我试过这些命令: sudo rm -r
不好意思问,但我正在使用 webapp2,我正在设计一个解决方案,以便更容易定义路由 based on this google webapp2 route function .但这完全取决于能够在子级
我有代表树的数字字符串(我不知道是否有官方名称): 012323301212 上面的例子代表了 2 棵树。根用 0 表示。根的直接子代为“1”,“1”的直接子代为“2”,依此类推。我需要将它们分组到由
是否可以在当前 Activity 之上添加 Activity 。例如,假设我单击一个按钮,然后它将第二个 Activity 添加到当前 Activity 。而第二个 Activity 只覆盖了我当前
我很难思考如何为子资源建模。 以作者的书籍为例。你可以有 N 本书,每本书只有一位作者。 /books GET /books POST /books/id PUT /books/id DELETE 到
有人可以向我解释以下内容(python 2.7) 来自已解析文件的两个字符串数字: '410.9''410.9 '(注意尾随空格) A_LIST = ['410.9 '] '410.9' in '41
背景 在 PowerShell 中构建 hash table 是很常见的通过特定属性快速访问对象,例如以 LastName 为基础建立索引: $List = ConvertFrom-Csv @' I
我真的很难弄清楚如何调用嵌套 Polymer Web 组件的函数。 这是标记: rise-distribution组件有 canPlay我想从 rise-playlist
我写了一个小工具转储(以 dot 格式)一个项目的依赖关系图,其中所有位于同一目录中的文件都聚集在一个集群中。当我尝试生成包含相应图形的 pdf 时,dot开始哭: 命令 dot -Tpdf trim
给定一个 CODE ref,是否可以: 访问该 CODE ref 的解析树 通过指定 CODE ref 的解析树来创建一个新的 CODE ref,该解析树可以包含在 1 中返回的解析树的元素 通常我们
我是一名优秀的程序员,十分优秀!