Что это на самом деле означает, что переменные не могут варьироваться в SML? - PullRequest
0 голосов
/ 20 февраля 2019

У меня вопрос по поводу языка SML.Я читал, что SML имеет переменные, но они не меняются .Когда значение и переменная ограничены, они устанавливаются на всю жизнь и не могут быть изменены.Мой вопрос, как это работает "За кулисами", иначе в памяти.Если, например, я запустил следующую программу:

val a = 5;
val a = a + 1;

Будет ли переводчик выделять новое место в памяти для "нового" a?

Каковы преимущества этой идеи?Такое ощущение, что он менее эффективен, чем PL, такой как C.

Ответы [ 2 ]

0 голосов
/ 20 февраля 2019
val a = 5
val a = a + 1

Будет ли переводчик выделять новое место в памяти для «нового» * ​​1003 *?

Да, точно.

SML имеет двавещи, привязки значений и изменяемые ссылки (как переменные, например, в C).

Что вы описываете привязки значений и ихзначение не может изменяться в одной и той же области.

Здесь значение a не изменяется , оно затенено другой a, создавая новую областьсо старым a скрытым.Поэтому, если вы используете старые a и shadow a, использование старого a не изменится.Более наглядный пример:

val a = 5
fun f x = x + a
val a = 10
val b = f 1  (* = 6, not 11 *)

В чем преимущества этой идеи?

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

  1. Привязки значений вместо изменяемых ссылок означает, что именованные значения не меняются в течение срока их службы.Это хорошо, потому что тогда рассуждать о вашем коде проще.Чтобы найти значение привязки, вы можете перейти к ее определению, и вы поймете, что с тех пор оно никогда не меняло значения.

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

    fun factorial 0 = 1
      | factorial n = n * factorial (n - 1)
    

    Здесь n - это значение привязки и переменная в математическом смысле, но не изменяемая ссылка .

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

    Многие функциональные языки программирования не позволяют shadowing .

    Например, вErlang следующее является ошибкой:

    f(X) ->
        A = 5,
        A = 6,
        X + A.
    

    И в Haskell следующее является ошибкой:

    f :: Int -> Int
    f x = x + a
      where
        a = 5
        a = 6
    

SML имеет переменные, но они не меняются .

Верно, это верно для привязок значений , которые наиболее распространены в SML.«Неизменяемые переменные» могут вызвать путаницу, поскольку «переменная» может означать как «изменяемая ссылка», так и «параметр функции».

SML, имеющий как функциональные, так и императивные функции языка, также имеет изменяемые ссылки :

val a = ref 5
fun f x = x + !a
val _ = a := 10
val b = f 1  (* 11, not 6 *)

Здесь ref : 'a -> 'a ref создает ссылку и ! : 'a ref -> 'a разыменовывает ее.

Они так же опасны, как и в других языках;возможно, меньше, потому что вы не будете случайно смешивать 'a и 'a ref, поскольку система типов вызовет ошибку.Синтаксически они немного непрактичны, но это должно служить напоминанием о том, что вам следует опасаться их использования.: -)

0 голосов
/ 20 февраля 2019

Переменные в SML различаются так же, как переменные в математике.То есть в целом они могут обозначать разные ценности в разных обстоятельствах.Например,

fun f x =
  let val a = x + 1 in ... end

Здесь значение a зависит от x.Это первоначальное значение слова «переменная» в математике.

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

Вы можете все еще есть мутация, но в ML это отдельная концепция и более явная.Вам нужно использовать ссылки:

let
  val r = ref 1
in
  f (!r);
  r := 2;
  f (!r)
end

Наконец, ваш пример демонстрирует совершенно другое явление, а именно отслеживание объявлений.Это не является чем-то исключительным для ML, ваша программа похожа на следующую в C:

{
  const int a = 5;
  {
    const int a = a + 1;
  }
}

Единственное реальное отличие состоит в том, что в C используется a в правой частивторое объявление заставляет его рекурсивно ссылаться на (пока не определенную) вторую a, тогда как в объявлениях SML по умолчанию нерекурсивно, так что a справа относится к первому объявлению.

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

...