2013-12-02 3 views
0

Мне было интересно, что (cons? list-name) делает. Он просто проверяет, что list-name не является непустым списком? Это как противоположность (empty? list-name)? Если да, то не лучше ли просто сказать (empty? list-name), а затем сказать else вместо cons?? Например:Что делает (cons? List-name)?

(define (f list-name) 
    (cond 
    [(empty? list-name) empty] 
    [(cons? list-name) "do something])) 

ответ

1

cons? проверяет, является ли значение является cons клетки, например, то, что это (cons foo bar) для некоторых foo и bar.

> (cons? 1) 
#f 
> (cons? '()) 
#f 
> (cons? (list 1 2 3)) 
#t 
> (cons? (cons 1 2)) 
#t 

Если (cons? a) правда, то это безопасно использовать car и cdr на a.

Это не противоположность empty?, так как empty? истинно тогда и только тогда, когда аргумент является пустым списком, поэтому (empty? 1) == (cons? 1) == #f.

Sidenote: Пожалуйста, не ставьте PLEASE HELP!! или аналогичные в заголовках вопросов, все здесь рады помочь, но это немного неприятно читать. Просто нужно иметь в виду в будущем. Добро пожаловать в SO.

+1

Это правильно. _However_, если аргумент, входящий, как известно, является списком (будь то с помощью предыдущих проверок или потому, что это то, что требуется функции), тогда он имеет смысл иметь простой if/else. 'empty? 'проверяет, есть ли у вас тривиальный случай списка, а _everything else_ должен быть списком, на котором вы можете использовать' first' и 'rest'. –

1

jozefg's answer прав, указывая на то, что (cons? x) не то же самое, как (not (empty? x)), в целом, потому что есть вещи (например, номера), которые не являются ни минусы клетки, ни пустой список.

Однако ваша переменная была list-name, поэтому у вас может быть некоторая причина ожидать, что ее значение, по сути, является списком. Список на Схеме:

  • пустой список; или
  • a cons cell, чей car является элементом списка first, а cdr является rest списка.

Из-за этого, если вы пишете функцию, которая требует списка будет принято в, то делает имеет смысл, чтобы просто проверить для тривиального случая (пустой список) с empty?, и принять на себя , поскольку вам нужен список, что все, что не соответствует этому случаю, является ячейкой cons, на которую вы можете позвонить cdr и cdr. Это происходит потому, что в то время как

(cons? x) == (not (empty? x)) 

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

(cons? lst) == (not (empty? lst)) 

является истинным. Есть ряд функций, которые делают то же самое, когда мы говорим о списках и ячейках cons. Например, empty? и null? делают то же самое, но они сигнализируют немного другое намерение со стороны программиста.Точно так же, car и cdr сделать то же самое, как и firstrest, но car и cdr сигнал, который вы могли бы что-то для обработки в виде пары из двух вещей, в то время как first и rest четко сигнализировать намерение, что вы работаете со списком.

Ваш код, поскольку он, кажется, ожидает список, должен, вероятно, быть следующим, поскольку для списка, если это не пустой список, он должен быть минусом.

(define (f lst) 
    (cond 
    [(empty? lst) empty] 
    [else "do something])) 

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

(define (frob-list lst) 
    (cond 
    [(empty? lst) empty] ; arg is() 
    [else ...]))   ; arg is (x . y) 

(define (frob-object obj) 
    (cond 
    [(null? obj) ...]  ; arg is() 
    [(cons? obj) ...]  ; arg is (x . y) 
    [(number? obj) ...] ; arg is r 
    ...     ; arg is ... 
    [else ...]))   ; else ... 
+1

IOW, полагайтесь на контракт функции для правильности кода. :) –

Смежные вопросы