有人可以教我递归对于let-val-in-end的情况是什么样子的吗?我很难理解游行,即循环的崩溃[SML]
示例:'c'表现如何?我是说故障
fun less (nil, x) = nil
| less (a::b, x) =
let
val c = less(b,x)
in
if a < x then a::c else c
end;
或者x和y在每个循环中的行为如何?我知道它正在解构,就像JS一样。
fun half nil = (nil,nil)
| half [a] = ([a],nil)
| half (a::b::xs) =
let
val (x,y) = half(xs)
in
(a::x, b::y)
end;
half [1,2,3]
让我们来看看你的半
函数。
fun half nil = (nil, nil)
| half [a] = ([a], nil)
| half (a::b::xs) =
let
val (x, y) = half(xs)
in
(a::x, b::y)
end;
当我们计算半[1,2,3]
时,这如何减少?
half [1, 2, 3]
(1 :: [3], 2 :: [nil])
([1, 3], [2])
您在<code>xs<code>上递归调用了<code>half<code>在本例中为<code>[3]。这将返回([3],[nil])
,因此您将本地绑定x
为[3]
,而本地绑定y
为[nil]
。我们将<code>a</code>和<code>b</code>分别与这些列表进行比较,并得到最终结果。
重要的是要认识到这不是尾递归的,如果样本足够大,就会发生堆栈溢出。
我们可以使用累加器将其转换为尾部递归。通过这样做,所有数据都从一个堆栈帧传递到下一个。不需要任何先前的堆栈帧来完全评估函数。因此,一个好的编译器会将其优化为恒定的堆栈空间。
累加器是一个包含两个列表的元组。
fun split([], (a, b)) = (a, b)
| split([x], (a, b)) = split([], (x::a, b))
| split(x::x'::xs, (a, b)) = split(xs, (x::a, x'::b))
现在,如果我们调用拆分([1,4,7,2,89,12], ([], []))
:
split([1, 4, 7, 2, 89, 12], ([], []))
split([7, 2, 89, 12], (1::[], 4::[]))
split([89, 12], (7::1::[], 2::4::[]))
split([89, 12], (7::1::[], 2::4::[]))
split([], (89::7::1::[], 12::2::4::[]))
(89::7::1::[], 12::2::4::[])
([89, 7, 1], [12, 2, 4])
哎呀!他们倒过来了!让我们把蓄能器倒过来。
fun split([], (a, b)) = (List.rev a, List.rev b)
| split([x], (a, b)) = split([], (x::a, b))
| split(x::x'::xs, (a, b)) = split(xs, (x::a, x'::b))
但每次调用<code>split</code>时都必须指定初始累加器,这很烦人。我们可以创建一个局部函数来隐藏它。
fun split(lst) =
let
fun split'([], (a, b)) = (List.rev a, List.rev b)
| split'([x], (a, b)) = split'([], (x::a, b))
| split'(x::x'::xs, (a, b)) = split'(xs, (x::a, x'::b))
in
split'(lst, ([], []))
end;
然后< code>split([1,3,7,2,6,8,0,3,7,5])产生< code>([1,7,6,0,7],[3,2,8,3,5])。
总之:局部绑定本质上与递归没有任何关系。此外,尾部递归更容易推理,并防止堆栈溢出错误。
问题内容: 我一直在尝试将编程的递归作为一个概念进行研究(尽管我专门研究Java),而这正是我最好的理解: 例如,在现实生活中,递归是当我们将两个反射镜彼此相对放置并且它们之间产生的图像是递归的。 但是我在编程中没有得到这个算法吗?有人可以给我一个简化的例子来理解递归吗? 问题答案: 基本上,函数是递归的 函数具有简单的基本情况,何时 所有其他情况都有规则化简为基本情况。 例如,要计算阶乘:
递归是一种解决问题的方法,将问题分解为更小的子问题,直到得到一个足够小的问题可以被很简单的解决。通常递归涉及函数调用自身。递归允许我们编写优雅的解决方案,解决可能很难编程的问题。
我试图使用尾部递归局部辅助函数作为赋值的一部分来重新编写代码。 all_except_选项是一个返回类型为fn:string*string list的函数- 下面的函数是不使用尾部递归局部辅助函数的函数 这个函数使用尾部递归,但是我在递归调用助手函数时出错。错误是:错误:非构造函数应用于模式:all\u except\u选项中的参数
本文向大家介绍什么是递归?用Java写一个简单的递归程序,包括了什么是递归?用Java写一个简单的递归程序的使用技巧和注意事项,需要的朋友参考一下 什么是递归?用Java写一个简单的递归程序 递归的定义 递归(recursion):以此类推是递归的基本思想,将规模大的问题转化为规模小的问题来解决。 递归的要素 自定义递归函数,并确定函数的基本功能 例如Java从键盘输入一个数,求输入这个数的阶乘。
我一直在努力学习SML NJ(standard ML New Jersey),我遇到了一个我理解为递归的函数,但我不太明白为什么这个函数会返回它的值。 功能: 我知道如果sum的值为0,那么将返回0。然而,我不明白第二部分是如何工作的。 测试函数: 我相信它应该计算如:sum n=(n(sum(n-1))),所以给定n=2,(2(sum(2-1))= 但是,给定n=4,(4(和(4-1))= 如果
问题内容: 我正在用Java学习网络,不清楚端口是什么。我还需要知道什么是套接字? 请解释清楚。 问题答案: 端口: 在计算机网络中,术语“端口”可以指物理或虚拟连接点。 物理网络端口允许将电缆连接到计算机,路由器,调制解调器和其他外围设备。 虚拟端口是TCP / IP网络的一部分。这些端口允许软件应用程序共享硬件资源,而不会互相干扰。计算机和路由器自动管理通过其虚拟端口传播的网络流量。为了安全起