3

我正在尝试编写适合浮点、双精度等类型并使用算术运算的通用 Vector2 类型。有没有机会用 C#、F#、Nemerle 或任何其他或多或少成熟的 .NET 语言来实现它?

我需要一个解决方案

  • (1) 良好的性能(与我编写单独的 Vector2Float、Vector2Double 等类相同),
  • (2)这将使代码看起来不错(我不想在运行时为每个类发出代码)
  • (3) 并且会尽可能多地进行编译时检查。

由于原因 1 和 3,我不想使用动态。现在我正在检查 F# 和 Nemerle。

UPD:我希望这种类型有很多数学代码。但是,如果可能的话,我更愿意将代码放在扩展方法中。

UPD2: 'etc' 类型包括 int(我实际上怀疑我会使用)和 decimal(我想我可能会使用,但不是现在)。使用扩展方法只是个人喜好问题——如果有充分的理由不使用,请告知。

4

6 回答 6

8

正如 Daniel 所提到的,F# 有一个称为静态解析类型参数的功能,它超出了您在 C# 中使用普通 .NET 泛型所能做的事情。诀窍在于,如果您将函数标记为inline,F# 会自动生成专门的代码(有点像 C++ 模板),然后您可以使用 F# 类型系统的更强大功能来编写通用数学。

例如,如果您编写一个简单的 add 函数并使其inline

let inline add x y = x + y;;    

类型推断打印以下类型:

val inline add :
  x: ^a -> y: ^b ->  ^c
    when ( ^a or  ^b) : (static member ( + ) :  ^a *  ^b ->  ^c)

您可以看到推断的类型相当复杂 - 它指定了一个成员约束,该约束需要两个参数之一来定义一个+成员(标准 .NET 类型也支持这一点)好在这可以完全推断,所以你很少需要编写丑陋的类型定义。

正如评论中提到的,我写了一篇文章编写通用数字代码,其中详细介绍了如何在 F# 中执行此操作。我不认为这可以在 C# 中轻松完成,并且您在 F# 中编写的内联函数只能从 F# 调用(从 C# 调用它们基本上会使用动态)。但是您绝对可以在 F# 中编写通用数值计算。

于 2014-02-25T15:22:35.710 回答
3

这更直接地解决了您之前的问题。您不能将静态成员约束放在结构上,但可以将其放在static Create方法上。

[<Struct>]
type Vector2D<'a> private (x: 'a, y: 'a) =
  static member inline Create<'a  when 'a : (static member (+) : 'a * 'a -> 'a)>(x, y) = Vector2D<'a>(x, y)
于 2014-02-25T15:35:23.573 回答
1

不幸的是,仅 C# 并不能帮助您实现这一目标。在运行时发出结构也对您没有多大帮助,因为您的程序无法静态引用它们。

如果您真的不能复制代码,那么据我所知,“离线”代码生成是解决此问题的唯一方法。与其在运行时生成代码,不如使用AssemblyBuilder和朋友使用您的 Vector2 类型创建磁盘程序集,或者生成一串 C# 代码以提供给编译器。我相信一些本地库包装器采用了这种方法(即OpenTKSharpDX)。然后ilmerge,如果您想将这些类型合并到您的手动编码库之一,则可以使用。

我假设您必须来自 C++ 背景,使用模板可以轻松实现这一点。但是,您应该问自己是否真的需要基于整数、小数和其他“奇异”数字类型的 Vector2 类型。您可能也无法根据特定的 Vector2 参数化其余代码,因此这些努力可能不值得。

于 2014-02-25T13:16:54.520 回答
1

查看内联函数和静态解析类型参数

于 2014-02-25T14:14:44.140 回答
0

据我了解,您在编译时是严格类型,但您不在乎运行时发生了什么。Nemerle 语言目前不支持您想要的这种结构。但它支持宏并允许您编写 DSL 来生成任意代码。例如,您可以执行一些宏来分析此代码并将其转换为正确的类型。

def vec = vector { [1,2] };

假设我们有或创建了一个 VectorInt 类型,代码可以被翻译成

def vec = VectorInt(1,2);

当然,您可以在里面编写任何代码并将其转换为您想要的任何代码:)

运算符可以作为类的常用运算符来实现。Nemerle 还允许您定义任何运算符,例如 F#。

于 2014-03-18T23:30:55.163 回答
-2

使用泛型,这也是类型安全的

有关泛型的更多信息:http: //msdn.microsoft.com/en-us/library/512aeb7t.aspx

但是您也有可用的数据结构,例如ListDictionary

听起来你想要运算符重载,这有很多例子。没有真正的好方法只允许贴花,浮动等。您唯一能做的就是限制为结构,但这并不完全是您想要的。

于 2014-02-25T12:49:31.273 回答