在FP中使用OR作为分支控制

时间:2011-03-29 14:51:55

标签: python functional-programming lisp scheme

我上周接受了一次采访,在那里我学到了一些我不知道的关于python的东西(或者更确切地知道它们是如何被使用的),首先是这个问题的内容是使用{{1出于分支控制的目的。

因此,例如,如果我们运行:

or

然后,如果def f(): # do something. I'd use ... but that's actually a python object. def g(): # something else. f() or g() 计算到某个真实条件,则返回该值,否则,将评估f()并返回它产生的任何值,无论是真还是假。这使我们能够使用g()关键字实现if语句。

我们还可以使用orand如果f() and g()为真,则g()将返回f()的值,如果f()则返回g()的值是假的。

我被告知这个(使用or进行分支控制)在lisp等语言中很常见(因此是lisp标记)。我目前正在关注SICP学习计划,因此我可以看到(or (f x) (g x))会返回(g x)的值,假设(f x)#f

我对这项技术是否有任何优势感到困惑。它显然实现了分支控制,但对我来说,内置关键字似乎更加不言自明。

我也很困惑这是否“功能性”?我对纯函数式编程的理解是你使用这样的结构(我最近的erlang实验中的一个例子):

makeeven(N,1) -> N+1;
makeeven(N,0) -> N;
makeeven(N)   -> makeeven(N,N rem 2). 

使用template meta-programming in C++(通过cpp-next.com发现)更好,更复杂的示例。我的思维过程是函数式编程的一个方面归结为piecewise defined functions in code用于分支控制(如果你可以管理它,尾递归)。

所以,我的问题:

  • 这是“功能性”吗?看起来这样,我的采访者说他们有功能编程的背景,但它与我认为的功能不匹配。我没有理由为什么你不能将逻辑运算符作为函数的一部分 - 它似乎很好地适用于高阶函数的概念。我只是没想到逻辑运算符的使用是功能程序员如何实现分支控制。对?错误?我可以看到电路使用逻辑门进行分支控制,所以我猜这是一个类似的(相关的)概念?
  • 使用这种技术有一些优势吗?它只是语言简洁/语法问题,还是在构建解释器以使用这种结构方面有什么影响?
  • 这种技术有用例吗?或者它不经常使用?是否使用过?作为一个自学成才的人,我以前从未见过它,虽然这本身并不一定令人惊讶。

我为跳过这么多语言而道歉;我只是想把我对它们的理解联系在一起。随意用任何语言回答。如果我误解了任何定义或遗漏了一些重要的东西,我也很抱歉,我从未正式学过计算机科学。

6 个答案:

答案 0 :(得分:12)

你的面试官必须有一个“功能背景”的方式。曾经常见的是写

(or (some-condition) (some-side-effect))

但是在CL和支持它的Scheme实现中,使用unless写得更好。 andwhen相同。

所以,更具体一点 - 它不是更具功能性(事实上,这些东西的常见用途是单方面条件,这些条件起初不起作用);没有任何优势(当你知道事情是以宏的形式实现时,这些语言变得非常明显 - 例如,大多数orand实现扩展为if);任何可能的用例都应该使用whenunless,如果你的实现中有它们,否则最好将它们定义为宏而不是不使用它们。

哦,你可以使用它们的组合而不是双面的if,但那会很混乱。

答案 1 :(得分:6)

我不知道这个代码的执行方式会有任何问题,但是对于没有经验的人来说,这是令人困惑的。事实上,这种语法就像一个Python反模式:你可以做到,但它绝不是Pythonic。

答案 2 :(得分:5)

condition and true_branch or false_branch适用于所有具有短循环逻辑运算符的语言。另一方面,在值具有布尔值的语言中使用它并不是一个好主意。

例如

zero = (1==0) and 0 or 1   # (1==0) -> False 
zero = (False and 0) or 1  # (False and X) -> X
zero = 0 or 1              # 0 is False in most languages
zero = False or 1 
zero = 1

答案 3 :(得分:2)

正如以利所说;此外,纯粹使用逻辑运算符执行控制流程往往会在介绍性的FP类中进行教学 - 更多的是作为一个心灵练习,实际上,不是你必须要使用IRL的东西。能够将任何控制运算符转换为if总是好的。

现在,FP和其他语言之间的最大区别在于,在更多功能语言中,if实际上是一个表达式,而不是语句。 if总是有值! C语言系列有一个宏版本 - test? consequent : alternative构造 - 但如果你嵌套更多的表达式,它就变得非常难以理解了。

在Python 2.5之前,如果您想在Python中使用控制流表达式,则可能必须使用逻辑运算符。但是在Python 2.5中,类似于FP的if-expression语法,所以你可以这样做:

(42 if True else 7) + 35

请参阅PEP 308

答案 4 :(得分:2)

您只提到了需要评估的2个表达式的情况。如果有5个会怎么样?

;; returns first true value, evaluating only as many as needed
(or (f x) (g x) (h x) (i x) (j x))

你会嵌套if语句吗?我不确定我是如何用Python做的。这是几乎

any(c(x) for c in [f, g, h, i, j])

除了Python的any抛弃了值,只返回True。 (可能有一种方法可以用itertools.dropwhile来做,但对我来说似乎有点尴尬。或者我可能只是错过了明显的方法。)

(顺便说一下:我发现Lisp的内置不会相当对应于他们的名字在其他语言中的含义,这可能会令人困惑.Lisp的IF就像C的三元运算符例如,?:或Python的条件表达式,而不是它们的if语句。同样,Lisp的OR在某种程度上更像(但不完全像)Python的any(),只需2由于普通IF已经返回一个值,因此没有必要单独使用不能像这样使用的“if”,或者只使用两个值的单独的“or”。它已经像其他语言中不太常见的变体一样灵活。)

我恰好正在编写这样的代码,巧合的是,其中一些功能是“去问一些服务器的答案”,我想在得到肯定回复后立即停止。我永远不会在我真正想说OR的地方使用IF,但我宁愿说:

(setq did-we-pass (or (try-this x)
                      (try-that x)
                      (try-some-other-thing x)
                      (heck-maybe-this-will-work x))

而不是制作一棵大树的IF。这有资格作为“流量控制”还是“功能性”?我想这取决于你的定义。

答案 5 :(得分:0)

  1. 在功能语言中首选的编程风格可能被认为是“功能性的”。否则就没有任何功能。

  2. 这只是语法。

  3. 有时可能更具可读性,例如:

    def foo(bar=None):
        bar = bar or []
        ...
        return bar
    
    def baz(elems):
        print "You have %s elements." % (len(elems) or "no")
    
  4. 您可以使用bar if bar else [],但它非常详细。