我一直在学习F#,我正在编写一个工具.除非我需要处理无效输入或异常情况,否则一切正常.
在F#中处理此问题的推荐方法是什么?我的函数的构造和使用方式我不知道如何发回一条消息,告诉调用函数由于输入错误而导致调用失败以及类似于C#的循环继续需要发生.
我因为失去了回归而受苦.我可以从F#函数返回其中的任何位置,还是必须在最后一行?
这是我的一些代码示例,其中输入在某些情况下基本上是空的,我正在检测它.我需要阻止运行过程中的步骤.
let SchemaQueryString s =
let sqsValid s =
let Strcat (x : string) (y : string) = x + ", " + y;
let RecFieldName (x : MeasurementRecord) = x.FieldName;
let mapr = List.map RecFieldName s.MeasurementTypes;
let cores = List.reduce Strcat mapr;
"SELECT ProductionCode, TestTime, " + cores + " FROM " + s.TemplateName + " ORDER BY ProductionCode, TestTime";
match s.MeasurementTypes.Length with
| 0 -> ""
| _ -> sqsValid s;
let TemplateMigration tcs rr =
let sql = SchemaQueryString tcs;
let sqlc = new SqlCommand(sql, QCOld);
let sqldr = sqlc.ExecuteReader();
ignore (sqldr.Read());
...
Run Code Online (Sandbox Code Playgroud)
我需要中止TemplateMigration函数并立即返回sql变量与""的匹配.或构造某种类型的联合类型,表明不能构造sql查询字符串,因为对于特定情况,它无法完成.
谢谢你的帮助.我正逐渐搞清楚这种语言,我非常喜欢它,但我正在努力解决它的某些方面,我不知道如何取代关于如何用功能性思想做一些事情的程序性想法.
当第一次使用函数式语言时,很多人都认为一切都是表达式.这意味着使用控制流表达式执行控制流.
那么语句和表达式之间的区别是什么?
语句没有价值,即它不是类型的实例.表达式具有一个值(即使该值是特殊类型unit,它具有一个()不表示任何值的实例.)
在过程语言中,我们使用语句来控制执行流程,因此:
class Program
{
static void Main(string[] args)
{
string str;
if (DateTime.Now.DayOfWeek == DayOfWeek.Monday)
return;
else if (args.Length >= 2)
str = args[1];
else
str = "Hello";
Console.WriteLine(str);
}
}
Run Code Online (Sandbox Code Playgroud)
在这里,我们定义一个变量str类型string有一个值null.然后我们要么忽略它,return如果它是星期一,请分配,args[1]如果可用或"Hello"以其他方式打印它.
当控制流语句长达几行时,这种编程是相当安全的.但是,一旦语句变得大于页面长度,或者复杂和嵌套,我们就更有可能引入错误,通常是十亿美元的错误.
纯函数式语言使用控制流表达式.这意味着if表达式具有值!让我们在前面的代码示例中慢慢实现控件.首先让我们解决分配字符串的问题str.
let str =
if args.Length >= 2 then
args.[1]
else
"Hello"
Run Code Online (Sandbox Code Playgroud)
在这里,我们看到我们直接绑定if表达式的值str.所述的两个分支(子表达式)if表达必须评估为类型的实例string.我们简直不能忘记为字符串赋值,因为编译器会在我们尝试时抛出错误.
但是,在我们希望在控制流程的不同分支中执行不同类型的事情时,似乎存在许多情况.在我们的例子中,如果它是星期一,我们不想做任何事情.这就是受歧视的工会的力量发挥作用的地方.这些允许我们将异构类型组合成一个整体,保留基于表达式的语言的强大功能,以便在每个级别对我们的代码进行类型检查.
在我们的例子中,我们不需要创建新的联合类型,因为该option类型已经包含此功能.因此,我们重写:
open System
[<EntryPoint>]
let Main args =
let str =
if DateTime.Now.DayOfWeek = DayOfWeek.Monday then
None
elif args.Length >= 2 then
Some(args.[1])
else
Some("Hello")
match str with
| Some(str) -> Console.WriteLine(str)
| None -> ()
Environment.ExitCode
Run Code Online (Sandbox Code Playgroud)
现在我们从if表达式返回的值是string option(或Option<string>在C#中),然后我们使用模式匹配来安全地处理控制流的所有可能结果.
当您返回unit值时,TemplateMigration可以简单地从if表达式的两个分支返回相同的值,因此:
let TemplateMigration tcs rr =
let sql = SchemaQueryString tcs
if sql = null || sql.Length = 0 then
()
else
let sqlc = new SqlCommand(sql, QCOld)
let sqldr = sqlc.ExecuteReader()
ignore (sqldr.Read())
Run Code Online (Sandbox Code Playgroud)
但是从它返回一个option值可能会更好SchemaQueryString
let SchemaQueryString s =
... // Elided
match s.MeasurementTypes.Length with
| 0 -> None
| _ -> Some(sqsValid s)
Run Code Online (Sandbox Code Playgroud)
在整个代码中"传播"强类型值.