Что такое идиоматический c способ реализации ленивых громов - PullRequest
1 голос
/ 21 апреля 2020

Предположим, у вас есть структура графа. Соседи узла могут быть получены дорогостоящей операцией get_neighbor(server, node) (например, извлечением чего-либо из Интернета), которая требует административного параметра server. Ваша задача - найти путь от заданного начального узла.

У вас уже есть подпрограмма поиска, которая достаточно умна, чтобы вычислять окрестности по требованию. Но вы не можете изменять интерфейс этой подпрограммы, так как она используется где-то еще. В частности, вы не можете ввести административный параметр:

def search(p, node, todo, graph, visited):
  visited[n] = True
  if p(n): 
    return n
  # Note, we evaluate the neighborship relation on demand
  for n in graph[node]():
      if n not in visited:
          todo.append(n)
  if len(todo) == 0:
    return None

  next = todo.pop(0)
  return search(p, next, todo, graph, visited)

Мы могли бы использовать простые символы (лямбды) для оценки отношения соседства только при необходимости:

for node in all_nodes():
  tree[node] = (lambda node : lambda : get_neighbor(server, node))(node)

(необходима двойная лямбда) для принудительного сбора значений.)

Это должно работать нормально для одной оценки поиска, поскольку каждая дорогостоящая операция выполняется не более одного раза. Но для повторных поисков по одному и тому же графику одни и те же запросы могут повторяться. Поэтому в идеале возвращаемая лямбда должна кешировать свое значение, т. Е. Становиться фактически ленивым.

Как создать такой thunk наиболее идиоматическим образом c в python, предпочтительно без дополнительных зависимостей?

...