Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
元编程中F#引用和模式匹配的混淆_F#_Metaprogramming - Fatal编程技术网

元编程中F#引用和模式匹配的混淆

元编程中F#引用和模式匹配的混淆,f#,metaprogramming,F#,Metaprogramming,1-在元编程中应用F#引号和模式时,我真的很困惑,请建议一些在F#中接近这个概念的方法 2-你能给我展示一下F#引号和模式在元编程中的一些实际应用吗 3-有些人说他甚至可以用F#的IronScheme来制作另一种语言,对吗 谢谢。F#quotes允许您标记某段F#代码并获取源代码的表示形式。这在WebSharper中使用(参见示例),以将F#代码转换为JavaScript。另一个例子是对LINQ的F#支持,其中标记为的代码被转换为SQL: let res = <@ for p in db.

1-在元编程中应用F#引号和模式时,我真的很困惑,请建议一些在F#中接近这个概念的方法

2-你能给我展示一下F#引号和模式在元编程中的一些实际应用吗

3-有些人说他甚至可以用F#的IronScheme来制作另一种语言,对吗

谢谢。

F#quotes允许您标记某段F#代码并获取源代码的表示形式。这在WebSharper中使用(参见示例),以将F#代码转换为JavaScript。另一个例子是对LINQ的F#支持,其中标记为
的代码被转换为SQL:

let res = <@ for p in db.Products 
               if p.IsVisible then yield p.Name @> |> query
例如,这里我们使用模式匹配来计算数值表达式的一些表示。第一种模式是处理乘法的一个参数为0的情况的优化

编写语言您可以使用F#(就像任何其他通用语言一样)为其他语言编写编译器和工具。在F#中,这很容易,因为它附带了生成词法分析器和解析器的工具。例如,见

1-在元编程中应用F#引号和模式时,我真的很困惑,请建议一些在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;}
>;;
val it:Quotents.Expr=
调用(无,Int32运算加法[Int32,Int32,Int32](Int32,Int32),
[价值(1)、价值(2)])
{CustomAttributes=[NewTuple(值(“调试范围”),
新的(值(“标准数据”)、值(3)、值(3)、值(3)、值(3)、值(6));
原始=。。。;
Type=System.Int32;}
然后,您可以对该数据结构进行黑客攻击,以便对代码进行转换,例如将其从F#转换为Javascript,以便在几乎任何浏览器的客户端上运行它

2-你能给我展示一下F#引号和模式在元编程中的一些实际应用吗

与OCaml和Lisp等语言的引用机制相比,F#引用机制的功能极其有限,以至于我想知道为什么会添加它。此外,尽管.NET Framework和F#编译器提供了全速编译和执行引用代码所需的一切,但引用代码的求值机制比真正的F#代码慢几个数量级,这也使得它实际上毫无用处。因此,除此之外,我不熟悉it的任何实际应用

例如,您只能在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
>;;
;;
---^^^^
C:\Users\Jon\AppData\Local\Temp\stdin(4,4):错误FS0010:引号文字中出现意外的关键字“type”
大多数引用机制允许您引用任何有效的代码。例如,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>)
$ledit ocaml dynlink.cma camlp4oof.cma
目标Caml版本3.12.0
Camlp4解析版本3.12.0
#开放式Camlp4。预制;;
#让_loc=loc.ghost;;
val _loc:Camlp4.preducted.loc.t=。特别要注意的是,模式匹配非常容易对每种不同类型的表达式进行操作:

> 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>
>让rec eval vars=函数
|EApply(函数,参数)->
将eval vars func、eval vars arg与
|VClosure(变量,变量,主体),参数->评估((变量,参数)::变量)主体
|->无效的参数“尝试应用非函数值”
|EAdd(e1,e2)->VInt(内部(评估变量e1)+内部(评估变量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)->求值变量(如果是bool(求值变量p),则为t else f)
|EInt i->VInt i
|电气(变量、参数、主体、其余)->
让rec vars=(var,VClosure(arg,vars,body))::中的变量
eval vars rest
|EVar s->List.assoc s vars;;
val eval:(字符串*值)列表->表达式->值=
这篇OCaml文章被用作F#NET杂志文章的基础

3-有些人说他甚至可以用F#的IronScheme来制作另一种语言,对吗

是的,你可以用F#编写编译器。事实上,F#源自一个专门为元编程设计的语言家族,即所谓的元语言(MetaLanguages,ML)家族

来自F#NET杂志的文章描述了一种称为Brainf*ck的最小语言的简单编译器的设计和实现。您可以扩展它来实现更复杂的语言,如Scheme。事实上,F#编译器大部分是用F#本身编写的


与此相关的是,我刚刚完成了一个项目,编写了高性能序列化代码,该代码使用反射在项目中使用F#类型,然后吐出F#代码对这些类型的值进行序列化和反序列化

关于解析器和编译器的最后一个问题是它自己的领域,与引用或元编程无关。也许把问题3分解成一个单独的问题?我认为模式在其他语言的创造中起着重要的作用?”朱丽叶:呃?编译是元编程。。你是真实世界函数式编程的作者吗?我不希望从你那里得到答案:D.我们不是在语言本身的元编程中使用F#quote&Active模式吗?但是你只能引用某些类型的表达式,不能引用F#中的任何代码,使用它的引用机制,对吗?@Dark:是的,就是我。元编程是一个非常广泛的术语,引用和活动模式都是元编程的形式。引用更为普遍,活动模式是一种有一定限制的库形式
$ 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)
> 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>