2014-02-02 4 views
5

Я начал с небольшой оболочки OpenGL, и у меня возникла небольшая проблема. Я обычно создаю свои данные с такими записямиИдиоматические конструкторы в F #

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 = 
    ........ 

Проблема заключается в том, что это не представляется возможным с не tupled функций, и я не хочу смешивать мои Создать методы с tupled и не tupled функций.

Интересно, если я даже написал идиоматический код F # в первую очередь. Как вы подходите к этой «проблеме»?

ответ

6

Вы правы - если вы хотите определить необязательные параметры для метода, вам нужно определить аргументы в форме с чередованием. Один из способов, с помощью которого вы могли бы приблизиться к этому, - переместить реализацию вашего метода 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 (т. Е. Используя один метод с объявлением аргумента типа tuple и необязательными параметрами или используя описанный выше подход перегрузки). Например, если вы не используете мой метод перегрузки, и решили просто определить 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.

+0

Просто примечание: в F # 4.1 модуль-суффикс больше не нужен, [подразумевается] (https://blogs.msdn.microsoft.com/dotnet/2016/07/25/a-peek- в-F-4-1 /). Кроме того, 4.1 [теперь поддерживает типы записей структуры) (https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/records), что упрощает достижение того, о чем говорится в вашем последнем комментарии. – Abel

Смежные вопросы