我已经编写了以下函数来查找给定列表"lst“中的给定项目"x”,如果找到,则返回其索引,否则将返回错误:
exception Failure of string
let rec func x lst c = match lst with
| [] -> raise(Failure "Not Found")
| hd::tl -> if (hd=x) then c else func x tl (c+1)
let find x lst = func x lst 0
这个函数是完全工作的,我想知道它的内存消耗是多少?这意味着内存消耗
我的理解(这可能是不正确的或不完整的)是,懒惰的评估可以提供尾巴递归的所有优点,并且做得更好。
如果是这样的话,这是否意味着在惰性评估的上下文中不需要尾递归?
更新
具体来说,让我们看看下面的示例:
(define (foo f a)
(if (number? a)
(* a a)
(lazy-map foo a)))
这个函数可以很容易地转换成尾递归函数.然而,如果是这样的话,我们将失去懒惰的优势-评估。
实际上,当输入是相当大的列表(或无限)时,这个非尾递归函数需要消耗许多堆栈吗?我不这样认为。那么,是否有充分的理由使用tail-recursion而不是惰性评估?
我刚刚开始学习Haskell,并将阅读书籍和教程与解决Euler项目中的问题结合起来。由于使用以下代码获得"C堆栈溢出“错误,所以我一直停留在上:
euler.hs
divisors n = [x | x <- [1..n `div` 2], n `mod` x == 0] ++ [n]
is_prime n = divisors n == [1, n]
f a b = [n^2 + a * n + b | n <- [0..]]
primes_from_zero a b = length(takeWhile is_prime (f a b))
命令窗口
这个命令给出欧拉系
所以这是我程序的一部分。当我为相差超过250000的数字调用bound时,它会导致堆栈溢出。我该如何解决这个问题呢?对于较小的输入,该程序运行良好。我很确定程序的其余部分都很好。有没有办法重写函数,让它们正常工作?我不喜欢使用for while循环。谢谢
let rec sqdigits a =
if a = 0 then 0
else ( a mod 10)*( a mod 10) + sqdigits (a/10);;
let rec bound c d =
if c>d then []
else (sqdigits (c))::(bound (c+1) d);;
我有这样的测试代码:
public class Constants {
public static String c1 = "C1";
static {
System.out.println("Constants Class Loaded!");
}
}
public class Test {
public static void main(String[] args) {
String c1 = Constants.c1;
System.out.println(c1);
}
}
其产出是:
Const
我开始学习ocaml,并且真正体会到了递归在语言中的威力。然而,我担心的一件事是堆栈溢出。
如果ocaml使用堆栈进行函数调用,它最终不会溢出堆栈吗?例如,如果我有以下函数:
let rec sum x =
if x > 1 then f(x - 1) + x
else x;;
它最终一定会导致堆栈溢出。如果我在c++中做同样的事情(使用递归),我知道它会溢出。
所以我的问题是,有没有内置的保护措施来防止函数式语言溢出堆栈?如果不是,它们是不是像这样不太有用,因为上面的求和算法是用for循环的过程化风格编写的,可以处理任何数字(与整数溢出无关)?
这是我们教授写的一篇教程,我无法理解它。我可以想出派生词,但我不能仅仅通过分析推导就想出语法。
在这方面,“匹配”指的是什么?
你能解释一下matched_if,matched_stmt,unmatched_if是如何用简单的单词工作的吗?
The following is an unambiguous grammar for the problem:
stmt → if_stmt | nonif_stmt
if_stmt → matched_if | unmatched_if
matched_if → 'if' logical_expr 'then' mat
函数编程中有这样的CPS技巧,即采用非尾递归函数,并以连续传递方式(CPS)重写它,从而使其成为尾递归函数。很多问题都涉及到这个问题,比如
举个例子
let rec count n =
if n = 0
then 0
else 1 + count (n - 1)
let rec countCPS n cont =
if n = 0
then cont 0
else countCPS (n - 1) (fun ret -> cont (ret + 1))
第一个版本的count将在每个递归调用中累
我对Haskell很陌生,我读过Haskell的第一原则,在第384页中,我遇到了FoldR,它似乎不是尾部递归的
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr f z [] = z
foldr f z (x:xs) = f x (foldr f z xs)
1-我们能使它的尾递归吗?
2-它会被优化吗?
GCC在试图编译时给我以下警告信息:
las.c:13:18: warning: initializer element is not a constant expression [enabled by default]
const int ROWS = pow (2, MESH_K);
与此相关的代码部分是:
#define MESH_K 10
#define BUFF_SIZE 30
const int ROWS = pow (2, MESH_K);
我需要在代码的后面点同时使用MESH_K和行。我知道函数调用可能导致GCC相信这不是一个固定的表达方式。但是,考虑到对pow的调用
对于c和c++相同的程序,当我们使用常量整数变量作为case标签时,它只在c++中有效,而在c中不有效,当我们使用常量整数数组成员作为case标签时,它对c和c++都无效。这种行为的主要原因是什么?
//for c
#include <stdio.h>
int main()
{
const int a=90;
switch(90)
{
case a://error : case label does not reduce to an integer constant
printf("error");
b