F#内存管理
F# memory management
在 F# 中,当您在循环中传递数组(递归函数调用自身)时,数组是否会在每个循环中放入堆栈(增加内存消耗)?循环时如何处理列表或引用对象?你能以某种方式最小化内存消耗吗,也许通过使用 ref(引用)?
如果您编写尾递归函数,那么 F# 将进行尾调用优化,这样堆栈就不会在每次递归调用中增长。
如果你有一个非尾递归的函数,你可以使用一种称为连续传递风格的东西,并使用堆而不是堆栈来累积中间值。
只要您的函数是尾递归的,您就不必担心。这仅仅意味着你的函数做的最后一件事就是调用它自己。示例:
let rec fact x =
if x < 1 then 1
else x * fact (x - 1)
这个函数在 (x - 1) 之后乘以 x,所以它不是尾递归的。
数组是引用类型,因此当您将数组作为参数传递时,您并不是在复制或构造数组。如果您在递归函数中传递数组,则不会产生 space 开销。
例如:
let rec loop a i =
if 0 <= i && i < Array.length a then
loop a (a.[i])
else
a.[i]
这个函数在数组中跳转,直到它找到一个不是数组索引的值。假设尾调用优化,它没有 space-开销,即它不分配任何东西。
在 F# 中,当您在循环中传递数组(递归函数调用自身)时,数组是否会在每个循环中放入堆栈(增加内存消耗)?循环时如何处理列表或引用对象?你能以某种方式最小化内存消耗吗,也许通过使用 ref(引用)?
如果您编写尾递归函数,那么 F# 将进行尾调用优化,这样堆栈就不会在每次递归调用中增长。
如果你有一个非尾递归的函数,你可以使用一种称为连续传递风格的东西,并使用堆而不是堆栈来累积中间值。
只要您的函数是尾递归的,您就不必担心。这仅仅意味着你的函数做的最后一件事就是调用它自己。示例:
let rec fact x =
if x < 1 then 1
else x * fact (x - 1)
这个函数在 (x - 1) 之后乘以 x,所以它不是尾递归的。
数组是引用类型,因此当您将数组作为参数传递时,您并不是在复制或构造数组。如果您在递归函数中传递数组,则不会产生 space 开销。
例如:
let rec loop a i =
if 0 <= i && i < Array.length a then
loop a (a.[i])
else
a.[i]
这个函数在数组中跳转,直到它找到一个不是数组索引的值。假设尾调用优化,它没有 space-开销,即它不分配任何东西。