Сделать итеративный цикл в схеме

Новичок в схеме здесь, и у меня возникли проблемы с изучением циклов. Я пытаюсь создать функцию, которая будет принимать объект и вектор, а затем перебирать вектор, пока не найдет этот объект. Когда объект будет найден, он вернет список, содержащий все элементы в векторе перед объектом. Мой код ниже. Все, что он вернет, это количество итераций, которые прошел цикл do, а не список, который я хочу. Если кто-нибудь может помочь мне с синтаксисом, я был бы очень признателен. Спасибо! (в идеале это вернет (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))

person cliff259    schedule 11.11.2010    source источник
comment
В Схеме скобки не идут по своей линии. Отступа должно быть достаточно, чтобы отделить блоки кода.   -  person erjiang    schedule 12.11.2010


Ответы (2)


Если вы используете Racket, то нет необходимости использовать do, который в любом случае никогда не был популярен среди мошенников. Существует целый ряд итераторов — ищите for в документации и все, что начинается с for. Например, ваш код сводится к

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

(Если вы действительно хотите использовать do, то вам не хватает пары скобок вокруг теста, и вам следует добавить привязку для аккумулятора.)

person Eli Barzilay    schedule 11.11.2010
comment
Спасибо за ответ. то, что я хочу сделать, это сохранить в списке все значения, которые появляются в векторе, прежде чем какое-либо другое значение. Итак, если мой вектор равен 1 2 3 4, и я передаю 4, я хочу, чтобы функция возвращала 1 2 3. Я попытался запустить ваш код и получил ошибку, что for/list кстати был ссылкой на неопределенный идентификатор. но я обязательно посмотрю на циклы. - person cliff259; 11.11.2010
comment
Итак, мое первоначальное предположение о том, что вы пытаетесь сделать, было неверным - я изменил его, чтобы оно соответствовало тому, что вы хотите сейчас. Что касается ошибки, вы должны использовать язык определения из исходного языка и убедитесь, что у вас есть #lang racket вверху. (И, надеюсь, вы используете последнюю версию.) - person Eli Barzilay; 11.11.2010

Решение, использующее именованный цикл. Более чистый (на мой взгляд!), чем версия do, и должен работать на любой схеме R5RS:

;; 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()
person Vijay Mathew    schedule 11.11.2010
comment
Я не уверен, что это решение (с использованием альтернативного синтаксиса let) понятнее, чем do, если перед каждым вызовом тела возникает побочный эффект. Но я думаю, что это вопрос личных предпочтений. Однако +1 за ваше предложение. - person Benoît Fraikin; 08.08.2011