我从一个小的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#代码。您将如何处理这个“问题”?
没错-如果要为方法定义可选参数,则需要以元组形式定义参数。您可以采用的一种方法是将方法的实现转移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
(即,使用具有元组样式参数声明和可选参数的单个方法,或者使用上述的重载方法)。例如,如果您不使用我的重载方法,而决定仅将其定义Create
为static 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包装器库之一,例如OpenTK或OpenGL4Net。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句