2015-07-10 77 views
4

我很好奇列表模块/类型如何在F#中工作,具体是它优化了这个吗?F#中的列表如何实现?

let xs = ["1"; "2"; "3"] 

let ys = "0"::xs 

let zs = ["hello"; "world"]@xs 

我已经看过一些源https://github.com/fsharp/fsharp/blob/68e37d03dfc15f8105aeb0ac70b846f82b364901/src/fsharp/FSharp.Core/prim-types.fs#L3493似乎是相关领域。

我想知道,如果xs使ys时被复制。

我本来以为很容易,只是指向现有的列表,如果你只是负面因素的元素。

如果您串联我想这可能是不可能的,因为它需要变异列表的最后一个元素指向下一个?

如果有人能注释/从FSharp.Core的代码片段,将是理想的。

+0

当创建''ys'是xs'不深复制(这是不可改变的单链表的好处之一) – FuleSnabel

+0

你知道我在哪里能找到这个特定的F#的任何信息? – Willl

回答

8

所以List的实现有点奇怪。它实际上是作为一个有区别的联盟来实施的。从规格:

type 'T list = 
| ([]) 
| (::) of 'T * 'T list 

所以,你能想到的::因为有两个参数,并创建一个元组(这是快,因为它是独立于列表的大小)的功能。

@要复杂得多。这里是执行:

let (@) l1 l2 = 
     match l1 with 
     | [] -> l2 
     | (h::t) -> 
     match l2 with 
     | [] -> l1 
     | _ -> 
      let res = [h] 
      let lastCons = PrivateListHelpers.appendToFreshConsTail res t 
      PrivateListHelpers.setFreshConsTail lastCons l2; 
      res 

这两个奇怪的函数基本上改变了列表到位。 appendToFreshConsTail复制列表并返回最后一个元素。 setFreshConsTail然后更改最后一个元素,以使其下一个元素设置为l2而不是加入列表的[]

+0

最后一段是我正在寻找的!非常感谢! – Willl