所以这是我的问题。我有一个非常功能的python项目......但是它基本上是用类运行的......所以F#似乎是我的代码编译版本的理想语言(我想黑盒子我的源代码...... python代码只是坐在文件中。不酷。)
在我的python类中,我有一个通用容器 - 一个python列表。此容器将包含给定实现中的统一长度的数组...
这是我的问题:我需要在初始化后将数组添加到列表中。
将数组添加到类中的列表的正确方法是什么?
这就是我所拥有的...但似乎它会很慢,因为它会抛出一个新副本的旧列表(对吧??):
type myclass() =
let mutable _training = []
member this.training with get() = _training
and set(value) = _training <- value::_training
然而,这失败(即使在下面建议的修改之后),因为编译器声称set
函数是obj with set
而不是obj list with set
一个_training
,即使它承认<-
是设置函数中sortBy
左侧的可变obj列表......我很难过。
这样做的正确“F#”方法是什么?
答案 0 :(得分:3)
正确的&#39; F#的方法是根本没有myclass
类。具有单个getter和setter的类不会为不可变列表提供任何值。
尽管如此,上面的代码并没有因为多种原因而编译:
type
定义为=
,而不是:
。_training
不受let
表达式约束。_training
值,则必须声明let mutable
get
的返回值为obj list
,但set
(符号value
)的输入值为obj
,因为使用了cons运算符(::
)。正如编译器所说,get
和set
的类型必须相同。您可以通过解决所有这些问题进行编译:
type Myclass() =
let mutable _training = []
member this.training with get() = _training
and set(value) = _training <- value
但它什么都不会做。如果需要列表,则传递列表。并不是我们不相信F#中的封装,而是properties aren't equivalent to encapsulation anyway ......
顺便说一下,使用Pascal Case命名类型是惯用的,所以MyClass
而不是myclass
。领先的下划线也没有被使用,所以它应该是training
而不是_training
。
答案 1 :(得分:2)
问题是属性有类型, 并且getter和setter必须与该类型兼容。
如果我以交互方式运行您的代码,编译器会帮助我确切地告诉我!
type myclass() =
let mutable _training = []
member this.training
with get() = _training
and set(value) = _training <- value::_training
// error FS3172: A property's getter and setter must have the same type.
// Property 'training' has getter of type 'obj list'
// but setter of type 'obj'.
答案很简单,就是要有一个不同的方法来预先添加一个元素 到列表中:
type myclass() =
let mutable _training = []
member this.training
with get() = _training
and set(newTraining) = _training <- newTraining
member this.prepend(element) =
_training <- (element::_training)
member this.prependList(list) =
_training <- (list @ _training)
// test
let myList = myclass()
myList.prepend(1)
myList.prepend(2)
myList.training // output => [2; 1]
myList.prependList([3;4])
myList.training // output => [3; 4; 2; 1]
从功能的角度来看,它不是一个很好的实现, 但它确实回答了你的问题。
请注意,如果您确实需要纯功能实现, 你根本不需要上课。
// test
let myList = []
let myList2 = 1::myList
let myList3 = 2::myList2
// myList3 => [2; 1]
let myList4 = [3;4] @ myList3
// myList4 => [3; 4; 2; 1]
现在,如何以一种不错的方式使用不可变状态 - 这是一个整体 其他问题! :)