F#中的惯用构造函数

迈克·克莱因(Maik Klein)

我从一个小的OpenGL包装器开始,然后遇到一个小问题。我通常用这样的记录创建数据

type Shader = 
    { Handle : int }
    static member Create filepath stype = 
        let h = loadshader filepath stype
        { Handle = h }

type VertexShader = 
    { shader : Shader }
    static member Create path = 
        { shader = Shader.Create path ShaderType.VertexShader }

type FragmentShader = 
    { shader : Shader }
    static member Create path = 
        { shader = Shader.Create path ShaderType.FragmentShader }

我一直在使用带有非元组函数的静态构造函数。但是现在我想要另一个我想拥有可选参数的类型。

喜欢

type VAO = 
    { Handle : int }

    static member Create vboList ?ibo =
     ........

问题在于,非组合函数似乎无法做到这一点,而且我不想将Create方法与元组和非组合函数混合使用。

我想知道我是否一开始就写惯用的F#代码。您将如何处理这个“问题”?

杰克·P。

没错-如果要为方法定义可选参数,则需要以元组形式定义参数。您可以采用的一种方法是将方法的实现转移Create到私有方法中(并重命名为,例如CreateImpl),然后将其重新定义Create为重载方法,该方法将简单地分派给实现。例如:

type VAO =
    { Handle : int }

    static member private CreateImpl (vboList, ibo : _ option) =
        failwith "Not implemented."

    static member Create vboList =
        VAO.CreateImpl (vboList, None)

    static member Create (vboList, ibo) =
        VAO.CreateImpl (vboList, Some ibo)

另一种方法是定义一个模块(需要将其放置在您的VAO类型的定义下方),该模块定义用于“包装”静态VBO.Create(...)方法的咖喱函数但是,这将起作用,您决定为其声明参数Create(即,使用具有元组样式参数声明和可选参数的单个方法,或者使用上述的重载方法)。例如,如果您不使用我的重载方法,而决定仅将其定义Createstatic member Create (vboList, ?ibo)

// The [<CompilationRepresentation>] attribute is necessary here, because it allows us to
// define a module which has the same name as our type without upsetting the compiler.
// It does this by suffixing "Module" to the type name when the assembly is compiled.
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix>]
module VAO =
    let create (vboList : _ list) =
        VAO.Create vboList

    let createWithIndex vboList ibo =
        VAO.Create (vboList, ibo)

这些模块函数非常简单,因此很有可能会被F#编译器自动内联,因此您无需为它们支付任何运行时成本。如果在Release模式下进行编译,请检查程序集的IL,但情况并非如此,则可以将inline关键字添加到函数定义中以强制将它们内联。(最好不要进行强制内联,除非您进行基准测试并确定它可以带来真正的性能提升。)

一个技巧,与您关于可选参数的问题无关,请考虑将至少某些类型重新定义为结构而不是F#记录。记录类型被编译为类(即引用类型),因此您无故支付额外的间接费用;将它们定义为结构将消除这种间接影响,并为您的应用程序提供更好的性能。更好的是,如果可以的话,请重用现有的OpenGL包装器库之一,例如OpenTKOpenGL4Net

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

F#:尝试支持在F#和C#惯用语中的构造函数中传递函数

来自分类Dev

F#中的通用构造函数

来自分类Dev

F#调用构造函数中的成员函数

来自分类Dev

F#对象构造函数

来自分类Dev

F#记录构造函数

来自分类Dev

F#构造函数约束

来自分类Dev

从F#中的序列构造中调用函数

来自分类Dev

模式匹配中的F#惯用转换?

来自分类Dev

如何在Scala中实现OCaml / F#的“函数”构造?

来自分类Dev

F#中的多个构造函数和类继承

来自分类Dev

如何在Scala中实现OCaml / F#的“函数”构造?

来自分类Dev

F#使用构造函数作为函数

来自分类Dev

在F#中获取目录大小的惯用方式

来自分类Dev

在F#中获取目录大小的惯用方式

来自分类Dev

使用F#更惯用

来自分类Dev

使用F#更惯用

来自分类Dev

F#类中的主要构造函数与结构之间的行为差异?

来自分类Dev

在理解F#中的类构造函数时遇到问题

来自分类Dev

创建辅助非通用构造函数时F#中的编译器错误

来自分类Dev

编写带有参数化构造函数的f#函数

来自分类Dev

在F#中扩展函数

来自分类Dev

有没有一种方法可以为F#构造函数中的函数指定命名参数?

来自分类Dev

接受F#中的函数的函数

来自分类Dev

在F#中使用私有构造函数创建类

来自分类Dev

F#“值或构造函数...未定义”

来自分类Dev

具有私有构造函数的F#结构声明

来自分类Dev

F#惯用语直到

来自分类Dev

表示空数据构造函数的惯用方式

来自分类Dev

在F#中,带有强制构造函数参数的对象初始化程序语法是什么?