2013-07-25 23 views
1

我是使用函数式语言进行编程的新手。我正在尝试实现F#tryFindIndex函数。在F#中使用选项类型实现tryFindIndex

let rec tryFindIndex func list = 
    match list with 
    | [] -> None 
    | hd::tl -> if func hd then Some(0) 
       else (tryFindIndex func tl) + 1 

的问题是与最后一行,因为加1引起的返回类型是不是“廉政选项”“诠释”。我需要递归跟踪索引。

+2

实际上,你可以看一下F#源代码,找出它是如何为编译器实现的。 TryFindIndex在这里https://github.com/fsharp/fsharp/blob/master/src/fsharp/FSharp.Core/list.fs#L370 –

+0

@John Palmer酷,谢谢! – airietis

回答

3

将索引作为附加参数传递。如果你不这样做,那么你的函数也不是尾递归的。还要将您的递归作为单独的循环来隐藏索引参数。

let tryFindIndex func list = 
    let rec loop func list index = 
     match list with 
     | [] -> None 
     | hd::tl -> if func hd then Some(index) 
        else loop func tl (index+1) 
    loop func list 0 

正如约翰在评论中指出,核心库实现的,看起来像这样:

let tryFindIndex f list = 
     let rec loop n = function[] -> None | h::t -> if f h then Some n else loop (n+1) t 
     loop 0 list 
+0

@snf对不起。在编辑生效之前,我一直在编辑它! – mydogisbox

+0

完美。我意识到需要一个额外的参数,但并没有意识到嵌套让声明能够解决这个问题。谢谢! – airietis

+0

@airietis嵌套let允许你定义一个局部范围的函数,然后在该范围内调用它。乐意效劳。还修复了你的'Some'使其中的索引。 – mydogisbox