我试着通过研究去年的AdventOfCode解决方案来学习一些F#.我遇到了这个简洁的代码,我根本无法解析:
i 1|>Seq.sumBy(" (".IndexOf)
Run Code Online (Sandbox Code Playgroud)
注意,我相信我理解前一行(在链接中):
let i n=System.IO.File.ReadAllText(sprintf "%s/input/input%d.txt"__SOURCE_DIRECTORY__ n)
Run Code Online (Sandbox Code Playgroud)
这创建了一个函数i,它接受integer n并读取文件inputN.txt并将其作为字符串返回.因此i 1返回input1.txt为字符串.
然后|>将字符串(或字符数组?)作为第一个参数传递给下一个函数,即Seq.sumBy
但事情开始崩溃......
sumBy似乎很直接:
返回通过将函数应用于列表的每个元素而生成的结果的总和.
但是IndexOf字符串" ("让我感到困惑.
现在,我真的不想要任何鱼类,我想知道的是这个.作为这门外语的新手,当我学习更多的F#工作时,我怎么能把这段代码分解成更小的部分来测试它以弄清楚发生了什么?它让我疯狂,我有解决方案,谷歌/所以,我仍然无法理解这段代码.
有人可以给我看一些较小的片段,这样我自己就能找到答案吗?
所以,我们可以将其分解成碎片.
i 1|>Seq.sumBy(" (".IndexOf)
Run Code Online (Sandbox Code Playgroud)
你对这个i 1部分是正确的.这将阅读input1.txt,并给你整个文本作为string.
所以,这里的第一个关键是String implementsIEnumerable<char>(char seq),这意味着它可以被枚举.
接下来,让我们看一下parens里面的部分:
" (".IndexOf
Run Code Online (Sandbox Code Playgroud)
第一部分只是一个字符串:" (",IndexOf是一个字符串的方法.它返回特定字符的从零开始的索引,如果不存在,则返回-1.
因为它是一种方法,你可以将它用作函数 - 所以" (".IndexOf可以被认为是:
(fun someChar ->
let str = " ("
str.IndexOf(someChar))
Run Code Online (Sandbox Code Playgroud)
---------在此停止,除非你想详细解释完整答案--------
在这种情况下,如果输入字符是' ',它将返回0,如果是'(',它将返回1,如果是其他任何东西,它将返回-1.
该Seq.sumBy取输入字符串和管道它的每个字符到该功能,然后由结果总结.这意味着每个输入'('将添加1,每个输入' '将添加0,并且其他任何内容将添加-1(在这种情况下,这是')'字符.像这样的字符串"()"将添加1,然后添加-1,结果为0,这与第一天的目标来临挑战.
FSI是你的朋友.我经常用它来理解如何分解函数.如果将表达式粘贴" (".IndexOf到FSI中,乍一看它看起来不会有帮助:
> " (".IndexOf;;
" (".IndexOf;;
^^^^^^^^^^^^
stdin(12,1): error FS0041: A unique overload for method 'IndexOf' could not be determined based on type information prior to this program point. A type annotation may be needed. Candidates: System.String.IndexOf(value: char) : int, System.String.IndexOf(value: string) : int
Run Code Online (Sandbox Code Playgroud)
正如你已经想到的那样," ("是一个字符串,并且IndexOf是一个方法string.实际上,该方法存在相当多的重载,但只有两个具有arity 1.
其中一个重载采用char输入,另一个采用string输入.
表达式" (".IndexOf如果是一个函数.这是简短的形式fun x -> " (".IndexOf x.
您还已经识别出string实现char seq,因此当您Seq在其上使用模块时,您正在查看序列的每个元素.在这种情况下,每个元素都是a char,因此这里使用的重载必须是以char作为输入的重载.
现在您已经确定了正在使用的重载,您可以开始在FSI中进行实验:
> " (".IndexOf '(';;
val it : int = 1
> " (".IndexOf 'f';;
val it : int = -1
> " (".IndexOf 'o';;
val it : int = -1
> " (".IndexOf ' ';;
val it : int = 0
Run Code Online (Sandbox Code Playgroud)
显然,该函数查找每一个输入的索引char中" (",所以每次你在打发时间'('你1(因为它是零索引),而当输入' ',返回值是0.对于所有其他值,返回值为-1.
输入字符串"(foo bar)"也是一个char seq.sumBy您可以尝试将其管道化,而不是执行a ,Seq.map以便了解每个元素的翻译方式:
> "(foo bar)" |> Seq.map (" (".IndexOf) |> Seq.toList;;
val it : int list = [1; -1; -1; -1; 0; -1; -1; -1; -1]
Run Code Online (Sandbox Code Playgroud)
现在,Seq.map只翻译,但Seq.sumBy获取所有这些数字并将它们加在一起:
> "(foo bar)" |> Seq.sumBy (" (".IndexOf);;
val it : int = -6
Run Code Online (Sandbox Code Playgroud)
我仍然无法猜出目的是什么,但是,我从未见过输入字符串......
| 归档时间: |
|
| 查看次数: |
188 次 |
| 最近记录: |