Какви биха били последствията от допускането специалните форми да бъдат третирани като нормални стойности?

Открих, че специалните форми не могат да се подават като аргументи или да се записват в променливи, както в Clojure:

user=> (defn my-func 
         [op] 
         (op 1 2 3))
#'user/my-func
user=> (my-func +)
6
user=> (my-func if)
java.lang.Exception: Unable to resolve symbol: if in this context (NO_SOURCE_FILE:5)
user=> (def my-if if)
java.lang.Exception: Unable to resolve symbol: if in this context (NO_SOURCE_FILE:9)

и в Рекет/Схема:

> (define (my-func op)
    (op 1 2 3))
> (my-func +)
6
> (my-func if)
  if: bad syntax in: if
> (define my-if if)
  *if: bad syntax in: if

Това е страхотно, добре съм с това, знам, че мога просто да напиша функция, за да обвия специална форма и след това да предам тази функция.

Но бих искал да знам защо Lisps имат това ограничение и какви отрицателни последици би имало допускането на това. Има ли някакви големи диалекти, които позволяват това?


person Matt Fenwick    schedule 04.07.2012    source източник


Отговори (2)


Това прави оценката по-сложна и компилацията трудна.

Ако имате формуляр (a b c), тогава трябва да разрешите по време на изпълнение стойността на a и след това да я приложите по някакъв начин към формулярите b и c.

По-опростеният модел на няколко ограничен брой специални формуляри и иначе стриктна оценка отпада.

Вижте също: FEXPR

person Rainer Joswig    schedule 04.07.2012

Специалните форми не са функции: функциите приемат стойности като аргументи, докато специалните форми приемат форми. Например, вижте вашия пример за if:

(if 1 2 3)

Добре, това е лесно, тъй като 2 и 3 вече са стойности. Но какво да кажем за това?

(define (modadd a b n)
  (if (zero? n) #f (modulo (+ a b) n)))

В този случай if всъщност получава #f и (modulo (+ a b) n) като форми, а не като стойности. И това е важно! (modulo x n) ще се провали, ако n е 0: ето защо остава без оценка, докато не разберем, че n не е 0.

Проблемът с възможността за предаване на специални форми като първокласни обекти е, че функциите от по-висок ред не могат да извикват тези обекти, използвайки предсказуема семантика: дали това е функционален обект, така че предавате стойности, или е специална форма, така че минаваш във формуляри? Това става огромна бъркотия.

Да, можете да напишете обвиваща функция, като моята modadd, която капсулира if. Въпреки това, няма начин просто да внедрите if като функция, като същевременно запазите поведението само за оценка на един от клоновете.

person Chris Jester-Young    schedule 04.07.2012