将一个简单的命令式算法转换为函数式sty

2024-10-03 15:27:33 发布

您现在位置:Python中文网/ 问答频道 /正文

我最近做了一个小算法,从一段代码中去掉函数参数,只保留最外层的函数。
我发现这个算法很容易设计成命令式。
然而,我对函数式编程很感兴趣,我想知道如何用函数式的方式完成同样的事情。在

如果你能告诉我这样一个算法是如何工作的,那对我会很有帮助,这样我就可以更好地了解函数式编程是如何工作的。在设计算法的同时我也想知道你的想法。在

我用Python编写了命令式版本,但是您的答案不一定要用Python;haskell或其他任何语言也可以。在

它的作用如下(将字符串作为输入并返回字符串):

"foo(a.d, b.e.fi()).go(sd, ds())"     -- returns -->  "foo().go()"
"foo(a, b).bar().fuu"                 -- returns -->  "foo().bar().fuu"
"foo.bar"                             -- returns -->  "foo.bar"

下面是我的命令代码:

^{pr2}$

Tags: 函数字符串代码算法gofoo编程方式
3条回答

以下是我的版本:

import Control.Monad
import Control.Monad.State

-- filter `str` with the "stateful" monadic predicate function `handleChar`, 
-- with an initial state of 0
getRidOfArguments :: String -> String
getRidOfArguments str = filterM handleChar str `evalState` 0

handleChar :: Char -> State Int Bool
handleChar '(' = modify (+1) >> gets (<= 1)
handleChar ')' = modify (max 0 . subtract 1) >> gets (== 0)
handleChar _   = gets (== 0)

我的思考过程是:我们过滤一个列表,这样filter就会浮现在脑海中;然而,我们是否保留或删除一个字符取决于某种状态(我们的开放/关闭parens计数)。因此,一元过滤函数filterM是合适的,我们可以使用State单子来抽象开/闭计数的管道。在

如果你想知道更多关于以上工作的细节,请告诉我。在

好吧,我更喜欢jberryman的解决方案,但是如果你想避免monad,那么试试这个

stateFilter :: (s -> a -> (s, Bool)) -> [a] -> s -> [a]
stateFilter f as state = snd $ foldr stepper (state, []) as
  where stepper (state, filtered) a =
          let (state', b) = f state a in
             if b then (state', a:filtered) else (state', filtered)

这使一个状态在我们的过滤函数中保持运行,我们只返回当前值是否为真以及我们的新状态。那么你的代码就是

^{pr2}$

现在的状态是明确的(不是那么漂亮),但也许更容易理解。在

clean str = stateFilter handleChar str 0

现在这是好的和功能性的,整个事情归结为折叠在绳子上。有一点管道正在进行跟踪状态,但一旦你开始摸索哈斯克尔多一点,这就很好地消失了。在

已经有很多答案了,但是为了增加这个列表,这里有一个非常简单的函数式。在

它使用接受嵌套计数的helper函数。因此,0表示不在括号内,1表示在1对内等。如果n>;0,则删除字符。如果我们在括号中相应地增加/减少n。在

helper函数基本上是对该算法的逐个描述。如果真的使用它,你会把它挂在“where”子句上。在

skipBrackets :: String -> String
skipBrackets s = skipper s 0

skipper :: String -> Int -> String

skipper [] _ = []
skipper ('(':xs) 0 = '(' : skipper xs 1
skipper (')':xs) 1 = ')' : skipper xs 0

skipper ('(':xs) n = skipper xs (n + 1)
skipper (')':xs) n = skipper xs (n - 1)

skipper (x:xs) 0 = x : skipper xs 0
skipper (x:xs) n = skipper xs n

相关问题 更多 >