F# 如何在F中直接重用从另一个函数返回的函数#
我目前正在从事一个项目,在这个项目中,我必须根据一些规则创建许多函数,并在以后重用这些函数。为此,我开始学习F,在F中似乎比在C中更自然 我成功地创建了应该创建的函数,但在重用它们时遇到了一些问题。下面是一个非常简单的例子,来说明我正在尝试做什么F# 如何在F中直接重用从另一个函数返回的函数#,f#,F#,我目前正在从事一个项目,在这个项目中,我必须根据一些规则创建许多函数,并在以后重用这些函数。为此,我开始学习F,在F中似乎比在C中更自然 我成功地创建了应该创建的函数,但在重用它们时遇到了一些问题。下面是一个非常简单的例子,来说明我正在尝试做什么 let choice = 2 let fCreator (x:float) = match choice with |1 -> x * x |2 -> x * 10.0 |3 -> x + 20
let choice = 2
let fCreator (x:float) =
match choice with
|1 -> x * x
|2 -> x * 10.0
|3 -> x + 20.0
|_ -> x
我有一个全局变量选择,根据它,在fCreator中选择并返回x的转换。这可以称之为
let result1 = fCreator 1.0
但问题是,我必须对许多不同的输入使用所选的转换(在这种情况下是x*10),并且以这种方式使用它
let result2 = fCreator 2.0
let result3 = fCreator 3.0
.
.
.
然后整个选择过程再次完成,这在这里不是什么大问题,但我实际的选择函数要复杂得多,需要一些时间来计算
是否可以调用fCreator,获取并保存所选转换,然后直接使用它?差不多
let selectedFunction x:float = fCreator x:float
那在哪里呢
selectedFunction x:float = x * 10
是
我知道上面的方法是行不通的,但我希望你明白我在做什么。selectedFunction应该是从fCreator选择的转换
我对F#很陌生,所以我可能忽略了一些显而易见的东西,但根据F#中的函数缓存,我仔细阅读了几个Q&A。但就我所见,无论是回忆录还是懒散的评估都不能满足我的要求
我还尝试将fCreator编写为一个void函数,其中x作为声明但未初始化的变量,然后返回一个带有该变量的转换。但这并没有完全奏效,而且据我所知,这也不是F#的正确做法
我希望有人能给我一个提示。不要依赖全局值,而是定义一个返回另一个函数的函数:
let selectCreator choice =
match choice with
| 1 -> fun x -> x * x
| 2 -> fun x -> x * 10.0
| 3 -> fun x -> x + 20.0
| _ -> id
> let creator3 = selectCreator 3;;
3 selected
val creator3 : (float -> float)
> creator3 4.0;;
val it : float = 24.0
> creator3 5.0;;
val it : float = 25.0
这是一个返回所需函数的函数。它有签名int->(float->float)
。您可以将其绑定到以下特定选项:
let creator = selectCreator 2
let choice = 2
let fCreator =
match choice with
| 1 -> fun x -> x * x
| 2 -> fun x -> x * 10
| 3 -> fun x -> x + 20
| _ -> x
let mkCreator choice = function
| 1 -> fun x -> x * x
| 2 -> ( *) 10.0
| 3 -> (+) 20.0
| _ -> id
let fCreator = mkCreator 2
fCreator 20.0 (* val it = 200.0 : float *)
现在,您可以对各种值使用creator
:
> creator 2.0;;
val it : float = 20.0
> creator 3.0;;
val it : float = 30.0
仅当您调用selectCreator
时,选择才会发生;每次调用creator
,只需调用返回的函数即可。这可以通过对selectCreator
进行以下修改来说明:
let selectCreator choice =
match choice with
| 1 ->
printf "1 selected"
fun x -> x * x
| 2 ->
printf "2 selected"
fun x -> x * 10.0
| 3 ->
printf "3 selected"
fun x -> x + 20.0
| _ ->
printf "Default selected"
id
虽然在函数式编程中,我们不喜欢副作用,但这是一个很好的方式来证明它是按预期工作的。以下是FSI会话的日志:
> let creator = selectCreator 2;;
2 selected
val creator : (float -> float)
> creator 4.0;;
val it : float = 40.0
> creator 5.0;;
val it : float = 50.0
请注意,它仅在选择creator
时打印选择,而不是在调用它时打印
这种方法还有一个优点,即您在运行时改变主意,并选择不同的函数:
let selectCreator choice =
match choice with
| 1 -> fun x -> x * x
| 2 -> fun x -> x * 10.0
| 3 -> fun x -> x + 20.0
| _ -> id
> let creator3 = selectCreator 3;;
3 selected
val creator3 : (float -> float)
> creator3 4.0;;
val it : float = 24.0
> creator3 5.0;;
val it : float = 25.0
定义一个返回另一个函数的函数,而不是依赖全局值:
let selectCreator choice =
match choice with
| 1 -> fun x -> x * x
| 2 -> fun x -> x * 10.0
| 3 -> fun x -> x + 20.0
| _ -> id
> let creator3 = selectCreator 3;;
3 selected
val creator3 : (float -> float)
> creator3 4.0;;
val it : float = 24.0
> creator3 5.0;;
val it : float = 25.0
这是一个返回所需函数的函数。它有签名int->(float->float)
。您可以将其绑定到以下特定选项:
let creator = selectCreator 2
let choice = 2
let fCreator =
match choice with
| 1 -> fun x -> x * x
| 2 -> fun x -> x * 10
| 3 -> fun x -> x + 20
| _ -> x
let mkCreator choice = function
| 1 -> fun x -> x * x
| 2 -> ( *) 10.0
| 3 -> (+) 20.0
| _ -> id
let fCreator = mkCreator 2
fCreator 20.0 (* val it = 200.0 : float *)
现在,您可以对各种值使用creator
:
> creator 2.0;;
val it : float = 20.0
> creator 3.0;;
val it : float = 30.0
仅当您调用selectCreator
时,选择才会发生;每次调用creator
,只需调用返回的函数即可。这可以通过对selectCreator
进行以下修改来说明:
let selectCreator choice =
match choice with
| 1 ->
printf "1 selected"
fun x -> x * x
| 2 ->
printf "2 selected"
fun x -> x * 10.0
| 3 ->
printf "3 selected"
fun x -> x + 20.0
| _ ->
printf "Default selected"
id
虽然在函数式编程中,我们不喜欢副作用,但这是一个很好的方式来证明它是按预期工作的。以下是FSI会话的日志:
> let creator = selectCreator 2;;
2 selected
val creator : (float -> float)
> creator 4.0;;
val it : float = 40.0
> creator 5.0;;
val it : float = 50.0
请注意,它仅在选择creator
时打印选择,而不是在调用它时打印
这种方法还有一个优点,即您在运行时改变主意,并选择不同的函数:
let selectCreator choice =
match choice with
| 1 -> fun x -> x * x
| 2 -> fun x -> x * 10.0
| 3 -> fun x -> x + 20.0
| _ -> id
> let creator3 = selectCreator 3;;
3 selected
val creator3 : (float -> float)
> creator3 4.0;;
val it : float = 24.0
> creator3 5.0;;
val it : float = 25.0
如果选择计算一次,然后始终相同,则可以执行以下操作:
let creator = selectCreator 2
let choice = 2
let fCreator =
match choice with
| 1 -> fun x -> x * x
| 2 -> fun x -> x * 10
| 3 -> fun x -> x + 20
| _ -> x
let mkCreator choice = function
| 1 -> fun x -> x * x
| 2 -> ( *) 10.0
| 3 -> (+) 20.0
| _ -> id
let fCreator = mkCreator 2
fCreator 20.0 (* val it = 200.0 : float *)
这将返回一个完全不同的函数,具体取决于
选项的值如果选择计算一次,然后始终相同,则可以执行以下操作:
let creator = selectCreator 2
let choice = 2
let fCreator =
match choice with
| 1 -> fun x -> x * x
| 2 -> fun x -> x * 10
| 3 -> fun x -> x + 20
| _ -> x
let mkCreator choice = function
| 1 -> fun x -> x * x
| 2 -> ( *) 10.0
| 3 -> (+) 20.0
| _ -> id
let fCreator = mkCreator 2
fCreator 20.0 (* val it = 200.0 : float *)
这将返回一个完全不同的函数,具体取决于选项的值您的想法是正确的,重用“从另一个函数返回”的函数。您可以这样做:
let creator = selectCreator 2
let choice = 2
let fCreator =
match choice with
| 1 -> fun x -> x * x
| 2 -> fun x -> x * 10
| 3 -> fun x -> x + 20
| _ -> x
let mkCreator choice = function
| 1 -> fun x -> x * x
| 2 -> ( *) 10.0
| 3 -> (+) 20.0
| _ -> id
let fCreator = mkCreator 2
fCreator 20.0 (* val it = 200.0 : float *)
这使得“昂贵的”mkCreator
调用只发生一次
另一个答复建议如下:
let mkCreator choice x = function
| 1 -> x * x
| 2 -> (*) 10.0
| 3 -> (+) 20.0
| _ -> x
let fCreator = mkCreator 2
但是,mkCreator
的主体在拥有所有参数之前不会被计算。这意味着您以后每次应用fCreator
,都将评估mkCreator
的主体。但这正是我们试图避免的 您的想法是正确的,重用“从另一个函数返回”的函数。您可以这样做:
let creator = selectCreator 2
let choice = 2
let fCreator =
match choice with
| 1 -> fun x -> x * x
| 2 -> fun x -> x * 10
| 3 -> fun x -> x + 20
| _ -> x
let mkCreator choice = function
| 1 -> fun x -> x * x
| 2 -> ( *) 10.0
| 3 -> (+) 20.0
| _ -> id
let fCreator = mkCreator 2
fCreator 20.0 (* val it = 200.0 : float *)
这使得“昂贵的”mkCreator
调用只发生一次
另一个答复建议如下:
let mkCreator choice x = function
| 1 -> x * x
| 2 -> (*) 10.0
| 3 -> (+) 20.0
| _ -> x
let fCreator = mkCreator 2
但是,mkCreator
的主体在拥有所有参数之前不会被计算。这意味着您以后每次应用fCreator
,都将评估mkCreator
的主体。但这正是我们试图避免的 非常感谢大家的回复
所以总体思路是在我的选择函数中使用匿名函数作为返回值。在上面的例子中,这是一种非常简单的方法
但问题是(至少对我来说)在我的实际选择函数中,转换是通过大量递归函数调用创建的,这使得将它们定义为匿名函数不是那么容易。创建的转换(如上面的x*x
)实际上是操作序列和递归函数,最好的办法是让它们保持不变
我希望仅通过更改调用选择函数的代码就可以存储所选转换。这样我就可以得到像