Аналоговый диапазон Python () в Common Lisp

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

Другими словами, что эквивалентно функции range Python в Common Lisp?

В range(2, 10, 2) Python range(2, 10, 2) возвращается [2, 4, 6, 8] , причем первый и последний аргументы являются необязательными. Я не мог найти идиоматический способ создания последовательности чисел, хотя Emacs Lisp имеет number-sequence .

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

Связанный: Аналог диапазона Python в Схеме

  • CL-WHO-подобный HTML-шаблон для других языков?
  • 5 Solutions collect form web for “Аналоговый диапазон Python () в Common Lisp”

    Нет встроенного способа генерации последовательности чисел, канонический способ сделать это состоит в том, чтобы сделать одно из:

    • Использовать loop
    • Напишите функцию утилиты, которая использует loop

    Пример реализации будет (это только принимает подсчет «от низкого» до «высокого»):

     (defun range (max &key (min 0) (step 1)) (loop for n from min below max by step collect n)) 

    Это позволяет указать (необязательное) минимальное значение и (необязательное) значение шага.

    Чтобы создать нечетные числа: (range 10 :min 1 :step 2)

    alexandria реализует схему iota:

     (ql:quickload :alexandria) (alexandria:iota 4 :start 2 :step 2) ;; (2 4 6 8) 

    Вот как я подхожу к проблеме:

     (defun generate (from to &optional (by 1)) #'(lambda (f) (when (< from to) (prog1 (or (funcall f from) t) (incf from by))))) (defmacro with-generator ((var from to &optional (by 1)) &body body) (let ((generator (gensym))) `(loop with ,generator = (generate ,from ,to ,by) while (funcall ,generator #'(lambda (,var) ,@body))))) (with-generator (i 1 10) (format t "~&i = ~s" i)) 

    Но это всего лишь общая идея, есть много возможностей для улучшения.


    Хорошо, потому что, похоже, здесь обсуждается. Я предположил, что действительно нужен аналог функции генератора range Python. Который в определенном смысле генерирует список чисел, но делает это так, уступая число каждой итерации (чтобы он не создавал больше одного элемента за раз). Генераторы представляют собой несколько редкую концепцию (несколько языков ее реализуют), поэтому я предположил, что упоминание о Python предполагает, что эта точная функция желательна.

    Следуя некоторой критике моего примера выше, вот другой пример, который иллюстрирует причину того, почему генератор может использоваться, а не простой цикл.

     (defun generate (from to &optional (by 1)) #'(lambda () (when (< from to) (prog1 from (incf from by))))) (defmacro with-generator ((var generator &optional (exit-condition t)) &body body) (let ((g (gensym))) `(do ((,g ,generator)) (nil) (let ((,var (funcall ,g))) (when (or (null ,var) ,exit-condition) (return ,g)) ,@body)))) (let ((gen (with-generator (i (generate 1 10) (> i 4)) (format t "~&i = ~s" i)))) (format t "~&in the middle") (with-generator (j gen (> j 7)) (format t "~&j = ~s" j))) ;; i = 1 ;; i = 2 ;; i = 3 ;; i = 4 ;; in the middle ;; j = 6 ;; j = 7 

    Это опять же является лишь иллюстрацией цели этой функции. Вероятно, расточительно использовать его для генерации целых чисел, даже если вам нужно сделать это в два этапа, но генераторы лучше всего подходят для парсеров, когда вы хотите получить более сложный объект, построенный на основе предыдущего состояния анализатора, например, и множество других вещей. Ну, вы можете прочитать аргумент об этом здесь: http://en.wikipedia.org/wiki/Generator_%28computer_programming%29

    Использование рекурсии:

     (defun range (min max &optional (step 1)) (when (<= min max) (cons min (range (+ min step) max step)))) 

    В простой форме, указывающей start, stop, step:

     (defun range (start stop step) (do ( (i start (+ i step)) (acc '() (push i acc))) ((>= i stop) (nreverse acc)))) 
    Python - лучший язык программирования в мире.