F# 什么';它是if-then语句的功能替代品?

F# 什么';它是if-then语句的功能替代品?,f#,functional-programming,F#,Functional Programming,我一直在学习F#和函数式编程,并试图用函数式的方式做事。然而,当涉及到重写一些我已经用C语言编写的代码时,我会被简单的if-then语句(那些只做某事,不返回值的语句)所困扰。我知道你可以在F#完成这件事: 然而,我认为这是一种必要的编码方法?也许我对函数式编程的了解还不够,但对我来说它似乎不实用。我认为函数式方法是组合函数和表达式,而不是简单地一个接一个地执行语句,这似乎鼓励了if 那么,我是否遗漏了一些东西,如果在功能世界中,它是完美的呢?如果不是,这类语句的功能等价物是什么?我怎样才能接受

我一直在学习F#和函数式编程,并试图用函数式的方式做事。然而,当涉及到重写一些我已经用C语言编写的代码时,我会被简单的if-then语句(那些只做某事,不返回值的语句)所困扰。我知道你可以在F#完成这件事:

然而,我认为这是一种必要的编码方法?也许我对函数式编程的了解还不够,但对我来说它似乎不实用。我认为函数式方法是组合函数和表达式,而不是简单地一个接一个地执行语句,这似乎鼓励了if

那么,我是否遗漏了一些东西,如果在功能世界中,它是完美的呢?如果不是,这类语句的功能等价物是什么?我怎样才能接受一个if,然后将其功能化呢

编辑:我可能问了一个错误的问题(抱歉,对函数编程来说还是相当新的):让我们举一个真实的例子,让我甚至问:

if not <| System.String.IsNullOrWhiteSpace(data) then do
    let byteData = System.Text.Encoding.Unicode.GetBytes(data)
    req.ContentLength <- int64 byteData.Length
    let postStream : System.IO.Stream = req.GetRequestStream()
    postStream.Write(byteData, 0, byteData.Length)
    postStream.Flush()
    postStream.Dispose()

if-not在函数世界中,if-then没有什么问题

您的示例实际上类似于
let=expr
,因为
expr
有副作用,我们忽略其返回值。一个更有趣的例子是:

if cond then expr
这相当于:

match cond with
| true -> expr
| false -> ()
如果我们使用模式匹配

当条件很简单或只有一个条件表达式时,if-then比模式匹配更具可读性。此外,值得注意的是,函数式编程中的一切都是表达式。所以
if cond then expr
实际上是
if cond then expr else()
的快捷方式

如果then本身不是强制性的,那么使用If then作为陈述是一种强制性的思维方式。根据我的经验,函数式编程更多的是关于思维方式,而不是编程语言中的具体控制流

编辑:

您的代码完全可读。一些次要问题是去除冗余的
do
关键字、类型注释和
postStream.Dispose()
(通过使用
use
关键字):


if not命令不是if表达式,而是if表达式中的内容。例如,
let abs num=if num<0然后-num else num
是编写abs函数的一种完全实用的方法。它接受一个参数并返回该参数的转换,没有任何副作用。但是当你有“只做某件事而不返回值的代码”时,你就在写一些不完全是功能性的东西。函数式编程的目标是最小化程序中可以这样描述的部分。如何编写条件语句是相切的。

为了编写复杂的代码,您需要在某个点进行分支。实现这一点的方法非常有限,所有这些方法都需要通过一段代码的逻辑流。如果您想避免使用If/then/else,则可以使用loop/while/repeat进行欺骗,但这将使您的代码在维护和读取时变得不合理

函数式编程并不意味着你不应该一个接一个地执行语句——它只是意味着你不应该有一个可变的状态。每个函数在每次调用时都需要以相同的方式可靠地运行。数据处理方式的任何差异都需要由传入的数据来解释,而不是对调用函数的任何对象隐藏的触发器


例如,如果我们有一个函数
foo(int,bool)
,它根据
bool
是真是假返回不同的结果,那么
foo()
中几乎肯定会有一个
if
语句。这是完全合法的。不合法的是使用一个函数
foo(int)
,该函数根据是否是第一次在程序中调用而返回不同的内容。这是一个“有状态”函数,它使任何人都难以维护程序。

如果您的
if
语句具有返回值且没有副作用,则该函数被视为功能性函数

假设您想编写以下等效内容:

如果(x>3)n=3;否则n=x

使用if命令中的return语句,而不是执行此操作:

设n=(如果x>3,则为3,否则为x)


假设的
如果
突然起作用,因为它没有副作用;它只返回一个值。把它想象成某些语言中的三元运算符:
intn=x>3?3:x

到目前为止还没有提到的一个重要问题是,
if。。然后。。else
如果。。然后
而不使用
else
分支

函数式语言中的
If
if
的功能解释是,它是一个计算结果为某个值的表达式。要计算
if c然后e1 else e2
的值,请计算条件
c
,然后根据条件计算
e1
e2
。这将为您提供
if。。然后。。else

如果您只有
如果c然后e
,那么如果
c
false
,您就不知道评估的结果应该是什么,因为没有
其他
分支!以下内容显然毫无意义:

let num = if input > 0 then 10
在F#中,具有副作用的表达式,如
printf“hi”
返回类型为
unit
的特殊值。该类型只有一个值(写为
()
),因此您可以编写
if
,它只在一种情况下起作用:

let u = if input > 0 then printf "hi" else ()
它的计算结果总是
unit
,但在
true
分支中,它也会产生副作用。在
false
分支中,它只返回一个
unit
值。在F#中,你不需要
let num = if input > 0 then 10
let u = if input > 0 then printf "hi" else ()
let u = if input > 0 then printfn "hi"
maybeData |> Option.iter (fun data ->
    let byteData = System.Text.Encoding.Unicode.GetBytes(data)  
    req.ContentLength <- int64 byteData.Length  
    use postStream = req.GetRequestStream()  
    postStream.Write(byteData, 0, byteData.Length) )
function $if(param) {
    return new Condition(param)
}

function Condition(IF, THEN, ELSE) {
    this.call = function(seq) {
        if(this.lastCond != undefined) 
            return this.lastCond.call(
                sequence(
                    this.if, 
                    this.then, 
                    this.else, 
                    (this.elsif ? this.elsif.if : undefined),
                    seq || undefined
                )
            );
         else 
            return sequence(
                this.if, 
                this.then, 
                this.else, 
                (this.elsif ? this.elsif.if : undefined),
                seq || undefined
            )
    }


    this.if   = IF ? IF : f => { this.if = f; return this };
    this.then = THEN ? THEN : f => { this.then = f; return this };
    this.else = ELSE ? ELSE : f => { this.else = f; return this };
    this.elsif = f => {this.elsif = $if(f); this.elsif.lastCond = this; return this.elsif};
}

function sequence(IF, THEN, ELSE, ELSIF, FINALLY) {
    return function(val) {
        if( IF(val) ) 
            return THEN();

        else if( ELSIF && ELSIF(val) ) 
            return FINALLY(val);

        else if( ELSE ) 
            return ELSE();

        else 
            return undefined

    }
}}
var eq = val => x => x == val ? true : false;

$if( eq(128) ).then( doStuff ).else( doStuff )
.elsif( eq(255) ).then( doStuff ).else( doStuff ).call();
sequence(f, f, f, f,
    sequence(f, f, f, f
        sequence(f, f, f)
    )
);