1-我真的很混淆应用F#Quotation&关于元编程的模式,请建议在F#中使用某种方法来处理这个概念。
2-你能告诉我元编程中F#语录和模式的一些实际应用吗?
3-有些人说他甚至可以用F#制作另一种语言如IronScheme,是吗?
感谢。
答案 0 :(得分:28)
1-我真的很混淆应用F#Quotation&关于元编程的模式,请在F#中提出一些方法来解决这个概念。
引用机制允许您在代码中嵌入代码,并让编译器将您提供的源代码转换为代表它的数据结构。例如,下面给出了一个表示F#表达式1+2
的数据结构:
> <@ 1+2 @>;;
val it : Quotations.Expr<int> =
Call (None, Int32 op_Addition[Int32,Int32,Int32](Int32, Int32),
[Value (1), Value (2)])
{CustomAttributes = [NewTuple (Value ("DebugRange"),
NewTuple (Value ("stdin"), Value (3), Value (3), Value (3), Value (6)))];
Raw = ...;
Type = System.Int32;}
然后,您可以破解此数据结构,以便将转换应用于您的代码,例如将其从F#转换为Javascript,以便在几乎任何浏览器上运行客户端。
2-你能告诉我元编程中F#语录和模式的实际应用吗?
与OCaml和Lisp等语言的引用机制相比,F#引用机制的功能非常有限,我想知道它为何被添加。此外,虽然.NET Framework和F#编译器提供了全速编译和执行引用代码所需的一切,但引用代码的评估机制比实际F#代码慢几个数量级,这再次使它几乎无用。因此,我不熟悉Websharper以外的任何实际应用。
例如,您只能在F#中引用某些类型的表达式而不能引用其他代码,例如类型定义:
> <@ type t = Int of int @>;;
<@ type t = Int of int @>;;
---^^^^
C:\Users\Jon\AppData\Local\Temp\stdin(4,4): error FS0010: Unexpected keyword 'type' in quotation literal
大多数引用机制都允许您引用任何有效代码。例如,OCaml的报价机制可以引用F#刚刚禁止的类型定义:
$ ledit ocaml dynlink.cma camlp4oof.cma
Objective Caml version 3.12.0
Camlp4 Parsing version 3.12.0
# open Camlp4.PreCast;;
# let _loc = Loc.ghost;;
val _loc : Camlp4.PreCast.Loc.t = <abstr>
# <:expr< 1+2 >>;;
- : Camlp4.PreCast.Ast.expr =
Camlp4.PreCast.Ast.ExApp (<abstr>,
Camlp4.PreCast.Ast.ExApp (<abstr>,
Camlp4.PreCast.Ast.ExId (<abstr>, Camlp4.PreCast.Ast.IdLid (<abstr>, "+")),
Camlp4.PreCast.Ast.ExInt (<abstr>, "1")),
Camlp4.PreCast.Ast.ExInt (<abstr>, "2"))
# <:str_item< type t = Int of int >>;;
- : Camlp4.PreCast.Ast.str_item =
Camlp4.PreCast.Ast.StSem (<abstr>,
Camlp4.PreCast.Ast.StTyp (<abstr>,
Camlp4.PreCast.Ast.TyDcl (<abstr>, "t", [],
Camlp4.PreCast.Ast.TySum (<abstr>,
Camlp4.PreCast.Ast.TyOf (<abstr>,
Camlp4.PreCast.Ast.TyId (<abstr>,
Camlp4.PreCast.Ast.IdUid (<abstr>, "Int")),
Camlp4.PreCast.Ast.TyId (<abstr>,
Camlp4.PreCast.Ast.IdLid (<abstr>, "int")))),
[])),
Camlp4.PreCast.Ast.StNil <abstr>)
FWIW,这是Common Lisp中的一个例子:
$ sbcl
This is SBCL 1.0.29.11.debian, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.
SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses. See the CREDITS and COPYING files in the
distribution for more information.
* '(+ 1 2)
(+ 1 2)
元编程是一种应用程序,其中模式匹配非常有用,但模式匹配是一种通用语言功能。您可能会感谢my article from the Benefits of OCaml about a minimal interpreter。特别要注意模式匹配是如何容易地对每种不同的表达式起作用的:
> let rec eval vars = function
| EApply(func, arg) ->
match eval vars func, eval vars arg with
| VClosure(var, vars, body), arg -> eval ((var, arg) :: vars) body
| _ -> invalid_arg "Attempt to apply a non-function value"
| EAdd(e1, e2) -> VInt (int(eval vars e1) + int(eval vars e2))
| EMul(e1, e2) -> VInt (int(eval vars e1) * int(eval vars e2))
| EEqual(e1, e2) -> VBool (eval vars e1 = eval vars e2)
| EIf(p, t, f) -> eval vars (if bool (eval vars p) then t else f)
| EInt i -> VInt i
| ELetRec(var, arg, body, rest) ->
let rec vars = (var, VClosure(arg, vars, body)) :: vars in
eval vars rest
| EVar s -> List.assoc s vars;;
val eval : (string * value) list -> expr -> value = <fun>
该OCaml文章被用作F#.NET期刊文章"Language-oriented programming: The Term-level Interpreter" (31st December 2007)的基础。
3-有些人说他甚至可以用F#制作另一种语言如IronScheme,是吗?
是的,您可以在F#中编写编译器。事实上,F#源自一系列专门为元编程设计的语言,即所谓的MetaLanguages(ML)系列。
来自F#.NET Journal的文章"Run-time code generation using System.Reflection.Emit" (31st August 2008)描述了一个名为Brainf * ck的最小语言的简单编译器的设计和实现。您可以扩展它以实现更复杂的语言,如Scheme。实际上,F#编译器主要是用F#编写的。
在相关的说明中,我刚刚完成了一个编写高性能序列化代码的项目,该代码使用反射来消耗项目中的F#类型,然后吐出F#代码来序列化和反序列化这些类型的值
答案 1 :(得分:14)
F#引用允许您标记一些F#代码并获取源代码的表示。这是在WebSharper中使用(例如参见this tutorial)将F#代码转换为JavaScript。另一个例子是对LINQ的F#支持,其中标记为<@ ... @>
的代码被转换为SQL:
let res = <@ for p in db.Products
if p.IsVisible then yield p.Name @> |> query
模式匹配只是一种非常强大的语言结构,但它并不比例如if
更神秘。我们的想法是,您可以将值与模式匹配,程序将选择第一个匹配的分支。这很有用,因为模式可以嵌套,因此您可以使用它来处理各种复杂的数据结构或实现符号处理:
match expr with
| Multiply(Constant 0, _) | Multiply(_, Constant 0) -> 0
| Multiply(expr1, expr2) -> (eval expr1) * (eval expr2)
// (other patterns)
例如,这里我们使用模式匹配来评估数值表达式的一些表示。第一种模式是一种优化,用于处理乘法的一个参数为0的情况。
编写语言您可以使用F#(就像任何其他通用语言一样)为其他语言编写编译器和工具。在F#中,这很容易,因为它带有用于生成词法分析器和解析器的工具。请参阅示例this introduction。