我已经开始介绍F#的课程,我在两个作业中遇到了一些麻烦。第一个让我创建两个函数,其中第一个函数接受输入并将其添加四个,第二个函数计算sqrt(x ^ 2 + y ^ 2)。然后我应该为它们写两个函数表达式,但由于某种原因它给了我错误"意外的符号' |'在实施文件"。
let g = fun n -> n + 4;;
let h = fun (x,y) -> System.Math.Sqrt((x*x)+(y*y));;
let f = fun (x,n) -> float
|(n,0) -> g(n)
|(x,n) -> h(x,n);;
第二个作业要求我创建一个函数,它找到Fibonaccis数的序列。我已经编写了下面的代码,但它似乎忘记了开头的0,因为输出总是n + 1而不是n。
let rec fib = function
|0 -> 0
|1 -> 1
|n -> fib(n-1) + fib(n-2)
;;
请记住,这是第一周,因此我应该能够使用这些方法创建这些方法。
答案 0 :(得分:5)
您的第一个代码段主要有两个问题:
在F#中,float
和int
之间存在差异。您将整数值写为4
或0
,并将浮点值写为4.0
或0.0
。 F#不会自动将整数转换为浮点数,因此您需要保持一致。
f
函数中的语法有点奇怪 - 我不确定float
应该代表什么,fun
和{{1构造行为不同。
所以,从原始代码开始:
function
这样可行,但我不会使用let g = fun n -> n + 4;;
将其写为显式函数 - 您也可以使用fun
来定义函数,并且它更简单。此外,您只需要在F#Interactive中使用let
,但如果您使用任何合适的编辑器来命令将代码发送到F#interactive(通过Alt + Enter),则不需要。
但是,在;;
函数中,您希望返回f
,因此您需要修改float
以返回浮点数。这意味着将g
替换为4
:
4.0
let g n = n + 4.0
功能很好,但您可以使用h
再次编写它:
let
在let h (x,y) = System.Math.Sqrt((x*x)+(y*y));;
函数中,您可以使用f
使用模式匹配编写函数,也可以使用function
使用更详细的语法(match
只是写入函数的简写,然后在输入上进行模式匹配):
function
另请注意,缩进很重要 - 在let f = function
| (n,0.0) -> g(n)
| (x,n) -> h(x,n)
let f (x, y) =
match (x, y) with
| (n,0.0) -> g(n)
| (x,n) -> h(x,n)
之前需要空格。
答案 1 :(得分:3)
我将解决你的第一个代码块,并保留Fibonacci函数以供日后使用。首先我会重新发布你的代码,然后我会谈论它。
let g = fun n -> n + 4;;
let h = fun (x,y) -> System.Math.Sqrt((x*x)+(y*y));;
let f = fun (x,n) -> float
|(n,0) -> g(n)
|(x,n) -> h(x,n);;
第一条评论:如果您要定义一个函数并立即将其分配给名称,就像在所有这些示例中一样,您不需要fun
关键字。定义函数的常用方法是将它们写为let (name) (parameters) = (function body)
。所以上面的代码将成为:
let g n = n + 4;;
let h (x,y) = System.Math.Sqrt((x*x)+(y*y));;
let f (x,n) = float
|(n,0) -> g(n)
|(x,n) -> h(x,n);;
我没有进行任何其他更改,因此您的f
函数仍然存在错误。让我们接下来解决这个错误。
我认为你在这里犯的错误是认为fun
和function
是可以互换的。他们不是。 fun
是标准函数定义,但function
是其他内容。在F#中编写如下函数是非常常见的模式:
let someFunc parameter =
match parameter with
| "case 1" -> printfn "Do something"
| "case 2" -> printfn "Do something else"
| _ -> printfn "Default behavior"
function
关键字是一个参数加上匹配表达式的简写。换句话说,这个:
let someFunc = function
| "case 1" -> printfn "Do something"
| "case 2" -> printfn "Do something else"
| _ -> printfn "Default behavior"
与此完全相同:
let someFunc parameter =
match parameter with
| "case 1" -> printfn "Do something"
| "case 2" -> printfn "Do something else"
| _ -> printfn "Default behavior"
只有一个区别。在具有function
关键字的版本中,您无法选择参数的名称。它由F#编译器自动创建,由于您无法事先知道参数的名称是什么,因此您无法在代码中引用它。 (好吧,有办法,但我不想让你学会在学会走路之前跑步,可以这么说)。还有一件事:当你还在学习F#时,我强烈建议你不要使用function
关键字。一旦你知道自己在做什么,它就非常有用,但在你早期的学习阶段,你应该使用更明确的match (parameter) with
表达式。这样你就会习惯看到它在做什么。一旦你做了几个月的F#,你就可以开始用较短的let f param = match param with (...)
替换那些let f = function (...)
表达式。但是在match param with (...)
真正沉入并且你已经理解它之前,你应该继续明确地输入它。
所以你的f
函数看起来应该是这样的:
let f (x,n) =
match (x,n) with
|(n,0) -> g(n)
|(x,n) -> h(x,n);;
我看到,当我输入此内容时,Tomas Petricek发布了一个回复,它解决了float
的错误用法,所以我不会复制他为什么会出现错误的解释float
函数中的单词f
。他还解释了;;
,所以我也不会重复。我只想说,当他提到“任何体面的编辑器命令将代码发送到F#interactive(通过Alt + Enter)”时,有很多编辑器选择 - 但作为初学者,你可能只是想让某人推荐一个给你,所以我会推荐一个。首先,如果你在Windows上,你可能已经在使用Visual Studio,在这种情况下你应该坚持使用Visual Studio,因为你知道它。这是F#的好编辑。但是如果你还没有使用Visual Studio,我不建议下载它只是为了玩F#。它是一个程序的野兽,专为专业软件开发人员设计,可以完成他们在工作中需要做的各种事情,所以如果你刚刚开始,它会感觉有点压倒性。所以我实际上会推荐一些更轻量级的东西:编辑器叫做Visual Studio Code。它是跨平台的,在Linux,OS X或Windows上运行良好。下载并安装VS Code后,您将需要安装Ionide扩展。 Ionide是VS Code的插件(也是Atom的插件,虽然因为所有Ionide开发人员现在都使用VS Code,因此Ionode的Atom版本更新频率较低),这使得F#编辑成为一种真正的乐趣。实际上你会发现三种扩展:Ionide-fsharp,Ionide-FAKE和Ionide-Paket。下载并安装所有这三个:FAKE和Paket是F#编程的两个工具,你可能还不需要,但是一旦你需要它们,你就已经安装了它们。
好吧,我认为这足以让你开始。