behavior differently with two input lists with same length vs. with different lengths (Scheme)

StackOverflow https://stackoverflow.com/questions/23681219

  •  23-07-2023
  •  | 
  •  

Domanda

the code "tsFunc" gets two lists as input and it will pairs each elements from two lists. It works most of cases. but then I find a bit strange behavior when I give 2 equal length of lists (e.g. '(1 2) '(3 4).... or '(a b c) '(1 2 3).... , it works strangely. first, here are code.

[problem 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 '()))

the behavior like this:

1) correct behavior with uneven length of lists : (tsFunc '(1 2 3) '(a b)) ====> output: ((1 . a) (2 . b))

2) strange behavior with even length of lists : (tsFunc '(1 2 3) '(a b c)) ===> output (wrong): ((3 . c) (2 . b) (1 . a)) ===> expected : ((1 . a) (2 . b) (3 . c))

when the two input lists are same length, what is happening? do the tsFunc logic have different behavior between the input lists with same lengths vs. the input lists with different lengths? (Note. as I know, the code needs to have "reverse" for the final result. so it is not because of "reverse" in the code)

[problem 2] with the result of tsFunc => tsFunc result: (1 . 2) (3 . 4) => try to implement product like this (1*2)+(3*4) = 14, so I have like this..

(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 ??

line 3 , 4 ok..that's the logic what to do, then, how to call tsFunc result to use it as input and.. two lists for the last line.. unclear..

È stato utile?

Soluzione

The first problem is that you keep reversing the lists at each iteration, if you really need to reverse the output, do it just once at the end:

(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 '()))

Now, for the second problem - the code doesn't even compile: you're not correctly calling the tsFunc procedure, and you're calling it in the wrong point. Also the initial value for the accumulator parameter is wrong - you can't use a list if you intend to return a number:

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

Using the sample input in the question, here's how it would work:

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

In the above tsFunc takes '(1 3) and '(2 4) as inputs, transforming them into '((1 . 2) (3 . 4)) and then foldl preforms the operation (1*2)+(3*4) = 14, as expected.

Altri suggerimenti

Since you are allowed to use higher order functions, why not use just SRFI-1 List library 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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top