我正在做一项学术练习(为了个人成长)。我想找到一种编程语言,使您可以定义能够接受自身(即,指向自身的指针)作为参数的函数。
例如,在JavaScript中:
function foo(x, y) {
if (y === 0) return;
x(x, y - 1);
}
foo(foo, 10);
Run Code Online (Sandbox Code Playgroud)
上面的代码将在y达到零之前恰好执行11次foo(),从而导致递归终止。
我尝试在OCaml中定义类似的功能,如下所示:
let rec foo x y = if y < 1 then "hi" else x x (y - 1);;
Run Code Online (Sandbox Code Playgroud)
但是它失败并出现类型错误:
Error: This expression has type 'a -> 'b -> 'c
but an expression was expected of type 'a
The type variable 'a occurs inside 'a -> 'b -> 'c
Run Code Online (Sandbox Code Playgroud)
我想知道,是否可以在OCaml中定义这样的功能?我对OCaml特别感兴趣,因为我知道它具有全局类型推断系统。我想知道这样的功能是否与全局类型推断兼容。因此,我正在寻找任何具有全局类型推断功能的语言的示例。
ocaml type-systems type-inference hindley-milner anonymous-recursion
我正在创建一种静态编译的编程语言,并使用 LLVM 作为其后端。我希望我的语言在发生整数溢出时捕获/崩溃。
我知道llvm.sadd.with.overflow之类的东西,但我认为这不是最佳/有效的解决方案。该函数返回一个包含两个值的结构,而不仅仅是让我直接访问 OF 寄存器标志。理想情况下,在每次算术运算之后,只要发生整数溢出,我就会有一个“JO”汇编指令来捕获。这正是 clang 的UndefinedBehaviorSanitizer所做的。但是,我正在编译为 LLVM IR,而不是 C 或 C++。
如何直接在 LLVM IR 中使用 UndefinedBehaviorSanitizer(或完成等效操作)来处理整数溢出?
我正在为一种虚构的编程语言编写一个递归的体面解析器。这是一种C样式的语言,具有==,<,>,<=和> =等常用运算符,并且还具有通用功能(如C#中的那些功能)。
在C#之类的语言中,要调用通用函数,您可以编写:
someFunction<T>(x);
Run Code Online (Sandbox Code Playgroud)
我的问题是,解析器如何区分通用参数与比较运算符(<和>)。
在我看来,上面的代码可能具有以下两种含义之一:
解析器将如何知道要使用哪种解释?
我已经编写了许多简单的标记器和递归下降解析器,因此我熟悉它们如何工作的基本概念。但是当我偶然发现以下Rust代码时,我感到很惊讶:
Option<Option<i32>>
Run Code Online (Sandbox Code Playgroud)
我们知道Rust具有>>移位运算符,因此我认为天真的令牌生成器会>>在此处输出令牌,解析器将其视为错误(因为它期望使用两个>令牌)。
但显然Rust编译器了解情况并正确处理。这里发生了什么?
>>并将其分成两个令牌,然后将其推回到令牌流中?当我在https://godbolt.org上使用不同的编译器时,我注意到编译器生成这样的代码是很常见的:
push rax
push rbx
push rcx
call rdx
pop rcx
pop rbx
pop rax
Run Code Online (Sandbox Code Playgroud)
我理解每个push或pop做两件事:
所以在我们上面的例子中,我假设 CPU 实际上在做 12 次操作(6 次移动,6 次加/减),不包括call. 组合添加/订阅不是更有效吗?例如:
sub rsp, 24
mov [rsp-24], rax
mov [rsp-16], rbx
mov [rsp-8], rcx
call rdx
mov rcx, [rsp-8]
mov rbx, [rsp-16]
mov rax, [rsp-24]
add rsp, 24
Run Code Online (Sandbox Code Playgroud)
现在只有 8 次操作(6 次移动,2 次加/减),不包括call. 为什么编译器不使用这种方法?