为什么我不能把这个字符串变成Literal?

Sol*_*lma 4 f# constant-expression

我需要将字符串转换为Literal,以便将其作为参数传递给CsvProvider.但我无法做到.下面的代码运行没有问题:

open System.IO
open FSharp.Data
open FSharp.Data.JsonExtensions

let charSwitch (a: char) b x =
    if x = a then
        b
    else
        x

let jsonDataPath = Path.Combine(__SOURCE_DIRECTORY__, @"data\fractal.json")
let jsonData = JsonValue.Load(jsonDataPath)

/// Path with traded assets
let trp = ((jsonData?paths?tradedAssets).AsString() |> Core.String.map (charSwitch '\\' '/')).ToString()
printfn "trp is a standard string: %s" trp
// trp is a standard string: H:/Dropbox/Excel/Data/Fractal/Traded.csv
Run Code Online (Sandbox Code Playgroud)

但是,添加以下两行时

[<Literal>]
let tradedPath = trp
Run Code Online (Sandbox Code Playgroud)

最后我得到了消息This is not a valid constant expression or custom attribute value.

我甚至试图复制trp,但这没有帮助.

有什么办法可以绕过这个问题吗?

The*_*ght 5

遗憾的是,通过将[<Literal>]属性应用于它,您无法将普通值神奇地转换为文字值.

关于文字值的特殊之处在于它被编译为常量,这意味着它们必须在编译时可以确定.

例如,这是一个文字字符串:

[<Literal>]
let testLiteral = "This is a literal string"
Run Code Online (Sandbox Code Playgroud)

您可以将多个文字字符串组合成一个新的文字字符串:

[<Literal>]
let a = "a"
[<Literal>]
let b = "b"
[<Literal>]
let ab = a + b
Run Code Online (Sandbox Code Playgroud)

您不能将任意函数应用于文字,因为它们在编译时无法确定.

更多关于文字.

  • @Soldalma该示例用于生成类型,因此没有,在编译时无法知道它.您的工作流程应该是使用可在编译时解析的模式文件,并在运行时通过`Load`方法为其提供遵循相同模式的不同目标. (4认同)

s95*_*163 3

看看你尝试使用的最后一条评论CsvProvider,你当然可以使用其他东西来解析csv文件,但也可以使用[<Litera>]以及__SOURCE_DIRECTORY__给出一个ResolutionFolder参数(虽然这必须是一个文字)给提供商。以下是两个示例,其中一个使用项目根目录中的示例来创建类型,但随后使用实际文件的命令行参数。另一种使用相对路径来解析文件。

open System
open FSharp.Data
open FSharp.Data.JsonExtensions


#if INTERACTIVE
#r @"..\packages\FSharp.Data.2.3.2\lib\net40\FSharp.Data.dll"
#endif 


[<Literal>]
let file = __SOURCE_DIRECTORY__ + @"\file1.csv"
[<Literal>]
let path3 = __SOURCE_DIRECTORY__
[<Literal>]
let path4 = "."

type SampleFile = CsvProvider<file,HasHeaders=true>
type SampleFile3 = CsvProvider<"file1.csv",HasHeaders=true,ResolutionFolder=path3>


[<EntryPoint>]
let main argv = 

    //let nonLiteralPath = @".\file1.csv" // you could hardcode this in the file but:
    let nonLiteralPath = argv.[0]  // you can also use a path specified on the command line
    let DataFile = SampleFile.Load(nonLiteralPath)
    [for row in DataFile.Rows -> row.``Key #1``]  |> printfn "%A"
    let x= SampleFile3.GetSample()  // use a relative path, this will be the root of the project at design time
                                    // or the root of the exe at the execution time
    [for row in x.Rows -> row.``Key #2``] |> printfn "%A"   

    printfn "%A" argv
Run Code Online (Sandbox Code Playgroud)

对于输出:

在此输入图像描述