может ли if быть правильной функцией, а не специальной формой

StackOverflow https://stackoverflow.com/questions/2240762

Вопрос

Я, наконец, начал изучать функциональные языки (emacs lisp), и в нем проводится четкое различие между функциями и специальными формами, такими как управление потоком, например if.

Существует ли фундаментальная / теоретическая причина, по которой особые формы отличаются от функций?предоставляют ли какие-либо языки функциональные if?

Спасибо

Это было полезно?

Решение

При активной оценке требуется различие, языки с отложенной оценкой (т.е.Хаскелл), если и др.могут быть функциями.

Нетерпеливая оценка:Вычисляются аргументы функции до того, как вызывается функция, и в функцию передаются только результаты.

Ленивая оценка:Аргументы функции вычисляются тогда и только тогда, когда к ним осуществляется доступ.

Другие советы

Если if была обычной функцией, тогда оба ее аргумента — затем сформируйте и тот другая форма—было бы и то , и другое быть оцененным до того, как вызывая if функция, потому что это правило оценка функции:оценивать все аргументы чтобы создать значения, затем предоставьте эту последовательность значений в качестве аргументов функции, обозначенной первым символом в списке.

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

В таких языках, как Emacs Lisp и Common Lisp, специальные формы являются встроенными языковыми конструкциями.У них разные правила оценки, которые вызывает обычная функция.При обычных вызовах функций вычисляются все аргументы.Таким образом, вы не можете написать IF как обычную функцию - условие определяет, какое предложение будет оценено.Также обычно вы не можете писать свои собственные специальные формы - в Common Lisp нет языковой конструкции для определения специальной формы (хотя отдельные реализации должны были каким-то образом реализовывать существующие.Это приводит к созданию макросов.С помощью макросов вы можете написать синтаксическое преобразование, которое преобразует одно выражение в другое.Чтобы иметь возможность записать IF в виде макроса, вам нужно иметь другую условную форму, которую вы можете использовать для преобразованного кода.Lisp предоставляет условные выражения в качестве базовых конструкций.Давайте предположим, что COND является такой базовой конструкцией, тогда вы могли бы расширить IF до использования COND .

MY-IF как макрос в Common Lisp:

(defmacro my-if (condition true-clause false-clause)
   `(cond (,condition ,true-clause)
          (t ,false-clause)))

Итак

(my-if (foo-p) 'one 'two)

расширяется до

(cond ((foo-p) 'one)
      (t 'two))

Для полноты картины:в системе нет специальных формуляров Пико язык, например, и if является примитивным функция в то время как Pico вдохновлен Scheme и по умолчанию имеет нетерпеливую оценку.

В Схеме вы могли бы написать

(define (true t f)
  (t))

(define (false t f)
  (f))

(define (function_if c t e)
  (c t e))

а потом

(function_if true (lambda () 'true) (lambda () 'false))
==> true

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

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

(define (true (t) (f))
  (t))

(define (false (t) (f))
  (f))

Затем функция if становится:

(define (function_if c (t) (e))
  (c (t) (e)))

и

(function_if true 'true 'false)
==> true

В качестве другого примера приведем определение функции and является (define (and p (q)) (p (q) false)).

Аналогичным образом вы можете определить or, not, while, for, ...в качестве функций, используя приведенную выше кодировку логических значений.

Краткий ответ:Нет.

Длинный (er) ответ:(if ...) требует, чтобы вы контролировали порядок вычисления аргументов.Lisp, будучи нетерпеливым языком, не может сделать это в функции.

Обходной путь:сделайте это в макросе:

(defmacro _if (cnd true false)
    (let (  (gcond (gensym))
            (gresp (gensym)))
        `(let ( (,gcond ,cnd) ;`#quotes
                (,gresp nil))        
            (and ,gcond       (setf ,gresp (multiple-value-list ,true)))
            (and (not ,gcond) (setf ,gresp (multiple-value-list ,false)))
            (values-list ,gresp))))

Например:

[dsm@localhost:~]$ clisp -q
[1]> (defmacro _if (cnd true false)
    (let (  (gcond (gensym))
            (gresp (gensym)))
        `(let ( (,gcond ,cnd) ;`#quotes
                (,gresp nil))        
            (and ,gcond       (setf ,gresp (multiple-value-list ,true)))
            (and (not ,gcond) (setf ,gresp (multiple-value-list ,false)))
            (values-list ,gresp))))
_IF
[2]> (_if (= 1 1) (+ 2 3) "bar")
5
[3]> (_if (= 1 2) (+ 2 3) "bar")
"bar"
[4]> 

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

def If[A](cond : Boolean, truePart : => A, falsePart : => A) = if (cond) truePart else falsePart

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top