函数参数为null,即使传递了非null参数

时间:2015-05-13 03:27:43

标签: f#

F#newbie here,对不好的标题感到抱歉,我不知道怎么形容它 我有很奇怪的问题。以下是相关的代码段:

let calcRelTime (item :(string * string * string)) =
     tSnd item
     |>DateTime.Parse
     |> fun x -> DateTime.Now - x
     |> fun y -> (floor y.TotalMinutes).ToString()
     |>makeTriple (tFst item) (tTrd item) //makeTriple switches y & z. How do I avoid having to do that? 


let rec getRelativeTime f (l :(string * string * string) list) = 
    match l with
    | [] -> f
    | x :: xs -> getRelativeTime (List.append [calcRelTime x] f) xs

我使用Visual Studio逐步完成它,它清楚地显示getRelativeTime中的 x 是一个具有格式正确的日期时间字符串的3元组。但当我步骤calcRelTime 为空时。一切都会返回一个具有原始日期时间字符串的3元组,而不是一个总分钟过去的元组。在任何地方都没有其他错误,直到该datetime字符串命中一个期望它是整数字符串的函数。

任何帮助将不胜感激! (以及针对这些功能的任何其他F#样式提示/建议)。

2 个答案:

答案 0 :(得分:1)

item为null,因为尚未构建其中的部分。 F#编译器将tupled参数编译为单独的实际(IL级)参数,而不是类型Tuple<...>的一个参数。如果您在ILSpy中查看已编译的代码,您将看到此签名(使用C#语法):

public static Tuple<string, string, string> calcRelTime(string item_0, string item_1, string item_2)

这样做有几个原因,包括与其他CLR语言的互操作性以及效率。

可以肯定的是,元组本身就是根据这些参数构建的(除非你打开了优化),但不是马上。如果你迈出一步(点击F11),item将获得一个正确的非空值。

如果你去Debug - &gt;你也可以看到这些编译器生成的参数。 Windows - &gt; Visual Studio中的本地人。

至于为什么它返回原始列表而不是修改后的列表,我不能说:在我的设置上,一切都按预期工作:

> getRelativeTime [] [("x","05/01/2015","y")]
val it : (string * string * string) list = [("x", "y", "17305")]

也许如果你分享你的测试代码,我就能说出更多。

最后,你正在做的事情可以做得更简单:你不需要自己写一个递归循环,它已经在List模块的许多函数中为你完成,而你不需要接受元组,然后使用tFsttSndtTrd对其进行解构,编译器可以为您完成:

let getRelativeTime lst = 
   let calcRelTime (x, time, y) =
      let parsed = DateTime.Parse time
      let since = DateTime.Now - parsed
      let asStr = (floor since.TotalMinutes).ToString()
      (x, asStr, y)
   List.map calRelTime lst

答案 1 :(得分:1)

let getRelativeTime' list = 
    let calc (a, b, c) = (a, c, (floor (DateTime.Now - (DateTime.Parse b)).TotalMinutes).ToString())
    list |> List.map calc

该功能的签名是val getRelativeTime : list:('a * string * 'b) list -> ('a * 'b * string) list

您可以将函数声明中的item解构为(a, b, c),然后您不必使用函数tFsttSnd和{{1} }。

List模块有一个函数tTrd,它将一个函数应用于列表中的每个元素,并返回一个包含映射值的新列表。