Аналог диапазона Python в схеме

Как создать список последовательных номеров в схеме?

В Python создать список целых чисел от 1 до 10 будет range(1,11), Есть ли эквивалент для Схемы?

mzscheme --version дает Welcome to Racket v5.2.1.

Изменить: Для /questions/27179278/est-li-u-shemyi-raketki-operatsiya-perechisleniya/27179284#27179284 для реализации функциональности диапазона, этот код необходим:

#lang racket
(require srfi/1)
(iota 5 1)

7 ответов

Решение

Ищите йоту (как определено в SRFI-1).

Пример: (йота 10 1) дает 10 последовательных целых чисел, начиная с 1 (вместо значения по умолчанию 0).

iota не принимает те же аргументы, что и range, но дублирует все функциональные возможности - возрастающие диапазоны, убывающие диапазоны, начиная с 0, если задана только одна граница, возможность указать интервал.

В Racket есть встроенная функция range, которая ведет себя так же, как в Python.

> (range 10)
'(0 1 2 3 4 5 6 7 8 9)

Вот версия, которая делает возрастающий диапазон, если первый номер ниже, или нисходящий диапазон, если он выше:

(define range
  (lambda (n m)
    (cond
      ((= n m) (list n))
        (else (cons n (range ((if (< n m) + -) n 1) m))))))

А вот улучшенная версия, которая может принимать 1 или 2 аргумента; если задан только один, он находится в диапазоне от 0 до заданного числа:

(define range
  (lambda (n . m)
    (let
      ((n (if (null? m) 0 n)) (m (if (null? m) n (car m))))
      (cond
    ((= n m) (list n))
    (else (cons n (range ((if (< n m) + -) n 1) m)))))))

Если нет ничего встроенного, написать свой собственный тривиально:

(define (range first last)
  (if (>= first last)
      '()
      (cons first (range (+ first 1) last))))

Онлайн схема оценки: http://eval.ironscheme.net/?id=71

Я просто поднимаю комментарий @Ankur к ответу. В Racket у вас есть "в диапазоне":

#lang racket

(in-range 7)  ;; produces #<stream>

;; used in a loop:
(for/list ([i (in-range 7)])
  i)
;; produces (list 0 1 2 3 4 5 6)


;; and, for the lazy among us:

(for/list ([i 7])
  i)

;; produces the same

Он также может принимать нижний предел, приращение (включая отрицательное значение) и т. Д.

После комментария Германа Диаго я сделал для этого чисто функциональную ленивую версию (то есть стрим). Он может создать поток диапазона любого размера, который ваша реализация Схемы может обрабатывать в постоянное время, а также получать доступ к текущему элементу и продвигать поток, также в постоянное время.

(define ^range
    (lambda (x y getter)
      (op x y getter)))

(define EOS ; End of stream for finite streams
    (^range '() '() (lambda () EOS)))

(define range 
    (lambda (x . y) ; if y < x then stream is infinite
      (let ((x (if (null? y) 0 x))
            (y (if (null? y) x (car y))))
        (^range x y (lambda ()
                      (if (= x y) EOS 
                       (range (+ x 1) y)))))))

(define get ; Get current element
    (lambda (r)
      (r (lambda (x y g) x))))

(define next ; Get stream for next element
    (lambda (r)
      (r (lambda (x y g) (g)))))

Используя этот код:

> (define r (range 1 3))
> (get r)
1
> (get (next r))
2
> (get (next (next r)))
3
> (get (next (next (next r)))) ; EOS
()

Не найдя того, что я хотел, и не желая использовать внешний пакет, я закончил тем, что написал свою собственную версию, которая отличается от версии python (надеюсь, улучшится). Если вы думаете, что это действительно неэффективно и может улучшить это, пожалуйста, сделайте.

;; A version of range taking the form (range [[first] last [[step]]] ).
;; It takes negative numbers and corrects STEP to the same direction
;; as FIRST to LAST then returns a list starting from FIRST and
;; ending before LAST
(define (range . args)
  (case (length args)
   ( (0) '())
   ( (1) (range 0 (car args) (if (negative? (car args)) -1 1)))
   ( (2) (range (car args) (cadr args)
             (if (>= (car args) (cadr args)) -1 1)))
   ( (3) (let* ((start (car args)) (end (cadr args)) 
                (step (if (> start end)
                          (- (abs (caddr args))) 
                          (abs (caddr args)))))
            (let loop ((x start) (xs '()))
               (cond ((and (>= end start) (<= (abs end) (abs x)))
                      (reverse xs))
                     ((and (<= end start) (>= (abs end) (abs x)))
                      (reverse xs))
                     (else (loop (+ x step) (cons x xs)))))))
   (else (error 'range "too many arguments"))))
;  (else (display "ERROR: range too many arguments") (newline)))) ;;r4rs

;; (range-inc [[first] last [[step]]] ) includes LAST in the returned range
(define (range-inc . args)
  (case (length args)
    ( (0) '())
    ( (1) (append (range (car args)) args))
    ( (2) (append (range (car args) (cadr args)) (cdr args)))
    ( (3) (append (range (car args) (cadr args) (caddr args))
                  (list (cadr args))))
    (else (error 'range "too many  arguments"))))
;   (else (display "ERROR: range too many arguments") (newline)))) ;;r4rs

Обратите внимание, что я также написал общую версию для lisp

Другие вопросы по тегам