Кодирование длины цикла списка в схеме (R5RS)

(изображение сведений о вопросе -- описывает кодирование RLE)

Часть кода (if ((equal? (car coins) (cadr coins))) в моей функции rle не работает, и функция перестает работать.

 (define (element-index  lst element)
  (let loop ((counter 1) (temp lst))
    (if (= element (car temp))
        counter
        (loop (+ counter 1) (cdr temp)))))

 (define (rle coins)
   (cond ((null? coins) '()))
      (if ((equal? (car coins) (cadr coins)))
          (rle (cdr coins))
           (append '( cons (element-index (coins) (car coins)) (car coins))
                   '( cons (rle (cdr coins))))))

person NSK511    schedule 31.10.2020    source источник


Ответы (1)


Я не собираюсь отвечать, как решить проблему кодирования длин серий, но основную проблему синтаксиса.

Резюме: во многих языках программирования и часто в математической нотации круглые скобки служат для управления порядком операций и часто являются более или менее необязательными. Так, например, 1 + 2 * 3, вероятно, означает «умножить 2 на 3, затем добавить 1 к результату», а (1 + 2) * 3 означает «добавить 1 и 2, а затем умножить результат на 3». Но 1 + (2 * 3) означает то же, что и 1 + 2 * 3, что означает то же самое, что и (((1 + (2 * 3)))).

Это не относится к языкам семейства Scheme или Lisp, никогда. В этих языках круглые скобки являются частью синтаксиса языка и никогда не являются необязательными: они либо должны быть, либо их не должно быть.

Так, в частности, упрощенная версия синтаксиса выражения в Scheme может быть такой: выражение либо

  • какая-то атомарная вещь вроде ссылки на переменную;
  • форма вида (op ...), где op — некоторый оператор.

Во втором случае скобки необязательны: они являются частью синтаксиса языка. И, в частности, если вы рассматриваете такое выражение, как

((foo ...))

то это соответствует второму случаю, где op теперь равно (foo ...) в целом (и нет аргументов), а это, в свою очередь, снова соответствует второму случаю, где op равно foo. Итак, это выражение, оператором которого является другое выражение, а оператором этого выражения является foo: это не выражение, заключенное в некоторые необязательные круглые скобки, и, в частности, это не тот случай, когда ((foo ...)) совпадает с (foo ...).

Итак, синтаксис if таков: (if выражение последовательное альтернативное). Что ж, давайте посмотрим на ваш if:

(if ((equal? (car coins) (cadr coins)))
    ...
    ...)

Таким образом, выражение здесь равно ((equal? (car coins) (cadr coins))). Что ж, это соответствует случаю (op ...), где op равно (equal? (car coins) (cadr coins)), а это, в свою очередь, соответствует этому случаю, поэтому он оценит это, чтобы вернуть либо #t, либо #f. Таким образом, выражение такое же, как (#t) или (#f). А #t или #f — это булевы значения: их нельзя вызывать как функции.

И это как минимум одна из ошибок в вашем коде. Есть и другие, но это кажется самым важным, так как это также ошибка, которую вы допустили в комментарии к другому ответу.

Подводя итог: круглые скобки никогда не являются необязательными в Scheme: они либо обязательны, либо запрещены синтаксисом языка.


Другими словами, в «традиционном языке в стиле Алгола» круглые скобки обычно служат двум целям:

  • они служат важными и обязательными частями синтаксиса, обычно для аргументов функций, как f(x, ...), но иногда также и для других синтаксических целей, как, например, if (...) ... в C;
  • они служат для группировки выражений, чтобы управлять порядком вычислений, где они иногда необходимы, но часто необязательны.

В языках семейства Лисп существует только первая цель.

person Community    schedule 31.10.2020
comment
или, короче говоря, что op(a, ...) в JS, то (op a ...) в Lisp. поэтому ((op ...)) в Lisp — это op(...)() в JS. - person Will Ness; 31.10.2020
comment
@WillNess: да, но критически то, что было бы (op(a, ...)) в JS, даже невозможно (или когда-либо было необходимо) в Lisp (ну, (begin (op a)) возможно, но не совсем, потому что это больше похоже на то, что было бы {op(a, ...)}, если бы JS был языком выражений). Смотрите редактирование в конце. - person ; 31.10.2020