`fun` lambda 表达式有 shorthand 语法吗?
do `fun` lambda expressions have shorthand syntax?
我想确保我没有错过可读但简洁的 F# 语法:我对下面的 fun
的使用是否过于冗长?
let toCamelCase word indexes =
let mapping i c =
match (indexes |> List.contains i) with
| true -> Char.ToUpper(c)
| _ when Char.IsUpper(c) -> Char.ToLower(c)
| _ -> c
word |> String.mapi mapping
[
("fsharP", [0; 1])
("nAtiveinterop", [0; 6])
("taskbuildereXtensions", [0; 4; 11])
("microsoftword", [0; 9])
]
|> List.map (fun (word, indexes) -> (word, indexes) ||> toCamelCase)
另外,请让我知道上面代码的其他地方是否可以改进
在一些函数式语言中,uncurry
函数很常见:
let uncurry f (a,b) = f a b
那你可以写成|> List.map (uncurry toCamelCase)
。
或者,您可以将现有内容稍微简化为:
|> List.map (fun pair -> pair ||> toCamelCase)
您可以在不显式声明 lambda 的情况下使用柯里化来应用函数:
let inline flip f x y = f y x
...
List.map (flip (||>) toCamelCase)
或更改 toCamelCase
或输入列表中参数的顺序,这样您就不需要定义 flip
:
List.map ((||>) toCamelCase)
但我认为最好的选择是避免 ||>
:
List.map (fun (word, indexes) -> toCamelCase word indexes)
想添加一个不太关注 currying/uncurrying 的答案。这涉及到其他人已经在这里提出的一些要点,但希望更多细节会有所帮助。
关于你的问题,如果你想传入一个lambda function,你需要fun
关键字。您可以通过更改函数签名来避免这种情况:
let toCamelCase (word, indexes) =
let mapping i c =
match (indexes |> List.contains i) with
| true -> Char.ToUpper(c)
| _ when Char.IsUpper(c) -> Char.ToLower(c)
| _ -> c
word |> String.mapi mapping
[
("fsharP", [0; 1])
("nAtiveinterop", [0; 6])
("taskbuildereXtensions", [0; 4; 11])
("microsoftword", [0; 9])
]
|> List.map toCamelCase
如果您正在使用一个函数,无论出于何种原因您都无法进行此更改,您可以创建一个中间辅助函数(这实际上是手动取消柯里化):
let toCamelCase word indexes =
let mapping i c =
match (indexes |> List.contains i) with
| true -> Char.ToUpper(c)
| _ when Char.IsUpper(c) -> Char.ToLower(c)
| _ -> c
word |> String.mapi mapping
let toCCHelper (word, indexes) =
toCamelCase word indexes
[
("fsharP", [0; 1])
("nAtiveinterop", [0; 6])
("taskbuildereXtensions", [0; 4; 11])
("microsoftword", [0; 9])
]
|> List.map toCCHelper
您可以选择稍微简化您的 lambda 函数,不做任何更改。这是有效的,因为双管道 (||>) 将为您解构元组输入:
let toCamelCase word indexes =
let mapping i c =
match (indexes |> List.contains i) with
| true -> Char.ToUpper(c)
| _ when Char.IsUpper(c) -> Char.ToLower(c)
| _ -> c
word |> String.mapi mapping
[
("fsharP", [0; 1])
("nAtiveinterop", [0; 6])
("taskbuildereXtensions", [0; 4; 11])
("microsoftword", [0; 9])
]
|> List.map (fun x -> x ||> toCamelCase)
还有一些不需要的括号,就看你的喜好了。这里有一些清理以及一些逻辑更改供您考虑:
let toCamelCase (word, indexes) =
let mapping i c =
// You can omit parens here if you want:
match indexes |> List.contains i with
// This logic might be easier to maintain, no parens needed here:
| true -> Char.ToUpper c
| false -> Char.ToLower c
word |> String.mapi mapping
// The parens here are also optional when you're putting 1 entry per line
// (1 tuple being 1 entry in this case):
[
"fsharP", [0; 1]
"nAtiveinterop", [0; 6]
"taskbuildereXtensions", [0; 4; 11]
"microsoftword", [0; 9]
]
|> List.map toCamelCase
这是我想出的版本。我更喜欢 xs4
并且只做内联的所有事情,根本没有 map
。如果函数名很长,可能是 xs5
.
最重要的是,为了便于阅读,我会添加空格以创建表格视图。但这可能是一个关心可读性的老 Perl 程序员的老习惯,并且在任何其他语言中都没有广泛使用。也许所有其他语言都认为它们已经可读了?
(* Original *)
let xs1 =
[
"fsharP" , [0; 1]
"nAtiveinterop" , [0; 6]
"taskbuildereXtensions", [0; 4; 11]
"microsoftword" , [0; 9]
]
|> List.map (fun (word, indexes) -> (word, indexes) ||> toCamelCase)
(* Remove useless piping *)
let xs2 =
[
"fsharP" , [0; 1]
"nAtiveinterop" , [0; 6]
"taskbuildereXtensions", [0; 4; 11]
"microsoftword" , [0; 9]
]
|> List.map (fun (word, indexes) -> toCamelCase word indexes)
(* If you use piping, then like this *)
let xs3 =
[
"fsharP" , [0; 1]
"nAtiveinterop" , [0; 6]
"taskbuildereXtensions", [0; 4; 11]
"microsoftword" , [0; 9]
]
|> List.map (fun wi -> wi ||> toCamelCase)
(* toCamelCase part of list *)
let xs4 = [
toCamelCase "fsharP" [0; 1]
toCamelCase "nAtiveinterop" [0; 6]
toCamelCase "taskbuildereXtensions" [0; 4; 11]
toCamelCase "microsoftword" [0; 9]
]
(* you can create a shortcut for the function *)
let xs5 =
let f = toCamelCase
[
f "fsharP" [0; 1]
f "nAtiveinterop" [0; 6]
f "taskbuildereXtensions" [0; 4; 11]
f "microsoftword" [0; 9]
]
(* Use map2 *)
let xs6 =
List.map2
toCamelCase
["fsharP";"nAtiveinterop";"taskbuildereXtensions";"microsoftword"]
[[0;1]; [0;6]; [0;4;11]; [0;9]]
(* still map2, but extracted arguments *)
let xs7 =
let args1 = ["fsharP";"nAtiveinterop";"taskbuildereXtensions";"microsoftword"]
let args2 = [[0;1]; [0;6]; [0;4;11]; [0;9]]
List.map2 toCamelCase args1 args2
我想确保我没有错过可读但简洁的 F# 语法:我对下面的 fun
的使用是否过于冗长?
let toCamelCase word indexes =
let mapping i c =
match (indexes |> List.contains i) with
| true -> Char.ToUpper(c)
| _ when Char.IsUpper(c) -> Char.ToLower(c)
| _ -> c
word |> String.mapi mapping
[
("fsharP", [0; 1])
("nAtiveinterop", [0; 6])
("taskbuildereXtensions", [0; 4; 11])
("microsoftword", [0; 9])
]
|> List.map (fun (word, indexes) -> (word, indexes) ||> toCamelCase)
另外,请让我知道上面代码的其他地方是否可以改进
在一些函数式语言中,uncurry
函数很常见:
let uncurry f (a,b) = f a b
那你可以写成|> List.map (uncurry toCamelCase)
。
或者,您可以将现有内容稍微简化为:
|> List.map (fun pair -> pair ||> toCamelCase)
您可以在不显式声明 lambda 的情况下使用柯里化来应用函数:
let inline flip f x y = f y x
...
List.map (flip (||>) toCamelCase)
或更改 toCamelCase
或输入列表中参数的顺序,这样您就不需要定义 flip
:
List.map ((||>) toCamelCase)
但我认为最好的选择是避免 ||>
:
List.map (fun (word, indexes) -> toCamelCase word indexes)
想添加一个不太关注 currying/uncurrying 的答案。这涉及到其他人已经在这里提出的一些要点,但希望更多细节会有所帮助。
关于你的问题,如果你想传入一个lambda function,你需要fun
关键字。您可以通过更改函数签名来避免这种情况:
let toCamelCase (word, indexes) =
let mapping i c =
match (indexes |> List.contains i) with
| true -> Char.ToUpper(c)
| _ when Char.IsUpper(c) -> Char.ToLower(c)
| _ -> c
word |> String.mapi mapping
[
("fsharP", [0; 1])
("nAtiveinterop", [0; 6])
("taskbuildereXtensions", [0; 4; 11])
("microsoftword", [0; 9])
]
|> List.map toCamelCase
如果您正在使用一个函数,无论出于何种原因您都无法进行此更改,您可以创建一个中间辅助函数(这实际上是手动取消柯里化):
let toCamelCase word indexes =
let mapping i c =
match (indexes |> List.contains i) with
| true -> Char.ToUpper(c)
| _ when Char.IsUpper(c) -> Char.ToLower(c)
| _ -> c
word |> String.mapi mapping
let toCCHelper (word, indexes) =
toCamelCase word indexes
[
("fsharP", [0; 1])
("nAtiveinterop", [0; 6])
("taskbuildereXtensions", [0; 4; 11])
("microsoftword", [0; 9])
]
|> List.map toCCHelper
您可以选择稍微简化您的 lambda 函数,不做任何更改。这是有效的,因为双管道 (||>) 将为您解构元组输入:
let toCamelCase word indexes =
let mapping i c =
match (indexes |> List.contains i) with
| true -> Char.ToUpper(c)
| _ when Char.IsUpper(c) -> Char.ToLower(c)
| _ -> c
word |> String.mapi mapping
[
("fsharP", [0; 1])
("nAtiveinterop", [0; 6])
("taskbuildereXtensions", [0; 4; 11])
("microsoftword", [0; 9])
]
|> List.map (fun x -> x ||> toCamelCase)
还有一些不需要的括号,就看你的喜好了。这里有一些清理以及一些逻辑更改供您考虑:
let toCamelCase (word, indexes) =
let mapping i c =
// You can omit parens here if you want:
match indexes |> List.contains i with
// This logic might be easier to maintain, no parens needed here:
| true -> Char.ToUpper c
| false -> Char.ToLower c
word |> String.mapi mapping
// The parens here are also optional when you're putting 1 entry per line
// (1 tuple being 1 entry in this case):
[
"fsharP", [0; 1]
"nAtiveinterop", [0; 6]
"taskbuildereXtensions", [0; 4; 11]
"microsoftword", [0; 9]
]
|> List.map toCamelCase
这是我想出的版本。我更喜欢 xs4
并且只做内联的所有事情,根本没有 map
。如果函数名很长,可能是 xs5
.
最重要的是,为了便于阅读,我会添加空格以创建表格视图。但这可能是一个关心可读性的老 Perl 程序员的老习惯,并且在任何其他语言中都没有广泛使用。也许所有其他语言都认为它们已经可读了?
(* Original *)
let xs1 =
[
"fsharP" , [0; 1]
"nAtiveinterop" , [0; 6]
"taskbuildereXtensions", [0; 4; 11]
"microsoftword" , [0; 9]
]
|> List.map (fun (word, indexes) -> (word, indexes) ||> toCamelCase)
(* Remove useless piping *)
let xs2 =
[
"fsharP" , [0; 1]
"nAtiveinterop" , [0; 6]
"taskbuildereXtensions", [0; 4; 11]
"microsoftword" , [0; 9]
]
|> List.map (fun (word, indexes) -> toCamelCase word indexes)
(* If you use piping, then like this *)
let xs3 =
[
"fsharP" , [0; 1]
"nAtiveinterop" , [0; 6]
"taskbuildereXtensions", [0; 4; 11]
"microsoftword" , [0; 9]
]
|> List.map (fun wi -> wi ||> toCamelCase)
(* toCamelCase part of list *)
let xs4 = [
toCamelCase "fsharP" [0; 1]
toCamelCase "nAtiveinterop" [0; 6]
toCamelCase "taskbuildereXtensions" [0; 4; 11]
toCamelCase "microsoftword" [0; 9]
]
(* you can create a shortcut for the function *)
let xs5 =
let f = toCamelCase
[
f "fsharP" [0; 1]
f "nAtiveinterop" [0; 6]
f "taskbuildereXtensions" [0; 4; 11]
f "microsoftword" [0; 9]
]
(* Use map2 *)
let xs6 =
List.map2
toCamelCase
["fsharP";"nAtiveinterop";"taskbuildereXtensions";"microsoftword"]
[[0;1]; [0;6]; [0;4;11]; [0;9]]
(* still map2, but extracted arguments *)
let xs7 =
let args1 = ["fsharP";"nAtiveinterop";"taskbuildereXtensions";"microsoftword"]
let args2 = [[0;1]; [0;6]; [0;4;11]; [0;9]]
List.map2 toCamelCase args1 args2