#functional-programming #sml
#функциональное программирование #sml
Вопрос:
я изучаю язык программирования Standard ML, и мне интересно, как я могу выполнить повторение списка с условием проверки.
В других языках у нас есть циклы for, подобные :
var input;
for(var i = 0; i < arr.length; i ) {
if(arr[i] == input) {
//you have arrived at your condition...
} else {
//other case
}
}
например
я хочу выполнить итерацию по списку и проверить, соответствует ли входная переменная существующему элементу в списке.
i = 5
xs = [1,5,2,3,6] --> the element matches after one iteration.
fun check i nil = []
| check i (x::xs) = if i=x
then //dowork
else //iterate;
Я просмотрел множество документов о том, как это реализовать, но безуспешно.
Было бы действительно полезно, если бы кто-нибудь мог дать мне некоторые объяснения относительно того, как я могу использовать let val A in B end;
внутри или вне условий if для такого рода работы.
Ответ №1:
как я могу выполнить повторение списка с условием проверки
fun check i nil = [] | check i (x::xs) = if i=x then //dowork else //iterate;
я хочу выполнить итерацию по списку и проверить, соответствует ли входная переменная существующему элементу в списке.
Я бы назвал это комбинатором предикатов. Он уже существует в стандартной библиотеке и вызывается List.exists
. Но вы также можете создать это самостоятельно:
fun exists p [] = false
| exists p (x::xs) = p x orelse exists p xs
Это упрощение процедуры if-then-else, которую вы пытаетесь выполнить, которая будет выглядеть следующим образом:
fun exists p [] = false
| exists p (x::xs) = if p x then true else exists p xs
If-then-else на самом деле не является необходимым, когда тип результата является логическим, поскольку orelse
, andalso
и not
имеют короткое замыкание (не будут оценивать их второй операнд, если результат может быть определен с помощью первого).
Используя эту List.exists
функцию для проверки, содержит ли список определенный элемент, вы должны создать p
, который сравнивает элемент списка с некоторым заданным значением, например:
fun check y xs = List.exists (fn x => ...) xs
Это может показаться немного сложнее, чем просто писать check
рекурсивно с нуля,
fun check y [] = false
| check y (x::xs) = ... orelse check y xs
но решение, использующее функции более высокого порядка, предпочтительнее по нескольким причинам.
Один из них заключается в том, что опытный читатель быстро обнаружит, что вы делаете, когда увидите List.exists
: Ах, вы просматриваете список в поисках элемента, заданного предикатом. Принимая во внимание, что если ваша функция явно рекурсивна, читателю придется прочитать всю схему рекурсии: ОК, функция не делает ничего необычного, о чем я бы знал, если бы видел, например List.exists
.