Is there any built-in function for human-readable F# quotations?

后端 未结 3 963
闹比i
闹比i 2021-01-13 10:47

When quoting

<@ 1 + 1 @>

I want \"1 + 1\"

instead of

\"Call (None, Int32 op_Addition[Int32,Int32,Int32](Int32

相关标签:
3条回答
  • 2021-01-13 11:21

    You'll have to write it yourself. See the F# quotations visualizer code as a guide for transforming the quotations abstract syntax tree.

    0 讨论(0)
  • 2021-01-13 11:21

    There is none, and it's not quite that easy, except in very simple cases. One of the main problems, for example, is the match construct. It is syntactic sugar for a whole bunch of if and switch statements (try printing a quotation with a match in, you'll see). Another one of those biggies are computation expressions, but I guess you could skip those at first.

    Then there is a the rabbit hole of ambiguities you'll have to resolve, with conventions like the pipe operator starts a new line, let starts a new line, indentation, infix, prefix, special cases like the (::) operator and so forth.

    All in all, doable, but not trivial. Sort of like decompiling.

    0 讨论(0)
  • 2021-01-13 11:41

    I have implemented a quotation decompiler as part of a larger open source project Unquote. It can decompile many simple F# quoted expressions as single-line non-light syntax strings (see the project's home page for a list of decompiler features). For example,

    > decompile <@ (11 + 3) / 2 = String.length ("hello world".Substring(4, 5)) @>;;
    val it : string =
      "(11 + 3) / 2 = String.length ("hello world".Substring(4, 5))"
    

    @Kurt Schelfthout is correct about the many challenges faced when decompiling F# Quotations into human readable form. But from my work so far, I believe that it is possible to write a quotation decompiler which can generate correct F# code. Take match expressions and computation expressions for example, the Unquote decompiler can produce correct F# code in the following simple cases:

    > decompile <@ match true with | true -> "hi" | _ -> "bye"  @>;;
    val it : string =
      "let matchValue = true in if matchValue then "hi" else "bye""
    
    > decompile <@ seq {yield 1; yield 2}  @>;;
    val it : string =
      "seq (Seq.delay (fun unitVar -> Seq.append (Seq.singleton 1) (Seq.delay (fun unitVar -> Seq.singleton 2))))"
    

    Infix and prefix operators are not too hard (as you can see in the first example), but source structure such as new lines and indentation is an interesting topic (though not terribly difficult, I think). However, single-line non-light syntax is sufficient for Unquote's requirements.

    0 讨论(0)
提交回复
热议问题