寓言实现外部接口编译错误

时间:2017-01-12 14:13:32

标签: f# fable-f#

TL; DR: 我试图创建一个外部接口,但我得到编译错误。我的F#技能还不等于任务。

我已经编写了一个Photoshop脚本,现在我正在尝试将该脚本转换为Fable(F#),用于我自己的F#练习。

旁注:我对F#很新,但我有一个很好的C#背景。

要使用photoshop脚本库,我需要将其定义为外部接口(http://fable.io/docs/interacting.html)。我试图首先实现一个小类用于测试目的。即UnitValue类(参见https://wwwimages.adobe.com/content/dam/Adobe/en/products/indesign/pdfs/JavaScriptToolsGuide_CS5.pdf p.230)

我的尝试:

#r "node_modules/fable-core/Fable.Core.dll"

open System
open Fable.Core

[<Global>]
module Photoshop =
    [<Erase;StringEnum>]
    type PSUnit =
        | [<CompiledName("in")>] Inches
        | [<CompiledName("ft")>] Feet
        | [<CompiledName("yd")>] Yards
        | [<CompiledName("mi")>] Miles
        | [<CompiledName("mm")>] Millimeters
        | [<CompiledName("cm")>] Centimeters
        | [<CompiledName("m")>] Meters
        | [<CompiledName("km")>] Kilometers
        | [<CompiledName("pt")>] Points
        | [<CompiledName("pc")>] Picas
        | [<CompiledName("tpt")>] TraditionalPoints
        | [<CompiledName("tpc")>] TraditionalPicas
        | [<CompiledName("ci")>] Ciceros
        | [<CompiledName("px")>] Pixels
        | [<CompiledName("%")>] Percent

    type PSUnitValue =
        abstract ``as``: PSUnit -> float
        abstract ``value``: float with get, set
        abstract ``type``: PSUnit with get, set    

    let UnitValue : PSUnitValue = jsNative

open Photoshop

let test = new UnitValue();
test.``value`` = 12.0;
test.``type`` = Unit.Centimeters

Console.WriteLine (test.``as`` PSUnit.Millimeters)

在编译期间,我得到:

C:\PsScripts>fable test.fsx
fable-compiler 0.7.28: Start compilation...
F# project contains errors:
C:\PsScripts\test.fsx(L35,15) : error FSHARP: The type 'UnitValue' is not defined
C:\PsScripts\test.fsx(L36,0) : error FSHARP: Lookup on object of indeterminate type based on information prior to this program point. A type annotation may be needed prior to this program point to constrain the type of the object. This may allow the lookup to be resolved.
C:\PsScripts\test.fsx(L37,0) : error FSHARP: Lookup on object of indeterminate type based on information prior to this program point. A type annotation may be needed prior to this program point to constrain the type of the object. This may allow the lookup to be resolved.
C:\PsScripts\test.fsx(L37,21) : error FSHARP: The field, constructor or member 'Centimeters' is not defined
C:\PsScripts\test.fsx(L39,19) : error FSHARP: Lookup on object of indeterminate type based on information prior to this program point. A type annotation may be needed prior to this program point to constrain the type of the object. This may allow the lookup to be resolved.
C:\PsScripts\test.fsx(L39,0) : error FSHARP: A unique overload for method 'WriteLine' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: Console.WriteLine(buffer: char []) : unit, Console.WriteLine(format: string, [<ParamArray>] arg: obj []) : unit, Console.WriteLine(value: bool) : unit, Console.WriteLine(value: char) : unit, Console.WriteLine(value: decimal) : unit, Console.WriteLine(value: float) : unit, Console.WriteLine(value: float32) : unit, Console.WriteLine(value: int) : unit, Console.WriteLine(value: int64) : unit, Console.WriteLine(value: obj) : unit, Console.WriteLine(value: string) : unit, Console.WriteLine(value: uint32) : unit, Console.WriteLine(value: uint64) : unit

我的预期输出将是:

var test = new UnitValue();
test.value = 12;
test.unit = "cm";
console.log(test.as("mm"));

对于那些想知道UnitValue课程外观并且不想在pdf中查找的人,我在这里用C#定义:

public class UnitValue
{
    // Static baseUnit not yet implemented in Fable
    public static UnitValue baseUnit { get; set; }

    // Constructors not yet implemented in Fable
    public UnitValue(float value, string unit) { }
    public UnitValue(string valueUnit) { }

    public string type { get; set; }
    public float value { get; set; }

    public float @as(string unit) { throw new NotImplementedException(); }

    // I don't use convert in my scripts, so not yet implemented in Fable as well
    public UnitValue convert(string unit) { throw new NotImplementedException(); }
}

2 个答案:

答案 0 :(得分:4)

  • 您绑定变量UnitValue,而不是声明类型的别名(不确定这是否是意图)。

  • 类型和值,就像在C#中有不同的范围一样,因此就编译器而言,未声明类型。

  • jsNative只是&#34; throw&#34;的简写,它适用于导入的JS结构,但您不会导入任何内容。请参阅http://fable.io/docs/interacting.html

  • 因为JS缺少类型,如果interop是意图,你实际上必须自己定义F#中的类型。

  • 如果互操作不是意图,那么写一个普通的F#代码,没有任何寓言属性,寓言将处理其余的事情。

在此处添加评论答案以进行格式化: UnitValue需要是一个函数(构造函数):

let UnitValue : unit->PSUnitValue = jsNative 

然后你可以称之为:

let test = UnitValue() 

同时结帐this post了解有关绑定的一些背景信息。

答案 1 :(得分:1)

Eugene Tolmachev的帮助下:

工作(ish)代码:

#r "node_modules/fable-core/Fable.Core.dll"

open System
open Fable.Core

module Photoshop =
    [<StringEnum>]
    type PSUnit =
        | [<CompiledName("in")>] Inches
        | [<CompiledName("ft")>] Feet
        | [<CompiledName("yd")>] Yards
        | [<CompiledName("mi")>] Miles
        | [<CompiledName("mm")>] Millimeters
        | [<CompiledName("cm")>] Centimeters
        | [<CompiledName("m")>] Meters
        | [<CompiledName("km")>] Kilometers
        | [<CompiledName("pt")>] Points
        | [<CompiledName("pc")>] Picas
        | [<CompiledName("tpt")>] TraditionalPoints
        | [<CompiledName("tpc")>] TraditionalPicas
        | [<CompiledName("ci")>] Ciceros
        | [<CompiledName("px")>] Pixels
        | [<CompiledName("%")>] Percent

    type PSUnitValue =
        abstract ``as``: PSUnit -> float
        abstract ``value``: float with get, set
        abstract ``type``: PSUnit with get, set    
    let [<Global>] UnitValue : unit->PSUnitValue = jsNative

open Photoshop

let test = UnitValue();
test.``value`` <- 12.0;
test.``type`` <- PSUnit.Centimeters

Console.WriteLine (test.``as`` PSUnit.Millimeters)

<强>输出

export var test = UnitValue(null);
test.value = 12;
test.type = "cm";
console.log(test.as("mm"));

我不知道export关键字在这里做了什么,或者为什么UnitValue没有new关键字,但它编译并查看我想要的方向。 ...

勇往直前!

我现在在输出中有new个关键字:

let [<Global;Emit("new $0($1, $2)")>] UnitValue (v: float) (t: PSUnit): IUnitValue = jsNative

现在用法是:

let test = UnitValue 12.0 PSUnit.Centimeters
Console.WriteLine (test.``as`` PSUnit.Millimeters)