Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F# 词典列表';s vs字典序列';s_F# - Fatal编程技术网

F# 词典列表';s vs字典序列';s

F# 词典列表';s vs字典序列';s,f#,F#,在这个例子中,我很难理解F#的列表和Seq之间的区别。我认为主要的区别是Seq有点懒,但我肯定错过了什么 此代码段: open System.Collections.Generic let arr = ["a"; "b"; "c"] |> Seq.map (fun a -> let dic = Dictionary () in dic.Add("key", a); dic) in arr |> Seq.iter (fun a -> printfn "her

在这个例子中,我很难理解F#的列表和Seq之间的区别。我认为主要的区别是Seq有点懒,但我肯定错过了什么

此代码段:

open System.Collections.Generic
let arr = 
  ["a"; "b"; "c"]
  |> Seq.map (fun a -> let dic = Dictionary () in dic.Add("key", a); dic) in
arr
|> Seq.iter (fun a -> 
  printfn "here";
  a.["key"] <- "something"
  );
arr
|> Seq.iter (fun a -> printfn "%s" a.["key"])
鉴于(将第一个序号替换为列表)

为什么我使用Seq时字典值不改变?打印此处的
时,可以清楚地访问元素


提前谢谢。

原因正是你所说的
Seq
有点懒

它是“懒惰”的,因为每次你要求它时,它都会被评估。所有这些。直到最后一件非懒惰的事情

特别是,对
Seq.map
的调用是惰性的。它不会在内存中创建一个充满字典的新结构。相反,它创建了一些你可以称之为“管道”的东西。这个管道从您的列表开始,然后有一条指令:每当有人试图迭代这个序列时,为每个元素创建一个新的字典。“everytime”位在这里很重要-因为您在序列上迭代了两次(一次打印“here”,另一次打印值),所以字典也会被创建两次。将“某物”推入的字典和从中获取“键”的字典不是同一个字典

为了进一步说明,请尝试以下方法:

let s = ["a";"b";"c"] |> Seq.map( fun x -> printfn "got %s" x; x )
s |> Seq.iter(printfn "here's %s")
s |> Seq.iter(printfn "again %s")
这将打印以下内容:

got a
here's a
got b
here's b
got c
here's c
got a
again a
got b
again b
got c
again c
查看如何为每个元素生成两次“get”输出?这是因为
Seq.map
在每次迭代时都有效,而不是一次


列表则不然。每次
List.map
,您都会在内存中创建一个全新的列表。它只是永远地坐在那里(这里“永远”的定义是“直到垃圾收集器到达它为止”),并等待您对它做些什么。如果你用它做了很多事情,它仍然是同一个列表,不会被重新创建。这就是为什么您的词典总是相同的词典,它们不会像
Seq
中的词典那样重新创建。这就是为什么您可以修改它们,并在下次查看时看到修改


借助于
Seq.cache
,您可以对序列实现类似但不完全相同的效果。此函数接受一个常规的按需求值序列,并返回一个相同的序列,但每个元素只求值一次

但与列表不同,
Seq.cache
在调用整个序列时不会对其求值。相反,它将创建一个可变缓存,每次计算时都会更新该缓存

这对于序列非常大,甚至无限大的情况非常有用,但您只需要在序列开始时处理少量有限数量的元素

说明:

let s = ["a";"b";"c"] 
        |> Seq.map( fun x -> printfn "got %s" x; x ) 
        |> Seq.cache
s |> Seq.iter(printfn "here's %s")
s |> Seq.iter(printfn "again %s")
输出:

got a
here's a
got b
here's b
got c
here's c
again a
again b
again c

我在两个示例中都添加了一些
printfn
s,这样您就可以看到它们的区别:

let arr = 
    ["a"; "b"; "c"]
    |> Seq.map (fun a -> printfn "seq: %s" a
                         let dic = Dictionary ()
                         dic.Add("key", a)
                         dic)
arr
|> Seq.iter (fun a -> 
    printfn "here seq"
    a.["key"] <- "something"
)
arr
|> Seq.iter (fun a -> printfn "%s" a.["key"])
而这个,

let arr = 
    ["a"; "b"; "c"]
    |> List.map (fun a -> printfn "list: %s" a
                          let dic = Dictionary ()
                          dic.Add("key", a)
                          dic)
arr
|> Seq.iter (fun a -> 
    printfn "here list";
    a.["key"] <- "something"
)
arr
|> Seq.iter (fun a -> printfn "%s" a.["key"])
正如你所看到的,行为是完全不同的

Seq.map
是惰性的,这意味着它仍然是一个函数,只有在严格必要时才能被调用。每次调用它时,它都会从一开始就根据需要映射每个元素
Seq.map
被调用两次,每个
Seq.iter
调用一次,每次它为每个元素创建一个新的字典,然后被垃圾收集器丢弃

另一方面,
List.map
只被调用一次,它只在整个输入列表中创建一个新的字典列表一次

got a
here's a
got b
here's b
got c
here's c
again a
again b
again c
let arr = 
    ["a"; "b"; "c"]
    |> Seq.map (fun a -> printfn "seq: %s" a
                         let dic = Dictionary ()
                         dic.Add("key", a)
                         dic)
arr
|> Seq.iter (fun a -> 
    printfn "here seq"
    a.["key"] <- "something"
)
arr
|> Seq.iter (fun a -> printfn "%s" a.["key"])
seq: a
here seq
seq: b
here seq
seq: c
here seq
seq: a
a
seq: b
b
seq: c
c
let arr = 
    ["a"; "b"; "c"]
    |> List.map (fun a -> printfn "list: %s" a
                          let dic = Dictionary ()
                          dic.Add("key", a)
                          dic)
arr
|> Seq.iter (fun a -> 
    printfn "here list";
    a.["key"] <- "something"
)
arr
|> Seq.iter (fun a -> printfn "%s" a.["key"])
list: a
list: b
list: c
here list
here list
here list
something
something
something