问题描述
在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 时,输入一个名称已存在的函数(有关阴影的更多信息,请参阅例如)。这意味着当你运行你的代码时,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的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!