From: Tamas Papp
Subject: iterate: how to enforce that lists are of the same length?
Date: 
Message-ID: <87myycnya1.fsf@pu100877.student.princeton.edu>
Hi,

I have two lists, (a0 a1 ... an) and (b1 ... bn), and, given a list
(i1 ... in), I want to calculate a0 + a1*i1 + ... + an*in, checking
that 0 <= ij < bj for each 1 <= j <= n.

The solution with iter I came up with looks like

(defun ffa-map-index (index-mapping upper-bounds indexes)
  (let ((sum (car index-mapping)))	; constant term
    (iter
      (for multiplier in (cdr index-mapping))
      (for upper-bound in upper-bounds)
      (for index in indexes)
      (if (and (<= 0 index) (< index upper-bound))
	  (incf sum (* index multiplier))
	  (error "Index ~a is not in [0,~a)" index upper-bound)))
    sum))

which works, except if the user supplies an indexes that is shorter
than upper-bounds or (cdr index-mapping).  I would like to signal an
error in this case, but iterate just terminates if either of the lists
run out.  I tried generators, but they behave the same...

Before rewriting the whole thing using do, I wanted to ask if there is
a solution.

Thanks,

Tamas

From: Pillsy
Subject: Re: iterate: how to enforce that lists are of the same length?
Date: 
Message-ID: <1183574743.468078.157730@c77g2000hse.googlegroups.com>
On Jul 4, 8:33 am, Tamas Papp <······@gmail.com> wrote:
[...]
> Before rewriting the whole thing using do, I wanted to ask if there is a solution.

There's one that's a little on the hacky side, but will do the trick.
Instead of using the  driver for a list with INDEXES, just use the
general := driver and pop an element off of it each time, and check
that you didn't get NIL (and thus run off the end of the list). IMO,
this is only worth doing if you really are concerned about efficiency,
though. If it's not, I'd stick in an

(assert (= (1- (length index-mapping)) (length upper-bounds) (length
indexes))

at the beginning. It means traversing each list twice, but I think
it's a lot more perspicuous. Here's the other solution:

(defun ffa-map-index (index-mapping upper-bounds indexes)
  (iter
    (for multiplier  :in (cdr index-mapping))
    (for upper-bound :in upper-bounds)
    (for index := (pop indexes))
    (cond ((null index) (error "Too few indices!"))
	  ((and (<= 0 index) (< index upper-bound))
	   (sum (* index multiplier) :into sum))
	  (t
	   (error "Index ~a is not in [0,~a)" index upper-bound)))
    (finally (return (+ sum (car index-mapping))))))

HTH,
Pillsy
From: Jon Harrop
Subject: Re: iterate: how to enforce that lists are of the same length?
Date: 
Message-ID: <468bf27d$0$8748$ed2619ec@ptn-nntp-reader02.plus.net>
Tamas Papp wrote:
> Before rewriting the whole thing using do, I wanted to ask if there is
> a solution.

Use a tuple and static typing.

-- 
Dr Jon D Harrop, Flying Frog Consultancy
The OCaml Journal
http://www.ffconsultancy.com/products/ocaml_journal/?usenet
From: Thomas A. Russ
Subject: Re: iterate: how to enforce that lists are of the same length?
Date: 
Message-ID: <ymiabuapsxq.fsf@sevak.isi.edu>
Tamas Papp <······@gmail.com> writes:

> Hi,
> 
> I have two lists, (a0 a1 ... an) and (b1 ... bn), and, given a list
> (i1 ... in), I want to calculate a0 + a1*i1 + ... + an*in, checking
> that 0 <= ij < bj for each 1 <= j <= n.
> 
> The solution with iter I came up with looks like
> 
> (defun ffa-map-index (index-mapping upper-bounds indexes)

    (unless (= (length (cdr index-mapping)) 
               (length upper-bounds)
               (length indexes))
       (error "All sequence arguments to FFA-MAP-INDEX must have the same length"))

>   (let ((sum (car index-mapping)))	; constant term
>     (iter
>       (for multiplier in (cdr index-mapping))
>       (for upper-bound in upper-bounds)
>       (for index in indexes)
>       (if (and (<= 0 index) (< index upper-bound))
> 	  (incf sum (* index multiplier))
> 	  (error "Index ~a is not in [0,~a)" index upper-bound)))
>     sum))
> 
> which works, except if the user supplies an indexes that is shorter
> than upper-bounds or (cdr index-mapping).  I would like to signal an
> error in this case, but iterate just terminates if either of the lists
> run out.  I tried generators, but they behave the same...



-- 
Thomas A. Russ,  USC/Information Sciences Institute