if-then 语句的功能替代是什么? [英] What's a functional replacement for if-then statements?

查看:21
本文介绍了if-then 语句的功能替代是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在学习 F# 和函数式编程,并尝试以函数式的方式做事.然而,当谈到重写一些我已经用 C# 编写的代码时,我陷入了简单的 if-then 语句(那些只做某事,不返回值的语句).我知道你可以在 F# 中做到这一点:

I've been learning F# and functional programming and trying to do things the functional way. However, when it comes to rewriting some code I'd already written in C# I get stuck at simple if-then statements (ones that only do something, not return a value). I know you can pull this off in F#:

if expr then do ()

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

However, I thought this was an imperative approach to coding? Maybe I've not learned enough about functional programming, but it doesn't seem functional to me. I thought the functional approach was to compose functions and expressions, not simply execute statements one after the other which is what if-then seems to encourage.

那么,我是否遗漏了一些东西,如果-那么在功能世界中完全没问题?如果不是,那么这种语句的功能等价物是什么?我如何才能使用 if-then 并使其发挥作用?

So, am I missing something and if-then is perfectly fine in the functional world? If not, what is the functional equivalent of such a statement? How could I take an if-then and turn it functional?

我可能问错了问题(抱歉,对函数式编程还是很陌生):让我们举一个让我什至问这个问题的真实例子:

I might've asked the wrong question (sorry, still fairly new to functional programming): Let's take a real world example that made me even ask this:

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-then 的主体不返回任何内容,但我不知道如何使其更具功能性(如果可能的话).我不知道最小化命令式代码的正确技术.鉴于 F# 的性质,直接传输我的 C# 相当容易,但我很难将其转换为功能性.每次我在 C# 中遇到这样的 if 语句,并且我试图将它传输到 F# 时,我都感到气馁,因为我想不出一种方法来使代码更具功能性.

The body of that if-then doesn't return anything, but I don't know how I could make this more functional (if that's even possible). I don't know the proper technique for minimizing imperative code. Given F#'s nature it's fairly easy to just transport my C# directly, but I'm having difficulties turning it functional. Every time I reach such an if statement in C#, and I'm trying to transport it to F#, I get discouraged that I can't think of a way to make the code more functional.

推荐答案

一个目前没有提到的重点是 if .. then .. else 之间的区别if .. then 没有 else 分支.

An important point that hasn't been mentioned so far is the difference between if .. then .. else and if .. then without the else branch.

if 的功能解释是它是一个计算结果为某个值的表达式.要评估 if c then e1 else e2 的值,您需要评估条件 c 然后评估 e1e2>,视情况而定.这给你 if .. then .. else.

The functional interpretation of if is that it is an expression that evaluates to some value. To evaluate the value of if c then e1 else e2 you evaluate the condition c and then evaluate either e1 or e2, depending on the condition. This gives you the result of the if .. then .. else.

如果你只有if c then e,那么你不知道如果cfalse,因为没有else分支!以下显然没有意义:

If you have just if c then e, then you don't know what the result of the evaluation should be if c is false, because there is no else branch! The following clearly does not make sense:

let num = if input > 0 then 10

在 F# 中,具有诸如 printf "hi" 之类的副作用的表达式返回 unit 类型的特殊值.该类型只有一个值(写为 ()),因此您可以编写 if ,它只在单个情况下起作用:

In F#, expressions that have side-effects like printf "hi" return a special value of type unit. The type has only a single value (written as ()) and so you can write if which does an effect in just a single case:

let u = if input > 0 then printf "hi" else ()

这总是计算为 unit,但在 true 分支中,它也执行副作用.在 false 分支中,它只返回一个 unit 值.在 F# 中,您不必手动编写 else (),但从概念上讲,它仍然存在.你可以写:

This always evaluates to unit, but in the true branch, it also performs the side-effect. In the false branch, it just returns a unit value. In F#, you don't have to write the else () bit by hand, but conceptually, it is still there. You can write:

let u = if input > 0 then printfn "hi"

关于您的附加示例

代码在我看来非常好.当您必须处理命令式 API(如许多 .NET 库)时,最好的选择是使用命令式功能,例如 ifunit-返回分支.

您可以使用各种调整,例如使用 option<string> 表示您的数据(而不仅仅是带有 null 或空字符串的 string).这样,您可以使用 None 来表示丢失的数据,而其他任何内容都是有效输入.然后你可以使用一些高阶函数来处理选项,比如Option.iter,如果有值就会调用给定的函数:

You can use various tweaks, like represent your data using option<string> (instead of just string with null or empty string). That way, you can use None to represent missing data and anything else would be valid input. Then you can use some higher-order functions for working with options, such as Option.iter, which calls a given function if there is a value:

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) )

这并不是真正的非强制性,而是更具声明性,因为您不必自己编写 if.顺便说一句:如果你想自动Dispose对象,我也推荐使用use.

This is not really less imperative, but it is more declarative, because you don't have to write the if yourself. BTW: I also recommend using use if you want to Dispose object auotmatically.

这篇关于if-then 语句的功能替代是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆