В схеме цель (пусть ((cdr cdr)) - PullRequest
14 голосов
/ 09 июля 2010

Я недавно изучал Scheme и натолкнулся на функцию, которая определена следующим образом:

(define remove! 
    (let ((null? null?)
          (cdr cdr)
          (eq? eq?))
     (lambda ... function that uses null?, cdr, eq? ...)

Какова цель привязки нуля?обнулить?или cdr to cdr, когда они встроены в функции, которые доступны в определении функции без блока let?

Ответы [ 2 ]

30 голосов
/ 09 июля 2010

В простой схеме R5RS нет модульной системы - только верхний уровень.Кроме того, менталитет состоит в том, что все можно изменить, так что вы можете «настроить» язык так, как вам хочется.Но без модульной системы это не работает хорошо.Например, я пишу

(define (sub1 x) (- x 1))

в библиотеку, которую вы загружаете - и теперь вы можете переопределить -:

(define - +) ; either this
(set! - +)   ; or this

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

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

(define sub1 (let ((- -)) (lambda (x) (- x 1))))

Теперь все будет работать "более хорошо", поскольку вы не можете изменить значение моей функции sub1, изменив -.(За исключением ... если вы измените его до , вы загрузите мою библиотеку ...)

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

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

2 голосов
/ 09 июля 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...