10

T4 是 C#/VB.NET 的“官方”代码生成引擎。但是F# 不支持它(这是从四月开始的,但我找不到任何更新的提及)。那么生成 F# 代码的好方法是什么?

编辑:

我想在 F#中实现2-3 个手指树。我已经在 C# 中实现了它们,所以这应该是一个很好的比较。树的“数字”和节点可以表示为数组,所以

type 't FingerTree = Empty | Single of 't | Deep of 't array * (('t FingerTree) array) lazy * 't array

但是,这些数组的最大大小非常小,所以最好有

type 't Digit = Digit1 of 't | Digit2 of 't*'t | Digit3 of 't*'t*'t | Digit4 of 't*'t*'t*'t
type 't Node = Node2 of 't FingerTree * 't FingerTree | Node3 of 't FingerTree * 't FingerTree * 't FingerTree 
type 't FingerTree = Empty | Single of 't | Deep of 't Digit * ('t Node) lazy * 't Digit

避免边界检查等。

但随后在 Digit 和 Node 上手动编写所有函数变得更加困难,最好生成它们。类似 T4 的方法看起来非常适合它......

4

4 回答 4

8

由于 F# 不支持解决方案资源管理器中的自定义工具,因此您可以将 T4​​ 文件放在 C# 或 Visual Basic 项目中,并将其输出重定向到您的 F# 项目。以下是使用T4 Toolbox的方法:

<#@ template language="C#" hostspecific="True" debug="True" #>
<#@ output extension="txt" #>
<#@ include file="T4Toolbox.tt" #>
<#
    FSharpTemplate template = new FSharpTemplate();
    template.Output.Project = @"..\Library1\Library1.fsproj";
    template.Output.File = "Module2.fs";
    template.Render();
#>
<#+
class FSharpTemplate: Template
{
    public override string TransformText()
    {
#>
// Learn more about F# at http://fsharp.net

module Module2
<#+
        return this.GenerationEnvironment.ToString();
    }
}

#>
于 2010-02-04T12:17:57.413 回答
6

这取决于你想做什么。虽然这种方法并不真正适合以许多 T4 示例显示的方式生成模板,但总的来说,我建议为代码生成或 F# 中面向语言的编程任务设计一个“组合器库”[1]。这个想法是设计一些组合器来表示您尝试生成的代码,从组合器生成 F# 源文本,然后通过代码 DOM 编译它。

然而,通常为组合器编写解释器比生成代码更容易。

F# 中组合子的好例子是:

[1] http://en.wikipedia.org/wiki/Combinator_library

于 2010-02-02T09:13:55.600 回答
5

我查看了各种选项,最终使用 *.fsx 脚本来满足我相对简单和静态的代码生成需求,该脚本使用 TextWriterfprintf来写出生成的 F# 代码。

实际上,我确实使用 FParsec 进行一些解析工作,但由于我没有将其他语法转换为 F#,因此这两部分彼此之间几乎没有关系。

于 2010-02-02T22:28:08.537 回答
1

我基本同意 Robert 的观点(尽管在某些情况下使用 F# 中的 T4 可能非常有用)。无论如何,知道为什么要生成 F# 代码可能会很有趣?然后我们可能会建议一些典型的功能解决方案来解决这个问题:-)。

于 2010-02-02T21:45:40.927 回答