调用重定义函数时,F#和Clojure的区别 [英] Difference in F# and Clojure when calling redefined functions

查看:199
本文介绍了调用重定义函数时,F#和Clojure的区别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在F#中:

 > let f x = x + 2 ;; 

val f:int - > int

> let g x = f x ;;

val g:int - > int

> g 10 ;;
val it:int = 12
> let f x = x + 3 ;;

val f:int - > int

> g 10 ;;
val it:int = 12

在Clojure中:

  1:1 user => (defn f [x](+ x 2))
#'user / f
1:2 user => (defn g [x](f x))
#'user / g
1:3 user => (g 10)
12
1:4 user => (defn f [x](+ x 3))
#'user / f
1:5 user => (g 10)
13

注意,在Clojure中,f的最新版本被调用在最后一行。在F#中,仍旧调用旧版本的f。为什么这个和它如何工作?

解决方案

> shadowing 时,输入一个名称已存在的函数(有关阴影的更多信息,请参阅例如这个SO问题)。这意味着当你运行你的代码时,F#编译器看到这样的东西:

 >令f 1 x = x + 2; 
> let g @ 1 x = f @ 1 x ;;
> g @ 1 10 ;;
val it:int = 12
> let f 2 x = x + 3 ;;
> g @ 1 10 ;;
val it:int = 12

F#使用一些名称不能直接使用来区分值的版本。另一方面,Clojure的行为可能最好被理解为一个大的函数字典。使用伪语法,像这样:

 >符号[f] = fun x-> x + 2 ;; 
>符号[g] = fun x-> symbol [f] x ;;
>符号[g] 10;
val it:int = 12
>符号[f] = fun x-> x + 3 ;;
>符号[g] 10;
val it:int = 13

>

作为旁注,Clojure方法存在一个可能的问题(至少对于像F#这样的语言)。你可以声明一个类型的函数,使用它,然后,下一个命令可以改变函数的类型。如果F#使用Clojure方法,下面的示例应该如何工作?

 >让f a b = a + b ;; 
> let g x = f x x;;
> let f()= printff!;;
> g 0 ;;

函数 g 使用 f ,因为它有两个类型 int 的参数,但是thrid行改变了函数的类型。这使得Clojure方法对于类型检查的语言有点棘手。


In F#:

> let f x = x + 2;;

val f : int -> int

> let g x = f x;;

val g : int -> int

> g 10;;
val it : int = 12
> let f x = x + 3;;

val f : int -> int

> g 10;;
val it : int = 12

In Clojure:

1:1 user=> (defn f [x] (+ x 2))
#'user/f
1:2 user=> (defn g [x] (f x))
#'user/g
1:3 user=> (g 10)
12
1:4 user=> (defn f [x] (+ x 3))
#'user/f
1:5 user=> (g 10)
13

Note that in Clojure the most recent version of f gets called in the last line. In F# however still the old version of f is called. Why is this and how does this work?

解决方案

As gabe said, F# interactive uses shadowing of values when you enter a function with a name that already exists (for more info on shadowing, see for example this SO question). This means that the F# compiler sees something like this when you run your code:

> let f@1 x = x + 2;; 
> let g@1 x = f@1 x;; 
> g@1 10;; 
val it : int = 12
> let f@2 x = x + 3;; 
> g@1 10;; 
val it : int = 12 

F# uses some mangled name (like @) that you cannot use directly to distinguish between versions of the value. On the other hand, Clojure's behavior can be probably best understood as a big dictionary of functions. Using pseudo-syntax, something like this:

> symbols[f] = fun x -> x + 2;; 
> symbols[g] = fun x -> symbols[f] x;; 
> symbols[g] 10;; 
val it : int = 12
> symbols[f] = fun x -> x + 3;; 
> symbols[g] 10;; 
val it : int = 13

This should make the distinction quite clear.

As a side-note, there is one possible problem with the Clojure approach (at least for a language like F#). You can declare a function of some type, use it and then, the next command can change the type of the function. If F# used the Clojure approach, how should the following example work?

> let f a b = a + b;;
> let g x = f x x;;
> let f () = printf "f!";;
> g 0;;

The function g uses f as if it had two parameters of type int, but the thrid line changes the type of the function. This makes the Clojure approach a bit tricky for type-checked languages.

这篇关于调用重定义函数时,F#和Clojure的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆