Home > OS >  How can i create a list just using cons and empty list? Racket
How can i create a list just using cons and empty list? Racket

Time:04-20

Hi have been asked as to build the following lists,just by using cons and the empty list.I attempted to do the first one,i tried this first,for the first list.

(cons (cons 1 (cons 2 '())) (cons 3 (cons 2 '())))  this was the output '((1 2) 3 2)

i also tried this (cons (cons 1 '()) (cons (cons 2 '())) (cons 3 (cons 4 '())) '())

but it kept returning augment errors,can someone explain how should i apply the empty lists and cons to obtain the required results

‘(1 (2 ( 3 2 ))) 
 '(1 2 (3 4 (5))) 
 '(((1 2 3))) 
 '((1 (2)) 3 4) 

CodePudding user response:

When you're learning about pairs and lists, it can be useful to draw a Cons-cell diagrams. There's a great Racket library Sdraw, which visualizes given list or pair- so I used it to show you structure of created lists:

#lang racket
(require sdraw)

; '(1 (2 (3 2)))
(sdraw (cons 1 (cons (cons 2 (cons (cons 3 (cons 2 '())) '())) '())))
; '(1 2 (3 4 (5)))
(sdraw (cons 1 (cons 2 (cons (cons 3 (cons 4 (cons (cons 5 '()) '()))) '()))))
; '(((1 2 3)))
(sdraw (cons (cons (cons 1 (cons 2 (cons 3 '()))) '()) '()))
; '((1 (2)) 3 4)
(sdraw (cons (cons 1 (cons (cons 2 '()) '())) (cons 3 (cons 4 '()))))

CodePudding user response:

There are two things to understand:

  • A cons cell is , informally, a kind of container. It contains exactly two things, of any type, respectively its car and its cdr.
  • A list is a specific sequence of nested cons cells. More precisely, a list is a chain of cons, in which the car of each cons represents an element of the list, and the cdr is either the next link of the chain, or '().

A different formulation: a list is either '(), or a cons cell whose cdr is a list.

Now, for your problem:

First example: '(1 (2 (3 2)))

  • The first element of this list is 1. According to what precedes, this means that 1 is the car of the first cons cell which makes up the list. Hence, the expression will be of the form (cons 1 <something>).
  • The next element of the list is itself a list, namely (2 (3 2)). This is also the last element of the list. This means that <something> is of the form (cons '(2 (3 2)) '()). Indeed, we have seen that a list must end with a cons cell of the form (cons element '()); in that case, element is somewhat complicated, but you have to stick to the rules ! This means that the full expression will be of the form (cons 1 (cons '(2 (3 2)) '()))

We need to "develop" the ugly '(2 (3 2)) form that we still have in the middle of the previous expression. We just follow the same rules: this is a list, the first element of which is 2. It can therefore be written as (cons 2 <rest>).

  • Its next element is itself a list, namely '(3 2). It also happens to be the last element of the list, so <rest> == (cons '(3 2) '()).
  • Finally, and still following the same rules, '(3 2) == (cons 3 (cons 2 '())).

Putting everything together, we get that

'(1 (2 (3 2))) == (cons 1 (cons (cons 2 (cons (cons 3 (cons 2 '())) '())) '()))

The last expression is confusing and pretty much unreadable, but you can get it by doing things slowly. The important thing is that

(a b c d ... z) == (cons a (cons b (cons c ... (cons z '()))))

regardless of how complex a, b ... z actually are. You can the just apply this "formula" (which is really just the definition of a list as a chain of cons cells), and continue to apply it if your sub-expressions are still lists rather than atoms.

Another interesting example: '(((1 2 3)))

This is a list of exactly one element, '((1 2 3)). It is therefore written as (cons <this element> '()) where <this-element> is still somewhat complicated.

In particular, <this-element> is itself a list ! It is of length 1, and has exactly one element, '(1 2 3). It can therefore be written as (cons '(1 2 3) '())

Now, '(1 2 3), by what precedes, is simply (cons 1 (cons 2 (cons 3 '()))).

So '((1 2 3)) is just (cons (cons 1 (cons 2 (cons 3 '()))) '())

... and finally

'(((1 2 3))) == (cons (cons (cons 1 (cons 2 (cons 3 '()))) '()) '())

CodePudding user response:

A nice way to answer this question is not to: instead write a program which will answer it for you: you want a program which, given some object, will return a description of a program which will make it for you. Here is one such:

(define (make-cons-tree-maker tree)
  ;; Note this assumes that the trees are trees.
  (cond
    [(null? tree)
     ;; If the tree is null then it is made by '().  This case is not needed
     ;; (why?)
     '(quote ())]
    [(cons? tree)
     ;; If the tree is a cons we make it by the cons function
     `(cons ,(make-cons-tree-maker (car tree))
            ,(make-cons-tree-maker (cdr tree)))]
    [(symbol? tree)
     ;; Symbols need quoting.  This case is not strictly needed either
     `(quote ,tree)]
    [(or (number? tree)
         (string? tree))
     ;; Numbers and strings do not need quoting
     tree]
    [else
     ;; But assume anything else does (this is safe)
     `(quote ,tree)]))

And now

> (make-cons-tree-maker '(x y))
'(cons 'x (cons 'y '()))

In fact, as the comments in the function say, it can be made a lot simpler, if you are willing to accept that the instructions it returns are not minimal:

(define (make-cons-tree-maker tree)
  ;; Note this assumes that the trees are trees.
  (if (cons? tree)
     ;; If the tree is a cons we make it by the cons function
     `(cons ,(make-cons-tree-maker (car tree))
            ,(make-cons-tree-maker (cdr tree)))
     ;; otherwise just quote it
     `(quote ,tree)))

This will return the same result for the above tree:

> (make-cons-tree-maker '(x y))
'(cons 'x (cons 'y '()))

But its result has a lot of unneeded quotes for some other trees:

> (make-cons-tree-maker '(1 2 3 "foo" . 4))
'(cons '1 (cons '2 (cons '3 (cons '"foo" '4))))

And finally you can of course do this, which entertains you if this sort of thing entertains you:

> (make-cons-tree-maker '(define (make-cons-tree-maker tree)
                           ;; Note this assumes that the trees are trees.
                           (if (cons? tree)
                               ;; If the tree is a cons we make it by the cons function
                               `(cons ,(make-cons-tree-maker (car tree))
                                      ,(make-cons-tree-maker (cdr tree)))
                               ;; otherwise just quote it
                               `(quote ,tree))))
'(cons
  'define
  (cons
   (cons 'make-cons-tree-maker (cons 'tree '()))
   (cons
    (cons
     'if
     (cons
      (cons 'cons? (cons 'tree '()))
      (cons
       (cons
        'quasiquote
        (cons
         (cons
          'cons
          (cons
           (cons
            'unquote
            (cons
             (cons
              'make-cons-tree-maker
              (cons (cons 'car (cons 'tree '())) '()))
             '()))
           (cons
            (cons
             'unquote
             (cons
              (cons
               'make-cons-tree-maker
               (cons (cons 'cdr (cons 'tree '())) '()))
              '()))
            '())))
         '()))
       (cons
        (cons
         'quasiquote
         (cons (cons 'quote (cons (cons 'unquote (cons 'tree '())) '())) '()))
        '()))))
    '())))
  • Related