ocaml - 插入 let 绑定局部变量
问题描述
我正在阅读 Oleg Kiselyov 的教程Reconciling Abstraction with High Performance: A MetaOCaml approach。一个练习(练习 23)要求使用 let-insertion 将数组索引访问绑定到局部变量。question 的函数是vmult_ca
,它生成用于将复数数组相乘的代码:
let vmult_ca :
(float_complex array -> float_complex array -> float_complex array -> unit)
code =
.<fun vout v1 v2 ->
let n = Array.length vout in
(* vector representations *)
.~(let vout = OVec (.<n>., fun i v ->
.<vout.(.~i) <- .~(of_code_complex v)>.) in
let v1 = Vec (.<n>., fun i ->
of_complex_code .<v1.(.~i)>.) in
let v2 = Vec (.<n>., fun i ->
of_complex_code .<v2.(.~i)>.) in
let module V = VMULT(FloatCodeComplex)(VecDyn) in
V.vmult vout v1 v2)
>.
;;
vout
存储结果的输出向量
在哪里。Vec (n, fun i -> v)
是一个抽象向量,其中n
是长度,并将fun i -> v
每个索引映射到一个值。
OVec (n, fun i v -> body)
是一个抽象的“输出向量”,其中n
是长度并且fun i v -> body
在每个索引i
和相关输出元素v
上运行i
。
of_complex_code
将一个complex code
值转换为一个code complex
值,例如.<{real=1.0, imag=0.0}>.
转换为{real=.<1.0>., imag=.<0.0>.}
. 该模块VMULT
定义(逐点)向量乘法(有关详细信息,请参见此处的代码)。
运行时,vmult_ca
生成以下代码:
val vmult_ca :
(float_complex array -> float_complex array -> float_complex array -> unit)
code = .<
fun vout_4 ->
fun v1_5 ->
fun v2_6 ->
let n_7 = Array.length vout_4 in
for i_8 = 0 to n_7 - 1 do
vout_4.(i_8) <-
{
Cmplx.im =
(((v1_5.(i_8)).Cmplx.re *. (v2_6.(i_8)).Cmplx.im) +.
((v1_5.(i_8)).Cmplx.im *. (v2_6.(i_8)).Cmplx.re));
Cmplx.re =
(((v1_5.(i_8)).Cmplx.re *. (v2_6.(i_8)).Cmplx.re) -.
((v1_5.(i_8)).Cmplx.im *. (v2_6.(i_8)).Cmplx.im))
}
done>.
注意v1_5.(i_8)
重复4次。let
挑战是在某处插入一个vmult_ca
绑定v1_5.(i_8)
到局部变量以避免重复。genlet
我可以通过简单地调用来“作弊” .<v1.(~i)>.
,但我不知道在哪里插入let
without genlet
; 任何提示将不胜感激。
解决方案
Let-insertion 是BER 中的一个原始操作,它自动将传递的代码绑定到一个新生成的变量。
这是一个工作示例,假设您有返回数组元素平方的代码,
let power_elt xs i = xs.(i) * xs.(i)
我们想生成一个只有一个数组访问的优化代码
let power_elt xs i = let x = xs.(i) in x*x
在 MetaOCaml 样式中,我们可以使用genlet
它
let power_elt xs i =
let x = genlet .<xs.(i)>. in
.<.~x * .~x>.
生成的代码
let t = power_elt [|1;2;3|] 1;;
将会
val t : int code = .<let lv_8 = Stdlib.Array.get (* CSP xs *) 1 in lv_8 * lv_8>.
推荐阅读
- graphql - 如何使用 GraphQL 查询 Netlify CMS config.yml 以从选择小部件字段中提取值
- javascript - 通过cypress出价不少于DB中的随机金额
- node.js - Nestjs 无法将 undefined 或 null 转换为对象 nestjs 代码
- r - 在R中按条件堆叠多列
- wso2 - WSO2 IS - SAML 外部身份提供者 - 如何使用特定的密钥/证书
- python - Python Flask 错误:在导入“api”时,引发了 ImportError
- java - 管道'没有定义任何阶段',但它确实?
- python - Sequentially calculate RMSE for each row, each time using the next row (Pandas)
- scala - coursier scala3 util.Properties.versionMsg
- python - 你如何为海龟创建边界?