英文:
What functional paradigm is this
问题
I can provide the translated code and questions without additional content:
代码部分:
我正在编写一些Python代码,我一再实现了一个我在许多语言中都实现过的模式。我一直在思考这是否是一种函数式范式,并且是否可以在不使用for
循环的情况下实现这个功能,但我没有看到它。 Map
接受一个系列并返回一个新系列。 Reduce
接受一个系列并将其减少为单个结果。这都不是那种情况。
下面的这个函数的想法是重复地对单个字符串应用转换。在这种情况下:
- 替换所有uuid
- 然后替换5到9位数字之间的所有数字组
- 还会有更多的转换
def to_template(message):
mappers = [
('[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}', '{.uuid}'),
(' [0-9]{5,9}.', ' {.request_id}.')
]
result = message
for pattern, replacement in mappers:
result = re.sub(pattern, replacement, result)
return result
问题:
- 这是否可以以函数式方式实现?
- 是否已知有用于此的函数式范式?
英文:
I am writing some python code and I am implementing a pattern that I have done repeatedly and in numerous languages. I keep thinking this is some sort of functional paradigm, and that this can be implemented functionally (without use of a for
loop), but I am not seeing it. Map
takes a series and returns a new series. Reduce
takes a series and reduces it to a single result. This is neither of those.
The idea of this function below is to repeatedly apply a transformation to a single string. In this case:
- Replace all uuids
- then replace all number groups between 5-9 digits
- There will be more transforms
def to_template(message):
mappers = [
('[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}', '{.uuid}'),
(' [0-9]{5,9}.', ' {.request_id}.')
]
result = message
for pattern, replacement in mappers:
result = re.sub(pattern, replacement, result)
return result
The questions:
- Can this be implemented functionally?
- Is there a known functional paradigm for this?
答案1
得分: 5
In functional programming terms, this is a fold: you are folding (i.e., reducing) a list of replacement operations to a single string, with a string as the starting point.
在函数式编程术语中,这是一个 折叠:你正在将替换操作的列表折叠(即,减少)为一个字符串,以字符串作为起始点。
In Python, you can write this using the reduce
function in the functools
module.
在Python中,你可以使用functools
模块中的reduce
函数来编写这个。
reduce
repeatedly calls re.sub
using an element from mappers
for the first arguments and the result of the previous call as the second argument. (The first call uses message
as the "zeroth" return value of re.sub
.)
reduce
重复调用re.sub
,使用mappers
中的一个元素作为第一个参数,上一次调用的结果作为第二个参数。(第一次调用时,将message
用作re.sub
的“零值”返回值。)
Recursively, one could implement reduce
as
递归地,可以实现reduce
如下:
Iteratively, it looks much like your function:
迭代方式看起来很像你的函数:
Theoretically, you could also imagine using function composition to fold a list of functions into a single function that gets applied to your message.
从理论上讲,你还可以想象使用函数组合将函数列表折叠成一个应用于你的消息的单个函数。
英文:
In functional programming terms, this is a fold: you are folding (i.e., reducing) a list of replacement operations to a single string, with a string as the starting point.
In Python, you can write this using the reduce
function in the functools
module.
from functools import reduce
def to_template(message):
mappers = [ ... ]
return reduce(lambda r, p: re.sub(*p, r), mappers, message)
reduce
repeatedly calls re.sub
using an element from mappers
for the first arguments and the result of the previous call as the second argument. (The first call uses message
as the "zeroth" return value of re.sub
.)
Recursively, one could implement reduce
as
def reduce(f, itr, init):
if not itr:
return init
else:
return reduce(f, itr[1:], f(init, itr[0]))
Iteratively, it looks much like your function:
def reduce(f, itr, init):
result = init
for x in itr:
result = f(result, x)
return result
Theoretically, you could also imagine using function composition to fold a list of functions into a single function that gets applied to your message.
from functools import reduce, partial
def to_template(message):
mappers = [
partial(re.sub, '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}', '{.uuid}'),
partial(re.sub, ' [0-9]{5,9}.', ' {.request_id}.')
]
# Apply f first, so that reduce applies functions
# in the order they appear in the list.
def compose(f, g):
return lambda x: g(f(x))
def identity(x):
return x
f = reduce(compose, mappers, identity)
return f(message)
However, for a large number of mapping operations, you would probably hit the recursion limit with the nested function calls that reduce
and compose
would build up.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论