Как мне сделать это более идиоматичным? - PullRequest
1 голос
/ 08 марта 2011

Итак, вот функция, которую я перевел с другого языка (Lisp), в основном дословно.Мне кажется, это не совсем правильно, что с использованием ref, if без else и т.д. Как бы вы переписали вторую функцию ниже?не требуется, чтобы код даже использовал Set;оригинал только что использовал список.

1 Ответ

3 голосов
/ 08 марта 2011

В целом, я думаю, что ваше решение выглядит довольно хорошо - я думаю, что это та проблема, в которой немного изменчивости делает выражение алгоритма более понятным. Однако вместо использования изменяемой ссылки на неизменяемый набор, который вы обновляете неоднократно, лучше использовать реализацию изменяемого набора:

open System.Collections.Generic

let getConnected node edges =
  let visited = HashSet()
  let rec traverse node = 
    if not (visited.Contains node) then
      visited.Add node
      directEdges node edges
      |> List.iter (fun (a,b) -> traverse b)
  traverse node
  visited

и если вы хотите, чтобы вывод был неизменным, вы можете просто добавить |> set после последней строки.

С другой стороны, если вы хотите использовать функциональный подход, это не слишком сложно:

let getConnected node edges =  
  let rec traverse node visited =       
    if not (Set.contains node visited) then
      directEdges node edges             
      |> List.fold (fun nodes (a, b) -> traverse b nodes) (Set.add node visited)
    else
      visited
  traverse node Set.empty
...