Class 函数在 Ruby 中
First Class Functions In Ruby
我正在努力完成这篇关于函数式编程的文章 (https://codewords.recurse.com/issues/one/an-introduction-to-functional-programming) 并尝试做 Ruby 中的练习。
一个练习定义了两个函数,零和一。零接受一个字符串参数和 returns 字符串索引 1 - 如果第一个字符为 0 则结束,一个做同样的事情,但前提是第一个字符是一个。
以下是 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
该问题要求您编写一个名为 rule_sequence 的方法,给定一个字符串和一个函数数组,returns 结果是一次调用一个函数 --第一个函数在整个字符串中调用,第二个函数在该字符串的 return 值上调用,等等。如果在任何时候,其中一个函数 returns nil,return 无。
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) } ])
有谁能想出比传递或调用 lambda 更简洁的方法吗?
你可以做到
puts rule_sequence('0101', [method(:zero), method(:one), method(:zero)])
顺便说一句,s[1..(s.length)]
可以写成s[1..-1]
,rules[0].call(string)
可以写成rules[0].(string)
。
我将以此练习为契机展示 Ruby 如何支持高阶函数。
让我们退一步重写 zero
- one
函数。
你会注意到他们有很多共同点。
让我们尝试通过编写一个可以生成两者的 lambda 来利用它
tail_on_prefix = lambda {|prefix|
lambda {|str| str[1..-1] if str[0] == prefix}
}
我们现在可以轻松定义 zero
和 one
zero = tail_on_prefix.("0")
one = tail_on_prefix.("1")
到rule_sequence
现在!
rule_sequence = lambda {|str, rules|
if (str.nil? or rules.empty?)
str
else
rule_sequence.(rules[0].(str), rules[1..-1])
end
}
现在调用 rule_sequence
看起来好多了,不是吗
rule_sequence.("100101", [one, zero, zero]) # => "101"
我正在努力完成这篇关于函数式编程的文章 (https://codewords.recurse.com/issues/one/an-introduction-to-functional-programming) 并尝试做 Ruby 中的练习。
一个练习定义了两个函数,零和一。零接受一个字符串参数和 returns 字符串索引 1 - 如果第一个字符为 0 则结束,一个做同样的事情,但前提是第一个字符是一个。
以下是 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
该问题要求您编写一个名为 rule_sequence 的方法,给定一个字符串和一个函数数组,returns 结果是一次调用一个函数 --第一个函数在整个字符串中调用,第二个函数在该字符串的 return 值上调用,等等。如果在任何时候,其中一个函数 returns nil,return 无。
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) } ])
有谁能想出比传递或调用 lambda 更简洁的方法吗?
你可以做到
puts rule_sequence('0101', [method(:zero), method(:one), method(:zero)])
顺便说一句,s[1..(s.length)]
可以写成s[1..-1]
,rules[0].call(string)
可以写成rules[0].(string)
。
我将以此练习为契机展示 Ruby 如何支持高阶函数。
让我们退一步重写 zero
- one
函数。
你会注意到他们有很多共同点。
让我们尝试通过编写一个可以生成两者的 lambda 来利用它
tail_on_prefix = lambda {|prefix|
lambda {|str| str[1..-1] if str[0] == prefix}
}
我们现在可以轻松定义 zero
和 one
zero = tail_on_prefix.("0")
one = tail_on_prefix.("1")
到rule_sequence
现在!
rule_sequence = lambda {|str, rules|
if (str.nil? or rules.empty?)
str
else
rule_sequence.(rules[0].(str), rules[1..-1])
end
}
现在调用 rule_sequence
看起来好多了,不是吗
rule_sequence.("100101", [one, zero, zero]) # => "101"