2015-09-09 5 views
0

В настоящее время я пытаюсь понять детали реализации следующей процедуры memoizing, как показано на severalvariants в Tcl вики:Детали реализации процедуры memoizing из Tcl вики

proc memoize {} { 
    global memo 
    set cmd [info level -1] 
    if {[info level] > 2 && [lindex [info level -2] 0] eq "memoize"} return 
    if {![info exists memo($cmd)]} {set memo($cmd) [eval $cmd]} 
    return -code return $memo($cmd) 
} 

Что является общим для всех из них (к моему пониманию), что они сравнивают первое слово команды бабушки и дедушки (lindex [info level -2] 0) с буквально название этой функции, напоминающее имя (в данном случае "memoize").

Будет ли какой-либо недостаток изменения, чтобы это сравнение команды прародитель с этой командой, другими словами, изменение [lindex [info level -2] 0] eq "memoize" к [info level -2] eq [info level 0]?

ответ

1

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

foo ab cd ef     <--- A 
    memoize     <--- B 
     foo ab cd ef   <--- C 
     memoize    <--- D 

Когда видит, что конфигурация стека, это return s, так что D не делает ничего, C возвращает фактическое вычисленное значение, B кэши это значение, и A может затем вернуть его в будущем, не вычисляя его. Все это довольно сложно и хакерски; Я предпочитаю просто делать функции о кэшировании материала.

Он также хрупкий несколькими другими ключевыми способами, такими как memoized функция не может использовать upvar или сделать рекурсивные вызовы к себе. Некоторые из других опций на этой странице wiki не имеют этой слабости. Проблема с рекурсивными вызовами, вероятно, лучше всего адресована (если вы не собираетесь ее решать, используя другую общую стратегию напоминания), проверяя не первое слово результата info level -2, а скорее, присутствует ли весь шаблон (т. Е. info level -1 - это то же самое, что и info level -3, и есть ли вообще info level -3).