В упражнении 2.26 SICP с использованием DrScheme, почему «против» возвращает список, а не пару списков? - PullRequest
6 голосов
/ 27 мая 2010

В упражнении SICP 2.26 дается код этой схемы:

(define x (list 1 2 3))
(define y (list 4 5 6))

Затем дается этот вызов "против":

(cons x y)

Я ожидал, что получится пара списков, ((1 2 3) (4 5 6)) но интерпретатор дает ((1 2 3) 4 5 6) ... список из 4 элементов, первый из которых - список.Почему к тебе относятся по-разному?Я попытался найти другие ответы SICP для объяснения, но не смог найти что-то удовлетворительное.Так могут ли эксперты по Схеме / Лиспу пролить свет на этот аспект минусов?Заранее благодарим за понимание.

Ответы [ 6 ]

12 голосов
/ 27 мая 2010

'((1 2 3) 4 5 6) на самом деле пара списков. Вот еще один способ написать это:

'((1 2 3) . (4 5 6))

Тем не менее, принтер избегает обозначения точечной парой, когда это возможно, поэтому вы получите первое представление вместо этого. Правило:

'(x . (xs ...))
=>
'(x xs ...)

Для любых x и xs. Здесь ваши x = '(1 2 3) и xs = '(4 5 6), поэтому вы получите ((1 2 3) 4 5 6).


Чтобы увидеть, как соотносятся минусы и обозначения точечной пары, давайте сократим проблему до '(1) и '(6). Самый низкий способ построить пару из них - это:

(cons (cons 1 '()) (cons 6 '()))

Здесь '() - ноль или пустой список. Если мы переведем это буквально в запись с точечной парой, мы получим это:

'((1 . ()) . (6 . ()))

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

'((1 . ()) . (6 . ()))
=>
'((1) . (6))    ; <-- x=1, xs=nothing; x=6, xs=nothing
=>
'((1) 6) ; <-- x=1, xs=6
10 голосов
/ 27 мая 2010

cons использует первый аргумент в качестве заголовка списка, а второй - в качестве хвоста.

Вы даете ему первый список (1 2 3), который будет составлять заголовок результирующего списка, и второй список (4 5 6), который будет использоваться в качестве хвоста списка. Таким образом, вы заканчиваете ((1 2 3) 4 5 6).

Вещество списков в виде слева-направо гребней, заканчивающихся пустым списком (представленным здесь как o), и посмотрите, как они объединяются.

 X=      Y=
 /\      /\
1 /\  + 4 /\    
 2 /\    5 /\  
  3  o    6  o

Затем вы строите:

 /\
X  Y

Получение:

  /\
 /\ \
1 /\ \
 2 /\ \
  3  o/\
     4 /\
      5 /\
       6  o

, который равен ((1 2 3) 4 5 6, если представлен в скобках. И это пара списков.

1 голос
/ 17 марта 2011

эй, я думаю, вы могли бы подумать об этом таким образом;

всякий раз, когда есть ноль, должна быть пара круглых скобок, как следует:

(минусы 1 (минусы 2 ноль)) -> (список 1 2)

(пусть ((x (список 1 2 3)) (y (список 4 5 6))))

1. (Минусы x y) -> (минусы (минусы 1 (минусы 2 (минусы 3 ноль)))) (минусы 4 (минусы 5 (минусы 6 ноль)))) здесь первый ноль обозначает конец пары, который можно выразить в скобках; тогда как второй ноль обозначает конец всей пары, которая использует другую пару скобок; Итак, ((1 2 3) 4 5 6)

2. (Список x y) -> (cons x (cons y nil); как мы знаем, x содержит ноль, так что это должно быть (1 2 3); вторая часть содержит два ноля, так ((1 2 3) (4 5 6));

самый внутренний ноль означает самый внешний скобок;

Надеюсь, это поможет.

1 голос
/ 11 июня 2010

Я нашел диаграммы в учебнике Emacs Lisp особенно полезными при изучении Lisp.

0 голосов
/ 27 мая 2010

try (список x y) Я уверен, что это работает на обычном языке, я не знаю, что такое Scheme

0 голосов
/ 27 мая 2010

Читать это: http://en.wikipedia.org/wiki/Cons

...