поведение по-разному с двумя входными списками одинаковой длины и с разной длиной (схема)

код «tsFunc» получает два списка в качестве входных данных, и он будет соединять каждый элемент из двух списков. Это работает в большинстве случаев. но затем я нахожу немного странное поведение, когда я даю 2 равной длины списков (например, '(1 2)' (3 4).... или '(a b c)' (1 2 3)...., это работает странно... во-первых, вот код.

[проблема 1]

(define (tsFunc lst1 lst2)
 (define (helper ls1 ls2 rst)  
  (reverse (if (or (null? ls1) (null? ls2))                          
      rst                                                   
      (helper (cdr ls1) (cdr ls2)               
                (cons (cons (car ls1) (car ls2)) rst)))))
(helper lst1 lst2 '()))

такое поведение:

1) правильное поведение с неравной длиной списков: (tsFunc '(1 2 3) '(a b)) ====> output: ((1 .a) (2 .b))

2) странное поведение с четной длиной списков: (tsFunc '(1 2 3) '(a b c)) ===> вывод (неправильный): ((3 . c) (2 . b) (1 . a)) = ==> ожидается : ((1.a) (2.b) (3.c))

когда два входных списка имеют одинаковую длину, что происходит? имеет ли логика tsFunc различное поведение между входными списками одинаковой длины и входными списками разной длины? (Примечание. Насколько я знаю, код должен иметь «обратный» для конечного результата, так что это не из-за «обратного» в коде)

[проблема 2] с результатом tsFunc => tsFunc result: (1. 2) (3. 4) => попробуйте реализовать такой продукт (1*2)+(3*4) = 14, поэтому мне нравится это..

(define (func l1 l2)
 (tsFunc (l1 l2)                              ;; line 2 - how to call tsFunc's result??
  (foldl (lambda (acc pair)                   ;; line 3
       (+ acc (* (car pair) (cdr pair))))     ;; line 4
     '()
     l1 l2)))                                 ;; like this?? or ??

строка 3, 4 ок.. это логика, что делать, тогда как вызвать результат tsFunc, чтобы использовать его в качестве входных данных и.. два списка для последней строки.. непонятно..


person user1915570    schedule 15.05.2014    source источник
comment
Кажется, что ты каждый раз переворачиваешься. Просто поменяйте местами, когда будете готовы вернуть аккумулятор.   -  person ggovan    schedule 15.05.2014


Ответы (2)


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

(define (tsFunc lst1 lst2)
  (define (helper ls1 ls2 rst)
    (if (or (null? ls1) (null? ls2))
        (reverse rst)
        (helper (cdr ls1) (cdr ls2)
                (cons (cons (car ls1) (car ls2)) rst))))
  (helper lst1 lst2 '()))

Теперь о второй проблеме — код даже не компилируется: вы неправильно вызываете процедуру tsFunc и вызываете ее не в том месте. Также неверно начальное значение параметра аккумулятора — вы не можете использовать список, если хотите вернуть число:

(define (func l1 l2)
  (foldl (lambda (acc pair)
           (+ acc (* (car pair) (cdr pair))))
         0
         (tsFunc l1 l2)))

Используя образец ввода в вопросе, вот как это будет работать:

(func '(1 3) '(2 4))
=> 14

В приведенном выше примере tsFunc принимает '(1 3) и '(2 4) в качестве входных данных, преобразуя их в '((1 . 2) (3 . 4)), а затем foldl выполняет операцию (1*2)+(3*4) = 14, как и ожидалось.

person Óscar López    schedule 15.05.2014
comment
да ты прав. это была вторая проблема, из-за которой я действительно понятия не имел, как вызвать tsFunc. Однажды я вижу ваше предложение (ну, это так просто), и теперь я понимаю, что ввод fold всегда в конце... - person user1915570; 15.05.2014

Поскольку вам разрешено использовать функции более высокого порядка, почему бы не использовать просто библиотеку списков SRFI-1. fold?

#!r6rs

(import (rnrs base)
        (only (srfi :1) fold)) ;; srfi-1 fold stop at the shortest list 

(define (func lst1 lst2)
  (fold (lambda (x y acc)
          (+ acc (* x y)))
        0
        lst1
        lst2))


(func '(1 3) '(2 4 8)) ; ==> 14
person Sylwester    schedule 15.05.2014