2010-02-02 2 views
6

T4는 C#/VB.NET의 "공식적인"코드 생성 엔진입니다. 그러나 F# doesn't support it (이것은 4 월부터이지만 더 새로운 언급을 찾을 수 없습니다). 그렇다면 F # 코드를 생성하는 좋은 방법은 무엇입니까?F # 코드 생성

편집 :

나는 F 번호에 2-3 finger trees을 구현하려는

. 이미 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와 같은 접근법은 그것을 완벽하게 보입니다 ...

+0

. 최근에 내가 해킹 한 것입니다. – nphx

답변

7

F #이 솔루션 탐색기의 사용자 지정 도구를 지원하지 않기 때문에 T4 파일을 C# 또는 Visual Basic 프로젝트에 배치하고 출력을 F # 프로젝트로 리디렉션 할 수 있습니다. 다음은 T4 Toolbox 함께 할 수있는 방법입니다 : 난 그냥 거기에 [이] (https://github.com/kerams/Templatus) 던질거야

<#@ 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(); 
    } 
} 

#> 
+1

불행히도 Module2.fs가 Library1.fsproj의 * bottom *에 추가되고 소스 파일의 순서가 F # :-(중요합니다. –

+1

"F #이 솔루션 탐색기의 사용자 지정 도구를 지원하지 않으므로" FsYacc, FsLex, 테스트 생성기 및 기타 MSbuild 확장과 같은 F # 프로젝트의 사용자 지정 도구를 사용하므로 평가 순서와 관련하여 파일을 올바른 순서로 * .fsproj 파일에 포함하거나 fsproj 파일을 자동으로 업데이트하지 마십시오.) 맨 아래에 파일을 추가하고 자동 생성되지 않은 파일 앞에 종속성이 있는지 확인하십시오. – Abel

6

그것은 당신의 행동에 달려 있습니다. 많은 T4 예제가 보여주는 것처럼 템플릿을 생성하는 데는 적합하지 않지만 일반적으로 F #의 코드 생성 또는 언어 지향 프로그래밍 작업을 위해 "combinators 라이브러리"[1]를 설계하는 것이 좋습니다. 아이디어는 생성하려고하는 코드를 나타내는 일부 결합자를 설계하고 결합 자에서 F # 소스 텍스트를 생성 한 다음 코드 DOM을 통해이를 컴파일합니다.

그러나 종종 코드를 생성하는 것보다 귀하의 연결자에 대한 인터프리터를 작성하는 것이 더 쉽습니다. F 번호에 콤비의

좋은 예는 다음과 같습니다

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

+1

명확히하기 위해 - 당신은 소스 코드로 변환 할 수있는 차별화 된 유니온 계층 구조와 같은 것을 출력하는 연결 라이브러리를 작성하는 것이 좋습니다. FParsec 자체를 사용하여 코드를 생성하는 것과는 대조적으로 말입니다. FParsec의 일부 숨겨진 기능을 내가 모르고 있었는지 확인하고 싶습니다. –

+0

네, 시작하기 좋은 곳은 F # 코드로 변환 될 수있는 공용체 유형이 될 것입니다. FParsec은 결합 라이브러리의 예제 일 뿐이며 적어도 필자가 알고있는 한 F # 코드는 생성하지 않습니다. – Robert

1

확실히 어떤 상황 곳이 있기는하지만 나는 대부분 (로버트에 동의 F #에서 T4를 사용하면 매우 유용 할 수 있습니다.) 어쨌든, 아마도 을 알면 흥미로울 것입니다. F # 코드를 생성 하시겠습니까? 그런 다음 문제에 대한 전형적인 기능적 해결책을 제시 할 수 있습니다.

+0

내 용도를 추가했습니다. –

+0

저는이 문제를 어떻게 우아하게 해결할 수 있을지 전혀 모르겠습니다. 저는 전에 비슷한 문제가 있었지만 좋은 방법을 찾지 못했습니다. T4 (또는 유사)가 작동하더라도, 모든 F # 편집 시간 유형 검사가 중단되어 매우 성가시다. OCaml에서 이것은 Campl4 (http://en.wikipedia.org/wiki/Camlp4)에 의해 해결되었지만 F #과 동일한 것은 없습니다. (그리고 이것에 대한 필요성이 특히 두려워요. 특히 다른 가능한 F # 개선 사항). –

+1

배열 대 튜플 - 배열의 성능 (경계 검사 포함)이 나쁘지 않을 수도 있습니다. (결국 CLR은 많은 경우 검사를 피할 수 있습니다.) 그러나 F # 목록을 사용하여 기능적 솔루션을 시도해 볼 수도 있습니다 (직접 인덱싱을 피할 수있는 경우). 매우 작은 목록은 매우 빠릅니다 (그러나 불행히도 숫자가 없습니다). –

3

다양한 옵션을 둘러 보았고 fprintf이있는 TextWriter를 사용하는 * .fsx 스크립트를 사용하여 상대적으로 간단하고 정적 인 코드 생성 요구 사항이 발생하여 생성 된 F # 코드를 작성했습니다.

사실 FParsec을 일부 구문 분석 작업에 사용합니다. 그러나 다른 구문을 F #으로 변환하지 않아서 두 조각이 서로 거의 관련이 없습니다.

+0

충분할 수 있습니다. –

+1

물론 내 대답에 잘못된 점을 말하면서 그 downvotes를 좋아하지 않습니다. 나는 그들로부터 많은 것을 배웁니다! –