Al escribir algoritmos recursivos que actúan sobre las estructuras de datos anidadas utilizando las funciones recursivas, puede utilizar throw
de manera similar a como se puede utilizar un break
o principios return
al escribir algoritmos iterativos que actúan sobre los datos planas usando for
bucles.
Por ejemplo, suponga que tiene una lista de números enteros positivos y que desea (por alguna razón) para escribir una función que devolverá verdadero si se cumple alguna de las siguientes condiciones:
- La suma de todos los elementos de la lista es mayor que 100
- Algunos elementos de la lista si es igual a 5
Digamos también que siempre se quiere realizar esta comprobación en una sola pasada circuito a corto, sobre la lista, en lugar de hacer un reduce
c todos para obtener la suma y una llamada por separado any?
para buscar cinco.
lo que probablemente escribir algo de código un poco como esto (de hecho, es probable que tenga código escrito como este en algún lenguaje en algún momento de su vida):
def test(list)
sum = 0
for i in list
sum += i
if i == 5 || sum > 100
return true
end
end
return false
end
En la mayoría de los idiomas, no hay equivalente limpio para romper un algoritmo recursivo que usa una función recursiva. ¡En Ruby, sin embargo, hay! Suponga que, en lugar de tener una lista y querer comprobar si sus elementos contienen un cinco o una suma de más de 100, tiene un árbol y quiere comprobar si su contiene contiene un cinco o suma de más de 100, mientras que corto -circuitar y regresar tan pronto como sepa la respuesta.
Usted puede hacer esto con elegancia con throw
/catch
, así:
def _test_recurse(sum_so_far, node)
if node.is_a? InternalNode
for child_node in node.children
sum_so_far = _test_recurse(sum_so_far, child_node)
end
return sum_so_far
else # node.is_a? Leaf
sum_so_far += node.value
if node.value == 5
throw :passes_test
elsif sum_so_far > 100
throw :passes_test
else
return sum_so_far
end
end
end
def test(tree)
catch (:passes_test) do
_test_recurse(0, tree)
return false
end
return true
end
El throw :passes_test
aquí actúa un poco como un break
; te permite saltar de toda la pila de llamadas debajo de la llamada más externa _test
. En otros idiomas, puede hacer esto al abusar de las excepciones para este fin o al usar un código de retorno para indicar a la función recursiva que detenga el recursivo, pero esto es más directo y más simple.
Posible duplicado de: http://stackoverflow.com/questions/51021/what-is-the-differance-between-raising-exceptions-vs-throwing-exceptions-in-ruby – Shadwell