Короткий ответ заключается в том, что if v then return v end
возвращает значение v
, если оно истинно, т. е. если оно не является ни false
, ни nil
. В противном случае функция продолжает вычислять значение для v
, сохранять это значение в binomtable
и, наконец, возвращать его. Более интересный вопрос: зачем функция все это делает?
В опубликованном коде binom3
является рекурсивной функцией. С рекурсивными вызовами v = binom3(n-1,m-1) + binom3(n-1,m)
будет много дублирования усилий, что означает много потраченного впустую места и времени. Рассмотреть возможность:
binom3(4, 2)
--> binom3(3, 1) + binom3(3, 2)
--> binom3(2, 0) + binom3(2, 1) + binom3(2, 1) + binom3(2, 2)
--> 1 + binom3(1, 0) + binom3(1, 1) + binom3(1, 0) + binom3(1, 1) + 1
Обратите внимание, что во второй редукции два одинаковых термина:
binom3(2, 1) + binom3(2, 1)
Нет причин вычислять термин binom3(2, 1)
дважды, и это означает, что пара терминов:
binom3(1, 0) + binom3(1, 1)
также должен быть рассчитан дважды, как видно из третьего сокращения. Было бы разумно вычислить binom3(2, 1)
только один раз и сохранить результат для последующего использования в более крупном расчете. Когда m
и n
больше, а количество вычислений увеличивается экспоненциально, это становится очень важной проблемой для производительности как с точки зрения требуемого объема памяти, так и с точки зрения требуемого времени.
В опубликованном коде используется memoization для повышения производительности. Когда расчет сделан, он сохраняется в таблице binomtable
. Прежде чем производить какие-либо расчеты, консультируются с binomtable
. Во-первых, v
устанавливается равным binomtable[i]
; если это значение является любым истинным значением (любое целое число является истинным в Lua), то это значение просто возвращается без необходимости рекурсивного вычисления. В противном случае, если возвращается nil
(т. е. значение для вычисления еще не сохранено), функция продолжает рекурсивное вычисление. После завершения расчета новое значение сохраняется в binomtable
для использования в следующий раз, когда оно понадобится. Эта стратегия экономит много ненужных вычислительных усилий и может иметь огромное значение в производительности таких рекурсивных алгоритмов.
person
ad absurdum
schedule
30.10.2020