Что такое оптимизация вызовов?

Вам придётся прибегнуть к решению JNI. В http://sourceforge.net/projects/jwlanscan есть что-то доступное, но это работает только для систем Windows. Или вы можете сделать это уродливым способом и использовать Runtime.getRuntime (). Exec (...) и использовать инструменты командной строки, доступные для вашей ОС (* nix = iwconfig), и прибегать к разбору.

719
задан ks1322 1 January 2014 в 15:02
поделиться

4 ответа

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

Схема является одним из нескольких языков программирования, которые гарантируют в спецификации, что любая реализация должна обеспечить эту оптимизацию (JavaScript делает также, начиная с ES6) , таким образом, вот два примера функции факториала в Схеме:

(define (fact x)
  (if (= x 0) 1
      (* x (fact (- x 1)))))

(define (fact x)
  (define (fact-tail x accum)
    (if (= x 0) accum
        (fact-tail (- x 1) (* x accum))))
  (fact-tail x 1))

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

(fact 3)
(* 3 (fact 2))
(* 3 (* 2 (fact 1)))
(* 3 (* 2 (* 1 (fact 0))))
(* 3 (* 2 (* 1 1)))
(* 3 (* 2 1))
(* 3 2)
6

Напротив, отслеживание стека для хвоста рекурсивный факториал смотрит следующим образом:

(fact 3)
(fact-tail 3 1)
(fact-tail 2 3)
(fact-tail 1 6)
(fact-tail 0 6)
6

, Как Вы видите, мы только должны отслеживать тот же объем данных для каждого вызова к хвосту факта, потому что мы просто возвращаем значение, в котором мы разбираемся до вершины. Это означает, что, даже если я должен был звонить (факт 1000000), мне нужна только та же сумма пространства как (факт 3). Дело обстоит не так с non-tail-recursive фактом и большими значениями как таковыми может вызвать переполнение стека.

674
ответ дан rogerdpack 1 January 2014 в 15:02
поделиться

TCO (Оптимизация последнего вызова) является процессом, которым умный компилятор может позвонить функции и не взять дополнительное стековое пространство. только ситуация, в которой это происходит, состоит в том, если последняя инструкция, выполняемая в функции f, является вызовом к функциональному g (Примечание: g может быть f). Ключ здесь - то, что f больше не нужно стековое пространство - это просто звонит g и затем возвращает любой , g возвратился бы. В этом случае оптимизация может быть сделана этим, g просто выполняет и возвращает любое значение, которое это имело бы к вещи который названный f.

Эта оптимизация может выполнить рекурсивные вызовы, берут постоянное стековое пространство, вместо того, чтобы взорваться.

Пример: эта функция факториала не является TCOptimizable:

def fact(n):
    if n == 0:
        return 1
    return n * fact(n-1)

Эта функция делает вещи, кроме того, вызывают другую функцию в ее операторе возврата.

Это ниже функции - TCOptimizable:

def fact_h(n, acc):
    if n == 0:
        return acc
    return fact_h(n-1, acc*n)

def fact(n):
    return fact_h(n, 1)

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

179
ответ дан today 1 January 2014 в 15:02
поделиться

Обратите внимание, в первую очередь, что не все языки поддерживают его.

TCO applys к особому случаю рекурсии. Суть его, если последней вещью, которую Вы делаете в функции, является сам вызов (например, это называет себя от положения "хвоста"), это может быть оптимизировано компилятором для действия как повторение вместо стандартной рекурсии.

Вы видите, обычно во время рекурсии, время выполнения должно отслеживать все рекурсивные вызовы, так, чтобы, когда каждый возвращается, это могло возобновиться в предыдущем вызове и так далее. (Попытка, вручную выписывающая результат рекурсивного вызова получить визуальную идею того, как это работает.) Отслеживание всех вызовов занимает место, которое становится значительным когда вызовы функции само много. Но с TCO, это может просто сказать, "возвращаются к началу, только на этот раз изменяют значения параметров на эти новые". Это может сделать это, потому что ничто после рекурсивного вызова не относится к тем значениям.

13
ответ дан J Cooper 1 January 2014 в 15:02
поделиться

Посмотрите здесь:

http://tratt.net/laurie/tech_articles/articles/tail_call_optimization

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

6
ответ дан BobbyShaftoe 1 January 2014 в 15:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: