【问题标题】:Can I avoid this casting in F#?我可以避免在 F# 中进行这种强制转换吗?
【发布时间】:2018-05-24 13:48:08
【问题描述】:

这个问题的上下文是我正在写的光线追踪器。

我有一个 Surface 类型,理想情况下我希望它是 NoSurface 和 Lambertian 继承的抽象基类。

但是,当我有这个层次结构时,我遇到了以下问题:

    let closestIntersection : bool*LineParameter*Surface = 
    match allIntersectionsWithRealSolutions with 
        | [] -> (false,0.0f, NoSurface(0UL,NotHitable(),Material(Vector3.Zero)))
        | x::xs -> List.reduce (fun smallest current -> smallestIntersection smallest current) allIntersectionsWithRealSolutions

这会引发编译器错误,因为它将返回类型绑定到的类型是 NoSurface,即使将类型指定为 Surface。

这解决了问题:

    let closestIntersection : bool*LineParameter*Surface = 
    match allIntersectionsWithRealSolutions with 
        | [] -> (false,0.0f, NoSurface(0UL,NotHitable(),Material(Vector3.Zero)) :> Surface)
        | x::xs -> List.reduce (fun smallest current -> smallestIntersection smallest current) allIntersectionsWithRealSolutions
closestIntersection

但是根据 BenchmarkDotNet,与将 Surface 定义为(非抽象)类并简单地返回它的解决方案相比,演员 :> 花费了我 25 毫秒!

我能否以某种方式避免显式转换并获得所需的 Surface 存在和抽象类层次结构?

【问题讨论】:

  • 试过upcast?
  • 你能提供一个代码示例吗?我对 F# 有点陌生
  • @FuleSnabel 我试过| [] -> (false,0.0f, (upcast NoSurface(0UL,NotHitable(),Material(Vector3.Zero)) : Surface)),是的,你是对的!它快了很多!也大约 25 毫秒。谢谢!为什么会出现这种性能差异?
  • 在本地尝试了一下,但我无法重现您看到的性能损失。这可能是因为我没有正确的类型定义。对于此类问题,我建议使用 dotPeek 之类的工具来查看您的代码被编译成什么。有时需要进入 IL 才能看到。
  • 嗯,我在一个非常递归的上下文中运行这个。也许在这种情况下进行投射会影响性能?如果你能解释为什么 upcast 比 :> 我会给你正确的答案。

标签: f#


【解决方案1】:

您可以尝试使用区分联合来解决相同的问题,因为您使用的是 F#?,这将是更“实用”的方式。虽然我有点确定这种方法可能会慢一些。但是,如果您追求最佳性能,托管语言并不是最好的选择。 在https://fsharpforfunandprofit.com/posts/discriminated-unions/找到一个好的工会解释

这样的。

type Intersectable =
    | Sphere of center:Point3 * radius:float
    | Triangle of v0:Point3 * v1:Point3 * v2:Point3
    | MeshTriangle of faceIndex:int * mesh:Mesh
    | Instance of Intersectable * Matrix.Matrix4x4
    | Plane of normal:Vec3 * pointOnPlane: Point3

共享/通用功能可以通过使用您的函数所作用的通用数据部分来处理,您可能有:

type Shape = {
    geometry: Intersectable
    material: Material }

【讨论】:

  • 感谢您的类型定义。我在想这样的事情。我可能会涉及到这个。如果它的速度较慢,请看 ;) 我不同意之前的观点。这里有灰色阴影。光线追踪(在我看来)是一个非常实用的问题。所以我想尝试F#。但仅仅因为我使用 F# 并不意味着我想运行糟糕/缓慢的代码。 HoF 和列表推导的能力真的很有帮助。
猜你喜欢
  • 2014-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-28
  • 1970-01-01
  • 1970-01-01
  • 2011-03-19
  • 1970-01-01
相关资源
最近更新 更多