Python Ruby中的第一类函数
我正在阅读这篇关于函数式编程()的文章,并尝试用Ruby做练习 一个练习定义了两个函数,零和一。Zero接受一个字符串参数并返回字符串索引1-end如果第一个字符为0,则执行相同的操作,但仅当第一个字符为1时 以下是ruby实现:Python Ruby中的第一类函数,python,ruby,functional-programming,Python,Ruby,Functional Programming,我正在阅读这篇关于函数式编程()的文章,并尝试用Ruby做练习 一个练习定义了两个函数,零和一。Zero接受一个字符串参数并返回字符串索引1-end如果第一个字符为0,则执行相同的操作,但仅当第一个字符为1时 以下是ruby实现: def zero(s) if s[0] == "0" return s[1..(s.length)] end end def one(s) if s[0] == "1" return s[1..(s.length)] end end
def zero(s)
if s[0] == "0"
return s[1..(s.length)]
end
end
def one(s)
if s[0] == "1"
return s[1..(s.length)]
end
end
这个问题要求您编写一个名为rule_sequence的方法,在给定一个字符串和一个函数数组的情况下,该方法返回结果,以便每次调用一个函数——第一个函数在整个字符串中调用,第二个函数在该字符串的返回值上调用,等等。如果,其中一个函数返回nil,返回nil
Python实现是:
def rule_sequence(s, rules):
if s == None or not rules:
return s
else:
return rule_sequence(rules[0](s), rules[1:])
然而,由于Ruby似乎不支持高阶函数,我能想到的最优雅的解决方案是:
def rule_sequence(string, rules)
if rules.length == 0 or string.nil?
return string
else
return rule_sequence(rules[0].call(string), rules[1..rules.length])
end
end
puts rule_sequence('0101', [lambda { |s| zero(s) }, lambda { |s| one(s) }, lambda { |s| zero(s) } ])
有人能想出比传递或调用lambdas更简洁的方法吗?你可以这样做
puts rule_sequence('0101', [method(:zero), method(:one), method(:zero)])
顺便说一句,
s[1..(s.length)]
可以写成s[1..-1]
,规则[0]。调用(字符串)
可以写成规则[0].(字符串)
,我将利用这个练习来展示Ruby是如何支持高阶函数的
让我们后退一步,重写zero
-one
函数。
你可以注意到他们有很多共同点。
让我们尝试通过编写一个lambda来利用这一点,该lambda可以同时生成
tail_on_prefix = lambda {|prefix|
lambda {|str| str[1..-1] if str[0] == prefix}
}
我们现在可以轻松定义0
和1
zero = tail_on_prefix.("0")
one = tail_on_prefix.("1")
现在开始执行规则序列
rule_sequence = lambda {|str, rules|
if (str.nil? or rules.empty?)
str
else
rule_sequence.(rules[0].(str), rules[1..-1])
end
}
现在调用rule\u sequence
看起来好多了,不是吗
rule_sequence.("100101", [one, zero, zero]) # => "101"
这些不是函数,而是方法。这就是你的全部问题!如果你用函数(Ruby中称为
Proc
s)重做这个练习,它就会工作。就我个人而言,我更喜欢lambda文本语法,而不是将块传递给Kernel 35; lambda
来创建lambda,但这只是一种风格偏好。它使它们看起来更接近于其他语言中的lambda文本,如ECMAScript、Haskell、C#、Java、Scala、CoffeeScript等。一个微小的优势可能是,作为内置语法,编译器可能会执行一些优化,这是类似于lambda
的方法所无法执行的,毕竟,可能会被重写或修改以执行完全不同的操作…但是,我不知道是否有任何现有(甚至未来)编译器会这样做。如果s[0]==p},您可以将函数定义为tail_on_prefix=->(p,s){s[1..-1],而不是嵌套的lambda
调用
并用于获取零和一,即one=strip_prefix.curry['1']