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
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. What am I doing wrong here?
现在问题是,在for循环中,这个词变成了null。我在这里做错了什么?
EDIT: Here is the full code. I have changed it to printf as suggested. Unfortunately I still get null in word when inside the for-loop:
编辑:这里是完整的代码。我已经把它改成了printf。不幸的是,在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
3 个解决方案
#1
2
I suspect this is due to the lazy evaluating nature of 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.
我怀疑这是由于f#的惰性评估特性所致。因此,在printf语句使用它之前,word并没有被分配,因此您无法在调试器中看到值。
If you add another statement in your loop and set a breakpoint there, you will see the value of assigned value of 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
#2
4
I understand you want your code to look like C#. But F# is a functional language (not strictly, but that's main paradigm) and in these features lies the power of the language. First your collection. A more idiomatic type is a List. It's immutable which is one of the functional features of the language.
我理解您希望您的代码看起来像c#。但是f#是一种函数式语言(不是严格意义上的,但这是主要的范例),并且在这些特性中,语言的力量。首先你的收藏。一个更习惯的类型是列表。它是不可变的,这是语言的功能特征之一。
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. Since we switched to a functional collection use one of the built-in List functions to iterate:
然后迭代。For循环是完全必要的构造。由于我们切换到功能集合,使用一个内置的列表函数来迭代:
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”)函数。
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
).
这个函数接受一个列表和另一个函数作为参数。匹配的列表。如果它是空的(|[])——执行该函数。否则,将列表拆分为头部和其他(头部::tail)执行头部(fn头部)的功能,并在其余的项上进一步循环(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")
#3
2
This works:
如此:
for word in words do
printf "%s" word
But if you really want debug output, are you loading the system.diagnostics namespace?
但是如果您真的想要调试输出,那么您是在加载系统吗?诊断名称空间?
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)
#1
2
I suspect this is due to the lazy evaluating nature of 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.
我怀疑这是由于f#的惰性评估特性所致。因此,在printf语句使用它之前,word并没有被分配,因此您无法在调试器中看到值。
If you add another statement in your loop and set a breakpoint there, you will see the value of assigned value of 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
#2
4
I understand you want your code to look like C#. But F# is a functional language (not strictly, but that's main paradigm) and in these features lies the power of the language. First your collection. A more idiomatic type is a List. It's immutable which is one of the functional features of the language.
我理解您希望您的代码看起来像c#。但是f#是一种函数式语言(不是严格意义上的,但这是主要的范例),并且在这些特性中,语言的力量。首先你的收藏。一个更习惯的类型是列表。它是不可变的,这是语言的功能特征之一。
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. Since we switched to a functional collection use one of the built-in List functions to iterate:
然后迭代。For循环是完全必要的构造。由于我们切换到功能集合,使用一个内置的列表函数来迭代:
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”)函数。
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
).
这个函数接受一个列表和另一个函数作为参数。匹配的列表。如果它是空的(|[])——执行该函数。否则,将列表拆分为头部和其他(头部::tail)执行头部(fn头部)的功能,并在其余的项上进一步循环(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")
#3
2
This works:
如此:
for word in words do
printf "%s" word
But if you really want debug output, are you loading the system.diagnostics namespace?
但是如果您真的想要调试输出,那么您是在加载系统吗?诊断名称空间?
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)