3

New to scheme here and I'm having some trouble learning do loops. I am attempting to make a function that will take in an object and a vector, and then iterate through the vector until it find that object. When the object is found, it would then return a list containing all of the items in the vector before the object. My code is below. All it will return is how many iterations the do loop went through, instead of the list I want it to. If anyone could help me with the syntax, I would greatly appreciate it. Thanks! ( ideally this would return (1 2))

    (define(vector-test-iterative X Vector)    
      (do ((i 0 (+ i 1))) (< i (vector-length Vector))
          (if (eqv? X (vector-ref Vector i))
              (= i (vector-length Vector))
              (cons (vector-ref Vector i) (ls '())))
          ls))


(vector-test-iterative '4 #(1 2 4 3 5))
YasirA
  • 9,531
  • 2
  • 40
  • 61
cliff259
  • 114
  • 2
  • 9
  • In Scheme, parens don't go on their own line. The indentation should be enough to set apart code blocks. – erjiang Nov 12 '10 at 00:20

2 Answers2

4

If you're using Racket, then there's no need to use do, which was never popular among schemers anyway. There's a whole range of iterators -- look for for in the docs, and things that start with for. For example, your code boils down to

#lang racket
(define (values-before x vector)
  (for/list ([y (stop-before (in-vector vector)
                             (lambda (y) (eqv? x y)))])
    y))

(If you really want to use do, then you're missing a pair of parens around the test, and you should add a binding for the accumulator.)

Eli Barzilay
  • 29,301
  • 3
  • 67
  • 110
  • thanks for the answer. what I want to do is store in a list all of the values that appear in the vector before some other value does. So if my vector is 1 2 3 4 and I pass in 4, I want the function to return 1 2 3. I tried running your code and received an error that "for/list" was a reference to an undefined identifier by the way. but I will definitely look into for loops. – cliff259 Nov 11 '10 at 04:33
  • So my initial guess about what you're trying to do was wrong -- I revised it to match what you want now. As for the error, you should be using the "determine language from source" language, and make sure that you have the "`#lang racket`" at the top. (And hopefully you're using a recent version.) – Eli Barzilay Nov 11 '10 at 04:41
1

A solution that uses a named loop. Cleaner (in my opinion!) than the do version and should work on any R5RS Scheme:

;; Extracts the sublist of `lst` up to `val`. 
;; If `val` is not found, evaluates to an empty list.
(define (upto val lst)
  (let loop ((res null) (lst lst))
    (cond ((null? lst) null)
          ((eq? val (car lst)) (reverse res))
          (else (loop (cons (car lst) res) (cdr lst))))))

;; Adapts the above procedure to work with vectors.
(define (vector-upto val vec)
  (list->vector (upto val (vector->list vec))))

;; test
(vector-upto 6 #(1 2 3 4 5))
=> #0()
(vector-upto 5 #(1 2 3 4 5))
=> #4(1 2 3 4)
(vector-upto 3 #(1 2 3 4 5))
=> #2(1 2)
(vector-upto 1 #(1 2 3 4 5))
=> #0()
Vijay Mathew
  • 26,737
  • 4
  • 62
  • 93
  • 1
    I am not sure that this solution (using alternative `let` syntax) is clearer than a `do`, if there is a side effect before each call of the body. But I think this is a matter of personal preference. However +1 for your suggestion. – Benoît Fraikin Aug 08 '11 at 19:33