Ракетка - вывод содержимого списка - PullRequest
2 голосов
/ 11 ноября 2011

Я определил список (в Racket / Scheme):

(define myList (cons 'data1 (cons 'data2 (cons 'data3 (cons 'data4 empty)))))

или

(list 'data1 'data2 'data3 'data4)

И я хочу написать функцию, которая перебирает список и выводит все значения из списка.

(define (outputListData list)
  (cond 
    [(null? list) list]
    [else (getListData)]))

С помощью какой функции я могу циклически просматривать содержимое списка? Я знаю, что можно использовать first & rest для получения списка данных, но я думаю, что это не правильный путь.

Кстати: есть хороший компактный справочник по ракетке, такой как php.net ? Я нахожу официальные документы по Racket очень запутанными ...

Ответы [ 4 ]

6 голосов
/ 11 ноября 2011

Вы можете использовать цикл for.Пример:

(for ([x (list 1 2 3)])
    (printf "~s -> ~s\n" x (* x x)))

Конечно, есть более функциональные способы сделать это, но этот способ также работает.Возможно, вы захотите взглянуть на учебник, например, Как разрабатывать программы, чтобы сделать рекурсивный подход.Смотри: http://www.ccs.neu.edu/home/matthias/HtDP2e/

3 голосов
/ 11 ноября 2011

Решение dyoo является хорошим и лаконичным в такой Схеме, как Racket, в которую встроены полезные итерационные подпрограммы. Однако, к вашему сведению, ваш 'outputListData' недалеко от стандартного рекурсивного способа сделать это. Вам просто нужно изменить пару строк:

(define (outputListData list)
  (cond 
    [(null? list) #f]             ; actually doesn't really matter what we return
    [else (printf "~s\n" (first list))    ; display the first item ...
          (outputListData (rest list))])) ; and start over with the rest

Поскольку это «императивная» процедура, которая не предназначена для возврата значения, на самом деле не имеет значения, что мы делаем с пустым списком, пока мы прекращаем повторяться (чтобы избежать бесконечного цикла). Если список не пустой, мы выводим первый элемент и начинаем рекурсивно с остальной частью списка.

Кстати, вот еще один способ, которым вы могли бы написать что-то почти идентичное, если бы вам просто нужен был цикл for в середине какой-то другой функции:

(let loop ((l (list 'foo 'bar 'baz 'quux))) ; or put whatever input you need
   (cond ((null? l) #f)
         (else
           (printf "~s\n" (first l))
           (loop (rest l)))))

Один из способов думать об этом «именованном let» заключается в том, что он определяет временную функцию с именем loop, которая работает так же, как outputListData выше. Схема обладает хорошим свойством, заключающимся в том, что она не будет наращивать стек для таких «хвостовых вызовов», как эти, поэтому вы всегда можете написать то, что будет «итеративным» циклом for или while в этом рекурсивном стиле.

Я настоятельно рекомендую Little Schemer Фридмана и Феллайзена для быстрого знакомства с этим стилем написания функций! Я нашел это на странице Дугласа Крокфорда здесь .

2 голосов
/ 11 ноября 2011

Редактировать согласно комментариям: Использовать для каждого

(for-each display myList)

Попробуйте это:

(void (map display myList))

Разбивка:

  • (void x) вызывает игнорирование x вместо возврата в выражение REPL / parent в качестве значения.
  • (map function lst): для списка '(a1 a2 ... an) возвращает список '((function a1) (function a2) ... (function an)).

Таким образом, мы используем map для отображения всех элементов, но, поскольку нас заботит только побочный эффект, а не возвращаемое значение, мы вызываем void в возвращаемом списке.

Официальные документы:

1 голос
/ 21 июля 2013

Я думаю, что решение, которое легче всего понять, это предложить так называемую функцию "списывателя". Именно так мой университет представил рекурсию и списки в Racket. Также большинство книг по Ракетам (то есть «Как разрабатывать программы» или «Царство ракеток») объясняют это так. Это код:

(define my-list (list 'data1 'data2 'data3 'data4)) 

(define (print-list a-list-of-data)
  (when (not (empty? a-list-of-data))
    (print (first a-list-of-data))
    (print-list (rest a-list-of-data))))

Если вы вызовете функцию с примером списка my-list , вы получите следующий вывод:

(print-list my-list)

'data1'data2'data3'data4

Функция выполняет следующие действия: пока данный список не пустой, он захватывает первый элемент этого списка и передает его в функцию print . Затем он говорит себе сделать то же самое с остальной частью списка. (Он вызывает себя в остальной части списка.) Эта вторая часть - то, что они называют рекурсией.

Однако вы можете сократить это, используя функцию под названием map :

(define (print-list a-list-of-data)
  (map print a-list-of-data))

Это в основном говорит о том, что вы хотите, чтобы функция print вызывалась для каждого элемента данного списка. Вывод точно такой же.

Надеюсь, это помогло!

...