В Схеме вы делаете локальную привязку, затеняя все, что выше, с let
.Поскольку +
и *
- это просто переменные, которые просто оцениваются для процедур, вы просто присваиваете старым процедурам другие имена переменных.
(let ((+ *))
+)
; ==> #<procedure:*> (non standard visualization of a procedure)
В схеме нет зарезервированных слов .Если вы посмотрите на другие языки, список зарезервированных слов довольно высок.Таким образом, в Схеме вы можете сделать это:
(define (test v)
(define let 10) ; from here you cannot use let in this scope
(define define (+ let v)) ; from here you cannot use define to define stuff
define) ; this is the variable, not the special form
;; here let and define goes out of scope and the special forms are OK again
(define define +) ; from here you cannot use top level define
(define 5 6)
; ==> 11
В этом действительно хорошая вещь: если вы выбираете имя, и следующая версия стандарта использует одно и то же имя для чего-то похожего, но не совместимоготвой код не сломается.На других языках, с которыми я работал, в новой версии могут возникнуть конфликты.
R6RS делает это еще проще
От R6RS у нас есть библиотеки.Это означает, что мы полностью контролируем, какие формы верхнего уровня мы получаем из стандарта в наши программы.У вас есть несколько способов сделать это:
#!r6rs
(import (rename (except (rnrs base) +) (* +)))
(+ 10 20)
; ==> 200
Это тоже нормально.
#!r6rs
(import (except (rnrs base) +))
(define + *)
(+ 10 20)
; ==> 200 guaranteed
И наконец:
#!r6rs
(import (rnrs base)) ; imports both * and +
(define + *) ; defines + as an alias to *
(+ 10 20)
; ==> 200 guaranteed
Другие языки тоже это делают:
JavaScript, пожалуй, самый очевидный:
parseFloat = parseInt;
parseFloat("4.5")
// ==> 4
Но вы не можете трогать их операторов.Они зарезервированы, потому что язык должен сделать много вещей для приоритета оператора.Так же, как Scheme JS - хороший язык для печати утки.