smlnj как перебрать значение

Я новичок в функциональном программировании, но у меня есть опыт в императивном программировании, особенно на Java. я хотел бы спросить, как значение повторяется в smlnj, я знаю, что на Java вы можете использовать varName += anyNumber или varName = varName + 1. на smlnj я не знаю, как это сделать, и мое значение var не повторяется здесь образец моего кода. заранее спасибо.

fun number_in_month (dates : (int*int*int) list , month : int) =
    let
      val total = 0;
    in
      let
        fun check(date : (int*int*int) list , m : int) =
            if #2(hd(date)) = m
            then total + 1  (* this is the problem in the code i don't know
                               how to iterate this like "varName += 1" in java *) 
            else check(tl(date),m)     
      in
        check(dates,month)
      end
    end

эта программа проверит, существуют ли введенные даты (в списке) в указанный месяц, и выведет, сколько дат существует в этом месяце.

например: number_in_month ([(год, месяц, день)],monthEntered) number_in_month([(2017,2,1),(2015,2,3),(2012,1,2)],2) выходные данные должны быть 2 потому что первый и второй элемент в списке равен monthEntered.

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

2 ответа

Решение

Эквивалентом обновления изменяемой переменной с помощью итерации является повторное связывание неизменяемого параметра функции с помощью рекурсии. Поэтому вместо "foo() { while (p) { x++; }}" в псевдокоде вы делаете "foo(p,x) { if (p) { foo(p,x+1); } }". Или в SML,

type date = {year : int, month : int, day : int}
fun countMonth month (dates : date list) =
    let fun countMonth' [] count = count
          | countMonth' (d::ds) count =
            if #month d = month
            then countMonth' ds (count+1)
            else countMonth' ds count
    in countMonth' dates 0 end

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

type date = {year : int, month : int, day : int}
fun filterMonth month (dates : date list) =
    List.filter (fn d => #month d = month) dates
fun countMonth month dates =
    List.length (filterMonth month dates)

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

Просто подумайте о проблеме в обратном порядке: «Она должна вернуть 1 в случае совпадения и 0 в противном случае» — это будет означать, что вызов функции внутри себя потенциально вернет 1 дважды, вызов ее 3 раза вернет 1 три раз и т. д. Теперь нужно только сложить все успешные случаи, когда рекурсивный вызов функции фактически возвращает 1. И не беспокойтесь о бесконечной рекурсии, поскольку в противном случае она вернет 0 и приведет к краху дерева рекурсии.

      fun number_in_month(dates: (int * int * int) list, month: int) =
    if null dates
    then 0
    else
        if #2 (hd dates) = month
        then 1 + number_in_month(tl dates, month) (* <--this is where the magic happens *)
        else number_in_month(tl dates, month)
Другие вопросы по тегам