Я вижу, что вы задаете три вопроса.
Могу ли я использовать несколько объявлений val в let?
Да. Вы уже делаете это массово.
Is let/val/in [/ end] б/у в картинке сопоставив?
Я не совсем уверен, что вы имеете в виду, поэтому я постараюсь ответить на все вопросы, которые, я думаю, вы можете просить.
Во-первых, let-bindings Позволяет временно привязать результат вычисления или значения к имени. Это полезно, если вам нужно использовать результат несколько раз, а вычисление стоит дорого или требует побочных эффектов, которые вы не хотите повторять. Но они также могут сделать код более читаемым (поскольку имя может добавить значение). Соответствие шаблону позволяет обрабатывать несколько случаев разных входов в каждом конкретном случае. Вы можете соответствовать произвольной глубине, и компилятор часто сможет определить, отсутствуют ли у вас какие-либо шаблоны.
Так что, если вы просите если LET-привязки используются в соответствии модели, ответ да, по крайней мере в следующих смыслах:
Подобно тому, как позволить связываниям временно связывает вычисление или значение для имени, то же самое происходит, когда у вас есть шаблон переменной в вашем шаблоне. Например.
let val (a, b, c) = f (x, y) in ... end
эквивалентно
(case f (x, y) of
(a, b, c) => ...)
с , б и с являются образцы, которые всегда соответствуют и привязаны к некоторому значению в ...
.
Вы можете позволить-привязки и случая-в с внутри других выпускаемых креплений или регистра в с, например,
let val result =
(case f (i, j) of
SOME (x, y) => let val (a, b, c) = (g x, g y, g (x + y))
in
...
end
| NONE => ...)
in ... end
, но эти примеры часто могут быть упрощены.
И если вы спрашиваете , если соответствующий шаблон используются в LET-привязок, ответ да, есть на самом деле немного сопоставления с образцом происходит при создании подведенного связывания; например в
let
val (s1, d1, d2) = (pass_cout(pass_cin h cin) cout,
#2 (find2digits((pass_cout(pass_cin h cin) cout))),
#2 (find2digits((pass_cout(pass_cin h cin) cout))))
in ... end
val (s1, d1, d2) = ...
связывание использует сопоставление с образцом на 3-кортежа. Совместимость шаблонов в let-bindings составляет только. Хороший выбор при работе с Типы продуктов и никогда с суммы типов. См What are "sums-and-products" data structures? - то есть, никогда не
val SOME x = f x
, потому что она взорвется момент f x
является NONE
. Корпус лучше подходит для большего диапазона шаблонов, чем let-in-end, тогда как let-in-end лучше подходит для выполнения последовательного диапазона заданий, например.
fun solve2 (a : real, b : real, c : real) =
let val discr = b * b - 4.0*a*c
val sqr = Math.sqrt discr
val denom = 2.0 * a
in ((~b + sqr)/denom,
(~b - sqr)/denom) end
Почему моя программа дает мне «оператор не является функцией» ошибка?
Как говорит Джон, это трудно понять, потому что код, который вы написали будет работать лишь при наличии значимых определений для значений pass_cout
, pass_cin
, find2digits
, last_element
, produce_cin
и produce_cout
. Способ передачи сообщения об ошибке не указывает на то, что кажется проблемой, и код, который вы пишете, не может быть запущен для полного воспроизведения сообщения об ошибке. Если бы у меня были значимые значения для них, кажется, что есть другие проблемы с этим кодом, где типы не объединяются.
Поскольку ваш код не ретранслировать свои собственные намерения (с родовыми именами, как action
, s1
, d2
и т.д.), я также не могу рекомендовать лучший способ, чтобы написать это, потому что я понятия не имею, что он должен делать, так вот некоторые общие рекомендации по стилю кодирования:
Использование LET-привязок, чтобы избежать вызова функций, таких как find2digits
дважды, например, подобный
let
val (d1, d2) = find2digits ...
val s1 = pass_cout ...
in
...
end
Разделите свои линии должным образом, например. как
if neo_in < 2 andalso neo_out < 2
then (d1::action(neo_in,neo_out,cut (first::t)),
d2::action(neo_in,neo_out,cut (first::t)))
else ([],[])
и даже лучше, как
if neo_in < 2 andalso neo_out < 2
then let
val wat = action (neo_in, neo_out, cut (first::t))
in
(d1::wat, d2::wat)
end
else ([], [])
где wat
заменяется какой-то значимое имя, описывающее, что это такое.
Choose good variable names!
Ваш код содержит несколько ссылок на функции, которые не определены (например, '' find2digits' и pass_cout'), так что трудно сказать что-либо значимое, тем более, что ваши намерения кажутся неясными. Что ты пытаешься сделать? Я скажу это, хотя - когда у вас есть несколько связок 'val' внутри' let', они должны быть разделены точками с запятой, а не с символами новой строки. –
@JohnColeman: точки с запятой между объявлениями являются необязательными, а также внутри let-bindings. Несколько связанный оператор с запятой между выражениями (единственные действительно полезные точки с запятой в SML) требует скобок вокруг них, например. '(f x; ...; g y)' кроме внутренних let-bindings: 'let ... in f x; ...; g y end'. Это делается для того, чтобы устранить его с помощью менее полезной точки с запятой между декларациями. Поскольку не может быть декларации непосредственно внутри 'let ... in' и' end' (если не введена внутренняя let-binding), скобки могут быть опущены там. –
@SimonShine Вы, конечно, правы. Я знал это, но временно забыл об этом. Я проверил в Ульмане, но он один из тех авторов, который часто использует точки с запятой. –