简体   繁体   English

为什么我不能在F#中打印这个数组?

[英]Why can't I print this array in F#?

I have this list in C#: 我在C#中有这个列表:

List<string> words = new List<string> { "how", "are", "you" };

I can easily print the content of the list with: 我可以轻松地打印列表的内容:

foreach(string word in words)
   Debug.WriteLine(word);

Now I want to do the same in F# (I understand from over here that a List<T> is similar to a ResizeArray): 现在我想在F#中做同样的事情(我从这里了解到List<T>类似于ResizeArray):

let words = ResizeArray<string>()
words.Add("how")
words.Add("are")
words.Add("you")

for word in words do
    Debug.WriteLine(sprintf "%s" word) 

Now the problem is, that in the for-loop word becomes null. 现在的问题是,for循环中的word变为null。 What am I doing wrong here? 我在这做错了什么?

EDIT: Here is the full code. 编辑:这是完整的代码。 I have changed it to printf as suggested. 我按照建议把它改成了printf。 Unfortunately I still get null in word when inside the for-loop: 不幸的是,当在for循环中时,我仍然会得到null:

let myFunction =
    let words = ResizeArray<string>()
    words.Add("how")
    words.Add("are")
    words.Add("you")

    for word in words do
        printf "%s" word // <-- word becomes null
    words

[<EntryPoint>]
let main argv = 
    ignore myFunction
    0 // return an integer exit code

I understand you want your code to look like C#. 我知道你希望你的代码看起来像C#。 But F# is a functional language (not strictly, but that's main paradigm) and in these features lies the power of the language. 但是F#是一种功能性语言(不严格,但这是主要范例),并且在这些功能中存在着语言的力量。 First your collection. 首先是你的收藏。 A more idiomatic type is a List. 更惯用的类型是List。 It's immutable which is one of the functional features of the language. 它是不可变的,这是该语言的功能特征之一。

let words = ["how"; "are"; "you"]

Since it's immutable you expand it by creating a new collection. 由于它是不可变的,因此您可以通过创建新集合来扩展它。 You can append an item at the beginning: 您可以在开头追加项目:

let moreWords = "Hello" :: words

or join one list with another one: 或者将一个列表加入另一个列表:

let evenMore = moreWords @ ["I"; "am"; "fine"]

Then iterating. 然后迭代。 For loop is purely imperative construct. For循环是纯粹的命令式构造。 Since we switched to a functional collection use one of the built-in List functions to iterate: 由于我们切换到功能集合,因此使用其中一个内置List函数进行迭代:

let prnt lst = lst |> List.iter (fun x -> printfn "%s" x)

This takes a list. 这需要一个清单。 Iterates it item by item. 逐项迭代它。 And executes the (fun x -> printfn "%s" x) function on each item. 并在每个项目上执行(fun x -> printfn "%s" x)函数。

Or you can play a bit and write your own function to go through all the elements and execute a function on each of them. 或者你可以玩一点并编写自己的函数来遍历所有元素并在每个元素上执行一个函数。 One approach would be to use recursion and list matching: 一种方法是使用递归和列表匹配:

let rec loopFn lst fn =
    match lst with
    | [] -> fn
    | head::tail ->
        fn head
        loopFn tail fn

This funciton takes a list and another function as arguments. 该函数采用列表和另一个函数作为参数。 Matches the list. 匹配列表。 If it's empty ( | [] ) - performs the function. 如果它为空( | [] ) - 执行该功能。 Otherwise splits the list to head and the rest ( head::tail ) executes the function on the head ( fn head ) and loops further on the remaining items ( loopFn tail fn ). 否则将列表拆分为head,其余( head::tail )执行headfn head )上的函数,并在其余项( loopFn tail fn )上进一步循环。

To print the items pass to the function the list of words and a print function: 要打印项目,请将单词列表和打印功能传递给函数:

loopFn words (fun x -> printfn "%s" x)

or since printfn is a function itself you can simplify the call a bit: 或者因为printfn本身就是一个函数,你可以简化一下调用:

loopFn words (printfn "%s")

This works: 这有效:

for word in words do
    printf "%s" word

But if you really want debug output, are you loading the system.diagnostics namespace? 但是,如果您真的想要调试输出,是否要加载system.diagnostics命名空间?

open System.Diagnostics

(Your code)

This worked for me without loading the namespace: 这对我有用,无需加载命名空间:

for word in words do
    System.Diagnostics.Debug.Write(sprintf "%s" word)

I suspect this is due to the lazy evaluating nature of F#. 我怀疑这是由于F#的懒惰评估性质。 So, word is not actually assigned till it is used by the printf statement, and hence you cannot see the value in the debugger. 因此,在printf语句使用word之前,实际上并未分配word ,因此您无法在调试器中看到该值。

If you add another statement in your loop and set a breakpoint there, you will see the value of assigned value of word . 如果在循环中添加另一个语句并在那里设置断点,您将看到指定的word值。 See the snippet below - 请参阅下面的代码段 -

let myFunction =
let words = ResizeArray<string>()
words.Add("how")
words.Add("are")
words.Add("you")

for word in words do
    printf "%s" word // 
    printf "%s" word // <-- SET A BREAKPOINT HERE AND VERIFY THE VALUE OF 'word'

words

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM