#scheme #racket
#схема #ракетка
Вопрос:
Я пытаюсь определить функцию точечного продвижения, которая принимает два списка в качестве параметров и применяет версию точечного произведения, принимая x1 * y1 x2 * y2 и так далее. Я заставил его работать с пустым списком, но это все. Спасибо.
(define (dot-prod l1 l2)
(cond ((or (null? l1)(null? l2)) '())
(else
(cons (* (car l1) (car l2))
(* (cdr l1) (cdr l2))))))
Ответ №1:
Это идеально подходит для использования встроенных процедур. Предполагая, что списки имеют одинаковую длину:
(define (dot-prod l1 l2)
(apply (map * l1 l2)))
Но если вы хотите написать решение с нуля, вы должны:
- Возвращает значение, которое имеет смысл для базового варианта — если это дополнение, мы хотим, чтобы там был ноль, а не пустой список, мы не создаем новый список в качестве выходных данных
- Вызовите
dot-prod
процедуру на рекурсивном шаге, о чем вы полностью забыли - Объедините результат осмысленно — опять же, если мы выполняем сложение, мы хотим использовать
cons
Это то, что я имею в виду:
(define (dot-prod l1 l2)
(cond ((null? l1) 0)
(else
( (* (car l1) (car l2))
(dot-prod (cdr l1) (cdr l2))))))
В любом случае, это работает так, как ожидалось:
(dot-prod '(1 2 3) '(4 5 6))
=> 32
Комментарии:
1. Я бы сказал, что это
(foldl (map * l1 l2))
лучше, чем использоватьapply
здесь.2. Я думаю, что foldl нужны три параметра.
Ответ №2:
цикл ‘for / sum’ может быть использован здесь для простой понятной функции. Если l и k — это 2 списка:
(define (dotproduct l k)
(for/sum ((i l)(j k))
(* i j)))
Тестирование:
(dotproduct '(1 2 3) '(4 5 6))
; =>32
Это также может быть изменено, если значения (x y) представлены в виде списка списков:
(define (f l)
(for/sum ((i l))
(apply * i)))
(f '((1 4)(2 5)(3 6)))
; => 32
Метод также может быть расширен, если необходимо вычислить x, y, z или даже больше значений.