как игнорировать внутренние списки в схеме?

Я написал процедуру, которая получает каждое значение из списка и возвращает список, в котором каждое значение равно -1 (например)

(define (Set-list a val)
  (if ( null? a) (list)
    (append (list val) (Set-list (cdr a) val))
))

(Set-list '(2 3 4) -1) //returns '(-1 -1 -1)
(Set-list '(A(2 3) B(2 3) C(2 3)) -1) // returns '(-1 -1 -1 -1 -1 -1)

как мне заставить его вернуть -1 -1 -1? Я не хочу получать внутренних членов списка?


person Ivan Prodanov    schedule 13.01.2013    source источник
comment
Просто чтобы убедиться, что вы понимаете свой пример: вы думаете, что A(2 3) - это единственный внешний элемент с некоторыми элементами внутри? (На самом деле это два внешних элемента, символ A и список (2 3). Вы хотите пропустить элементы, которые сами по себе являются списками?)   -  person Anton Kovalenko    schedule 13.01.2013


Ответы (4)


Поскольку Антон упомянул об идиоматическом решении, вот мое идиоматическое решение в Racket (я считаю, что использование функций высшего порядка, таких как map, filter-not и, возможно, const, более идиоматично, чем ручное зацикливание и фильтрация). :-)

(define (set-list lst val)
  (map (const val) (filter-not list? lst)))

(Racket предоставляет filter-map, но применяет filter и map в порядке, обратном тому, что мы хотим сделать.)

person Chris Jester-Young    schedule 13.01.2013

Возможно, вы не понимаете, как списки работают в Scheme. Этот список: '(A(2 3) B(2 3) C(2 3)) точно такой же, как этот список: '(A (2 3) B (2 3) C (2 3)). То есть это список из шести элементов. Если вы хотите рассматривать комбинацию символов и чисел как один элемент, упакуйте их вместе в один список: '((A 2 3) (B 2 3) (C 2 3))

В качестве примечания, способ написания процедуры set-list не идиоматичен, в частности, использование append - не лучший способ поместить элементы в начало при построении списка, используйте для этого cons. Это лучший способ написать процедуру:

(define (set-list a val)
  (if (null? a)
      '()
      (cons val
            (set-list (cdr a) val))))

Теперь, следуя моему совету выше, вот как это будет работать:

(set-list '((A 2 3) (B 2 3) (C 2 3)) -1)
=> '(-1 -1 -1)

ОБНОВЛЕНИЕ:

Теперь, если действительно нет недоразумений с тем, как работают списки, и вы просто хотите заменить все подсписки в списке заданным значением, это сработает:

(define (set-list a val)
  (build-list (length (filter (negate list?) a))
              (lambda (x) val)))
person Óscar López    schedule 13.01.2013
comment
OP, похоже, не сбит с толку, см. Комментарии. Он просто хочет полностью пропустить подсписки. (Я могу попробовать написать это, но это не будет идиоматическая схема, может быть, вы?) - person Anton Kovalenko; 13.01.2013

Вот моя попытка (вероятно, это не идиоматическая схема, и обратите внимание, что делать это с append в любом случае неправильно). Я предполагаю, что вы хотите полностью пропустить подсписки, как вы объяснили в комментариях.

(define (Set-list a val)
  (if (null? a)
      (list)     
      (append (if (list? (car a))
                  (list)
                  (list val))
              (Set-list (cdr a) val))))
person Anton Kovalenko    schedule 13.01.2013
comment
Вы близки. Если вы основываете свой подход на cons вместо append, ваше решение будет довольно идиоматическим, по крайней мере, из набора решений, которые не используют функции высшего порядка. (См. Мой пост для решения, основанного на функциях более высокого порядка.) - person Chris Jester-Young; 13.01.2013

Если вы хотите составить список значений, длина которого совпадает с заданной длиной списков,

(define (set-list list value)
    (build-list (length list) (lambda (x) value)))

so,

(set-list '(2 3 4) -1) //returns '(-1 -1 -1)
(set-list '(A (2 3) B (2 3) C (2 3)) -1) // returns '(-1 -1 -1 -1 -1 -1)
(set-list '(2 3 4) -2) //returns '(-2 -2 -2)
(set-list '(A (2 3) B (2 3) C (2 3)) -2) // returns '(-2 -2 -2 -2 -2 -2)
person grgizem    schedule 02.02.2013