Сравните два списка и верните false, если они не равны схеме - PullRequest
0 голосов
/ 30 декабря 2018

Я хотел бы попросить вас о помощи, чтобы завершить приведенный ниже код условием, которое проверяет, не совпадают ли списки ws и vs.Если они не равны, верните текст false(#f), иначе обработайте код ниже.Я смотрел с выполнением переменных len1 и len2, которые считали длину обоих списков.Когда я запускаю его, я получаю эту ошибку: lambda: no expression after a sequence of internal definitions in: lambda Что я делаю не так?

(define (weighted-sum . ws)
  (define (sub . vs)
    (let ((len1 (length ws)) (len2 (length vs)))
    (if (not (equal? (len1 len2) '#f))
    (foldl
     (lambda (i j res) (+ res (* i j)))
     0
     ws vs)))
   sub)

Спасибо за помощь.

Ответы [ 2 ]

0 голосов
/ 31 декабря 2018

Стереть )) после #f.Добавьте )) после len1 len2), и оно будет работать.(не совсем, но близко (*) )

#f самооценка, вам не нужно его цитировать.Сделайте отступ в форме (foldl ...), которая стала частью выражения if.

Наконец, (if (not A) #f B) - это то же самое, что (if A B #f) - это то же самое, что и (and A B).

Вы правильно убедились, что длины обоих списков,переносимый (sic) и ожидаемый, равны.Я не понимаю, почему списки сами должны быть равными.Насколько я могу судить, они не должны этого делать.

(weighted-sum list-of-weights) создает процедуру, ожидающую, что список чисел вычислит свою взвешенную сумму с использованием ранее предоставленных весов.


(*) Исправленный код после нескольких исправлений:

(define (weighted-sum . ws)
  (define (sub . vs)
    (let ((len1 (length ws)) (len2 (length vs)))
      (and (equal? len1 len2)
        (foldl
          (lambda (i j res) (+ res (* i j)))
          0
          ws vs))))
   sub)

Настоятельно рекомендуется установить, например, Racket и использовать его редактор для просмотра и исправления несоответствия скобок и т. Д.

0 голосов
/ 31 декабря 2018

length почти всегда является антишаблоном в схеме.

length - это O (n) операция, которая вызывается дважды, затем вы вызываете другую O (n) операция, foldl, приводящая к процессу O (3n) для weighted-sum - далеко от идеального минимума O (n) .foldl является хорошим кандидатом для многих линейных вычислений, но из-за требования согласования длины вы создали небольшую ситуацию с квадратным колышком в круглой дыре.

Использованиес именами - let и match*, мы записываем weighted-sum в виде O (n) вычислений -

#lang racket

(define ((weighted-sum . ws) . vs) ;; curried form syntactic sugar 
  (let loop ((acc 0)
             (ws ws)
             (vs vs))
    (match* (ws vs)
      ;; both lists have at least one value
      [((list w ws ...) (list v vs ...))
       (loop (+ acc (* w v))
             ws
             vs)]
      ;; both lists are empty
      [((list) (list))
       acc]
      ;; any other case
      [(_ _)
       #f])))

Конечно match* довольно симпатичный макрос, поэтомуЯ покажу вам, как переписать weighted-sum, используя простое выражение cond.Подготовьте свои логические рассуждения: порядок условий очень важен -

(define ((weighted-sum . ws) . vs)
  (let loop ((acc 0)
             (ws ws)
             (vs vs))
    (cond
      ;; both lists are empty
      [(and (null? ws)
            (null? vs))
       acc]
      ;; at least one list is empty
      [(or (null? ws)
           (null? vs))
       #f]
      ;; inductive: both lists have at least one value
      [else
       (loop (+ acc (* (car ws)
                       (car vs)))
             (cdr ws)
             (cdr vs))])))

Обе программы имеют одинаковый вывод -

((weighted-sum 1 2 3) 1 2 3)
;; 14

((weighted-sum 1 2 3) 1 2)
;; #f

((weighted-sum 1 2) 1 2 3)
;; #f

((weighted-sum))
;; 0
...