Cha*_*nya 4 f# loops functional-programming
我正在尝试循环数组并返回一个值,如下所示.但是在if语句之后,这给了我一个错误.它说"这个表达式应该有类型单位但是有类型int"
let findMostSignificantBitPosition (inputBits:System.Collections.BitArray) =
for i = inputBits.Length - 1 to 0 do
if inputBits.[i] then
i
done
Run Code Online (Sandbox Code Playgroud)
我该怎么做?我正在使用递归循环重新编码它,因为它似乎是在函数式语言中执行此类循环的更可接受的方式,但我仍然想知道上面我做错了什么.
for
循环不应该返回值,它们只执行固定次数的操作然后返回()
(单位).如果你想迭代并最终返回一些东西,你可以:
在循环之外有一个引用,当你得到最终结果时,然后在循环返回引用内容之后
直接使用递归函数
使用一个更高阶的函数来封装遍历,让你专注于应用程序逻辑
如果您的数据结构支持它,则更高的功能很好.fold_left
但是,简单的遍历函数不支持过早地停止迭代.如果您希望支持这一点(显然在您的用例中会很有用),您必须使用具有过早退出支持的遍历.对于像你这样的简单函数,简单的递归函数可能是最简单的.
在F#中,还应该可以用命令式编写函数,使用yield
它将其转换为生成器,然后最终强制生成器获得结果.这可以看作是使用异常跳出循环的OCaml技术的对应物.
编辑:避免"过早停止"问题的一个很好的解决方案是使用一个懒惰的中间数据结构,它只能构建到第一个令人满意的结果.这是优雅而优秀的脚本风格,但仍然比直接退出支持或简单递归效率低.我想这取决于你的需求; 这个函数用于关键路径吗?
编辑:以下是一些代码示例.它们是OCaml,数据结构不同(其中一些使用电池库),但想法是一样的.
(* using a reference as accumulator *)
let most_significant_bit input_bits =
let result = ref None in
for i = Array.length input_bits - 1 downto 0 do
if input_bits.(i) then
if !result = None then
result := Some i
done;
!result
let most_significant_bit input_bits =
let result = ref None in
for i = 0 to Array.length input_bits - 1 do
if input_bits.(i) then
(* only the last one will be kept *)
result := Some i
done;
!result
(* simple recursive version *)
let most_significant_bit input_bits =
let rec loop = function
| -1 -> None
| i ->
if input_bits.(i) then Some i
else loop (i - 1)
in
loop (Array.length input_bits - 1)
(* higher-order traversal *)
open Batteries_uni
let most_significant_bit input_bits =
Array.fold_lefti
(fun result i ->
if input_bits.(i) && result = None then Some i else result)
None input_bits
(* traversal using an intermediate lazy data structure
(a --- b) is the decreasing enumeration of integers in [b; a] *)
open Batteries_uni
let most_significant_bit input_bits =
(Array.length input_bits - 1) --- 0
|> Enum.Exceptionless.find (fun i -> input_bits.(i))
(* using an exception to break out of the loop; if I understand
correctly, exceptions are rather discouraged in F# for efficiency
reasons. I proposed to use `yield` instead and then force the
generator, but this has no direct OCaml equivalent. *)
exception Result of int
let most_significant_bit input_bits =
try
for i = Array.length input_bits - 1 downto 0 do
if input_bits.(i) then raise (Result i)
done;
None
with Result i -> Some i
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1077 次 |
最近记录: |