我正在为F#中的矩阵类实现切片表达式,这意味着我必须实现三个GetSlice
方法。我的问题是通过利用核心库中的现有功能来获得有效的方法。这三种方法的签名如下:
member GetSlice : idx1:int * start2:int option * end2:int option -> IMatrix
member GetSlice : start1:int option * end1:int option * idx2:int -> IMatrix
member GetSlice : start1:int option * end1:int option *
start2:int option * end2:int option -> IMatrix
考虑这三者的最终结果。矩阵类有一个名为float[,]
的私有entries
字段,用于保存矩阵数据。最自然的实现是这样的:
member this.GetSlice (?start1 : int, ?end1 : int, ?start2 : int, ?end2 : int) =
let newEntries = entries.GetSlice(?start1 = start1, ?end1 = end1,
?start2 = start2, ?end2 = end2)
new Matrix(newEntries),
只使用GetSlice
实现的float[,]
功能。但是,这不会编译,因为GetSlice
扩展方法不可用(至少没有我打开的命名空间)。我原以为这个方法默认在FSharp.Core中可用,但实际情况并非如此。基于float[,]
的切片表达式的手动实现可能看起来像这样
member this.GetSlice (?start1 : int, ?end1 : int, ?start2 : int, ?end2 : int) =
let newEntries = match (start1, end1, start2, end2) with
| Some(sta1), Some(end1), Some(sta2), Some(end2) -> entries.[sta1 .. end1, sta2 .. end2]
| Some(sta1), Some(end1), Some(sta2), None -> entries.[sta1 .. end1, sta2 .. ]
(...)
new Matrix(entries),
这将需要16个模式案例,因此有些不方便。是否有更简单的选项,可能基于某种方式获得GetSlice
的{{1}}扩展方法的访问权限?
答案 0 :(得分:6)
您可以使用defaultArg
为这些选项指定值,然后在数组中将它们切片:
member __.GetSlice (?start1 : int, ?end1 : int, ?start2 : int, ?end2 : int) =
let start1, end1, start2, end2 =
defaultArg start1 0,
defaultArg end1 (Array2D.length1 entries - 1),
defaultArg start2 0,
defaultArg end2 (Array2D.length2 entries - 1)
new Matrix (entries.[start1 .. end1, start2 .. end2])
答案 1 :(得分:0)
扩展方法只是语法糖,使静态方法看起来像实例方法。
如果您在GetSlice
扩展方法上点击“转到定义”(我猜你看到它在另一个项目中工作了吗?),您将能够看到它背后的“真实”静态方法。它将类似于:
public static class SomeMatrixUtilityLibrary.ExtensionMethods
{
public static float[,] GetSlice(this float[,] array2d,
int start1,
int end1,
int start2,
int end2)
{
//...
}
}
静态方法在F#中运行得很好,你只需要正常调用它而不是通过扩展语法。