Я пытаюсь написать процедуру stream-weighted-tuples
, которая принимает процедуру взвешивания и любое количество потоков для создания потока кортежей. Например,
(stream-weighted-tuples
(lambda (t) (+ (car t) (cadr t) (caddr t))
integers
integers
integers)
должен сгенерировать поток (1 1 1) (1 1 2) (1 2 1) (2 1 1) (1 1 3) (1 2 2) (1 3 1) (2 1 2) (2 2 1) (3 1 1) (1 1 4) (1 2 3) ...
.
Меня вдохновил упражнение 3.70 в SICP, которое посвящено написанию процедуры weighted-pairs
, которая принимает два потока и процедуру взвешивания для генерации потока пар в порядке, соответствующем весу. По сути, это обобщение процедуры weighted-pairs
, которая принимает более двух потоков.
Я написал такую версию:
(define (stream-weighted-tuples weight . streams)
(cond ((null? streams)
(error "No streams given -- STREM-WEIGHTED-TUPLES"))
((null? (cdr streams))
(stream-map list (car streams)))
(else
(let ((s (car streams))
(rest (cdr streams)))
(if (stream-null? s)
the-empty-stream ; {} x S = {}
(stream-merge-weighted
weight
(stream-map (lambda (tuple)
(cons (stream-car s) tuple))
(apply stream-weighted-tuples
(lambda (tuple) ; partial weight
(weight (cons (stream-car s)
tuple)))
rest))
(apply stream-weighted-tuples
weight
(stream-cdr s)
rest)))))))
(что явно не работает). Идея заключалась в том, чтобы объединить 1. поток, полученный в результате cons
объединения первого элемента первого потока с каждым элементом (рекурсивно созданного) потока, который состоит из кортежей из остальной части данного потоки и 2. поток, состоящий из кортежей stream-cdr
первого потока и остальных заданных потоков.
Это не работает, потому что создание потока 2 не остановится в случае бесконечного потока (по той же причине pairs
процедура из упражнение 3.68 не работает).
Это stream-merge-weighted
я реализовал:
(define (stream-merge-weighted weight s1 s2)
(cond ((stream-null? s1) s2)
((stream-null? s2) s1)
(else
(let* ((s1car (stream-car s1))
(s2car (stream-car s2))
(s1car-weight (weight s1car))
(s2car-weight (weight s2car)))
(cond ((<= s1car-weight s2car-weight)
(cons-stream
s1car
(stream-merge-weighted weight
(stream-cdr s1)
s2)))
((> s1car-weight s2car-weight)
(cons-stream
s2car
(stream-merge-weighted weight
s1
(stream-cdr s2)))))))))
Есть ли способ рекурсивно построить эту проблему?
РЕДАКТИРОВАТЬ: То, что я имел в виду под «кортежем» в этом вопросе, на самом деле является списком схемы, который семантически представляет кортеж.
Для справки я оставляю свою реализацию потоковых примитивов (которая идентична той, что есть в SICP):
(define-syntax cons-stream
(syntax-rules ()
((_ a b)
(cons a (delay b)))))
(define (stream-car stream)
(car stream))
(define (stream-cdr stream)
(force (cdr stream)))
(define (stream-null? stream)
(null? stream))
(define the-empty-stream '())
(define (stream-map proc s)
(if (stream-null? s)
the-empty-stream
(cons-stream
(proc (stream-car s))
(stream-map proc (stream-cdr s)))))