Functional programming 标准ML:回溯混淆
我被哈珀在第页的SML简介中给出的一个例子弄糊涂了。110他正在编写一个函数,对硬币价值列表进行一定量的更改,必要时进行回溯 e、 g.如果我运行change[5,2]16,我会得到[5,5,2,2,2](如果可能,算法应该是贪婪的) 有几个问题: 1) 我对这个算法如何实现回溯有点困惑。看起来,当使用硬币值的空列表作为第一个参数调用change时,它会引发change异常 但是更改异常处理程序调用Functional programming 标准ML:回溯混淆,functional-programming,sml,Functional Programming,Sml,我被哈珀在第页的SML简介中给出的一个例子弄糊涂了。110他正在编写一个函数,对硬币价值列表进行一定量的更改,必要时进行回溯 e、 g.如果我运行change[5,2]16,我会得到[5,5,2,2,2](如果可能,算法应该是贪婪的) 有几个问题: 1) 我对这个算法如何实现回溯有点困惑。看起来,当使用硬币值的空列表作为第一个参数调用change时,它会引发change异常 但是更改异常处理程序调用Change。这是如何“推翻最近的贪婪决定”的 2) 为什么处理程序被放在else子句中?我原以为
Change
。这是如何“推翻最近的贪婪决定”的
2) 为什么处理程序被放在else子句中?我原以为它是完全独立的
谢谢你的帮助,
b外行这里是调用的执行跟踪
change[5,2]16
ofhandle
表示函数迄今为止已计算的内容,而
右侧是通过更改
信号请求回溯时要继续的状态
> change [5, 2] 16
> 5 :: change [5, 2] (16 - 5) handle Change: change [2] 16
> 5 :: change [5, 2] 11 handle Change: change [2] 16
> 5 :: 5 :: change [5, 2] (11 - 5) handle Change: 5 :: change [2] 11
> 5 :: 5 :: change [5, 2] 6 handle Change: 5 :: change [2] 11
> 5 :: 5 :: 5 :: change [5, 2] (6 - 5) handle Change: 5 :: 5 :: change [2] 6
> 5 :: 5 :: 5 :: change [5, 2] 1 handle Change: 5 :: 5 :: change [2] 6
> 5 :: 5 :: 5 :: change [2] 1
> 5 :: 5 :: 5 :: change nil 1
> raise Change => 5 :: 5 :: change [2] 6
> 5 :: 5 :: 2 :: change [2] (6 - 2) handle Change
> 5 :: 5 :: 2 :: change [2] 4 handle Change
> 5 :: 5 :: 2 :: 2 :: change [2] (4 - 2) handle Change
> 5 :: 5 :: 2 :: 2 :: change [2] 2 handle Change
> 5 :: 5 :: 2 :: 2 :: 2 :: change [2] (2 - 2) handle Change
> 5 :: 5 :: 2 :: 2 :: 2 :: change [2] 0 handle Change
> 5 :: 5 :: 2 :: 2 :: 2 :: nil
> [5, 5, 2, 2, 2]
正如您所看到的,当捕获到更改异常时,算法返回两步
堆叠帧,从结果列表中丢弃第三个5硬币,并仅使用
硬币列表中的2枚硬币。金额也重置为6
第一行,handle
前面的部分尝试使用另一个5作为可能的参数
分解,而异常处理程序表示回溯选项,
i、 例如,移除我们刚刚尝试过的5个硬币,调整硬币列表和剩余的硬币
数量
最后一行通知最后安装的异常处理程序返回
> 5 :: 5 :: 5 :: change [5, 2] 1 handle Change: 5 :: 5 :: change [2] 6
> 5 :: 5 :: 5 :: change [2] 1
> 5 :: 5 :: 5 :: change nil 1
> raise Change => 5 :: 5 :: change [2] 6
换言之,当算法达到不再需要的状态时,它会进行回溯
硬币类型可以选择,但数量仍然是正数。这是贪婪的
因为在捕获异常之前,算法将使用相同的硬币
异常处理程序附加到else
表达式,因为它位于
贪婪的选择已经做出
希望我的解释能被理解
> 5 :: 5 :: 5 :: change [5, 2] 1 handle Change: 5 :: 5 :: change [2] 6
> 5 :: 5 :: 5 :: change [2] 1
> 5 :: 5 :: 5 :: change nil 1
> raise Change => 5 :: 5 :: change [2] 6