Jump to content

What on earth does (vl-list* 1 2 3) produce?


Semx11

Recommended Posts

When you run (vl-list* 1 2 3), it returns (1 2 . 3) (this example is also documented for the function vl-list*)

(vl-list* 1 2 3 4) returns (1 2 3 . 4)

This makes no sense to me. It seems to be partially a list, and partially a dotted pair.

 

To recreate it in vanilla lisp, you would use (setq $weirdList '(1 2 . 3))

 

Executing

(car) or (nth 0) returns 1.

(cadr) or (nth 1) returns 2

(caddr) or (nth 2) returns 'bad argument type: 3'

 

So what is this data structure? And what is the point... how do you access the last value (if it even is a value?)

I've worked with lisp for a year now and this really just confuses me lol. Wondering if someone knows what it does and can clear it up.

Edited by Semx11
Link to comment
Share on other sites

Directly off the website.

 

Return Values

The vl-list* function is similar to list, but it will place the last object in the final cdr of the result list. If the last argument to vl-list* is an atom, the result is a dotted list. If the last argument is a list, its elements are appended to all previous arguments added to the constructed list. The possible return values from vl-list* are

  • An atom, if a single atom object is specified.
  • A dotted pair, if all object arguments are atoms.
  • A dotted list, if the last argument is an atom and neither of the previous conditions is true.
  • A list, if none of the previous statements is true.
Edited by mhupp
Link to comment
Share on other sites

Hi @mhupp, thanks for your reply.

 

I did read that part of the documentation obviously. But what is a dotted list?

How do you access the data, and how does it differ from a list and a dotted pair?

 

I tried searching online and trying all kinds of commands on it but I can't figure it out.

 

Edit: and what would be a practical use-case for a dotted list?

Edited by Semx11
Link to comment
Share on other sites

I figured it out.

 

Apparently in LISP, a list is nothing but a bunch of nested cons.

So (list 1 2 3 4) is the same as (cons 1 (cons 2 (cons 3 (cons 4 nil))))

 

This also explains (car) and (cdr). (car) takes the left value, and (cdr) the right value.

Using (cdr) on a list returns everything from the 2nd value and after that.

 

(vl-list* 1 2 3 4) returns '(1 2 3 . 4), which is the same as (cons 1 (cons 2 (cons 3 4))).

So it essentially saves one extra cons.

 

Maybe this is super basic stuff but I've only figured this out after a year of working with LISP lol.

Still not clear what the use-case of a dotted list would be, maybe someone has a cool idea :)

 

Just leaving this here if anyone else is curious about this too.

Link to comment
Share on other sites

A dotted list is how dxf codes are stored.

http://docs.autodesk.com/ACAD_E/2012/ENU/filesDXF/WS1a9193826455f5ff18cb41610ec0a2e719-7a62.htm

 

for example here is part of an polyline's data

(-1 . <Entity name: 527c1a20>) 
(0 . "LWPOLYLINE") 
(5 . "4CCC9") 
(330 . <Entity name: 2770b0f0>) 
(100 . "AcDbEntity") 
(67 . 0) 
(410 . "Model") 
(8 . "0") 
(370 . -1) 
(100 . "AcDbPolyline") 
(90 . 16) 
(70 . 1) 
(43 . 0.0) 
(38 . 0.0) 
(39 . 0.0) 
(10 -33.507337499427 -0.845370190263241) 
...

 

So if you wanted to know how many vertices are in the polyline you can use assoc function.

 

(setq vert (cdr (assoc 90 (entget ("entname"))))

 

This would look at the entity data (above) and look for item 90 and returns (90 . 16) cdr returns 16

So this is a way to store data and quickly return specific values from a list.

 

Don't really use vl-list* so cant really give you any examples.

 

Link to comment
Share on other sites

I think you misunderstood my question, sorry for that.

 

DXF codes are stored in a list of dotted pairs. A dotted list is something else (apparently).

 

A list looks like this:

(cons 1 (cons 2 (cons 3 (cons 4 nil))))

which is the same as

(list 1 2 3 4)

which is the same as

'(1 2 3 4)

 

list of dotted pairs looks like this:

(cons (cons 1 2) (cons (cons 3 4) (cons (cons 5 6) (cons (cons 7 8 ) nil))))

which is the same as

(list (cons 1 2) (cons 3 4) (cons 5 6) (cons 7 8))

which is the same as

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

 

This is used for entget data and DXF codes, but it would look something like this:

(cons (cons 0 "LWPOLYLINE") (cons (cons 5 "4CCC9")  ... )) [terminated with a nil]

which is the same as

((0 . "LWPOLYLINE") (5 . "4CCC9") ... )

 

A dotted list is simply a normal list that isn't terminated with a nil, it looks like this:

(cons 1 (cons 2 (cons 3 (cons 4 5))))

which is the same as

'(1 2 3 4 . 5)

 

You can verify these examples by pasting the (cons) version into your AutoCAD console, and it will evaluate to the bottom version.

 

Not quite sure what the use case is for a dotted list, but it's fun to know it exists, I guess :)

Edited by Semx11
  • Like 1
Link to comment
Share on other sites

I suppose usage of (vl-list*) function is exactly you described haphazardly - to avoid multiple consecutive usage of (cons)...


 

Quote
: (vl-list* 1 2 3 4)
(1 2 3 . 4)
: (vl-list* (list 1 2 3) (list 2 3 4) (list 3 4 5) 4)
((1 2 3) (2 3 4) (3 4 5) . 4)
: (vl-list* (list 1 2 3) (list 2 3 4) (list 3 4 5) (list 4 5 6))
((1 2 3) (2 3 4) (3 4 5) 4 5 6)
: (vl-list* 3 (list 4 5 6))
(3 4 5 6)
: (vl-list* 1 2 3 (list 4 5 6))
(1 2 3 4 5 6)


: (cons 1 (cons 2 (cons 3 4)))
(1 2 3 . 4)
: (cons (list 1 2 3) (cons (list 2 3 4) (cons (list 3 4 5) 4)))
((1 2 3) (2 3 4) (3 4 5) . 4)
: (cons (list 1 2 3) (cons (list 2 3 4) (cons (list 3 4 5) (list 4 5 6))))
((1 2 3) (2 3 4) (3 4 5) 4 5 6)
: (cons 3 (list 4 5 6))
(3 4 5 6)
: (cons 1 (cons 2 (cons 3 (list 4 5 6))))
(1 2 3 4 5 6)

 

 

Here are couple of useful sub functions and perhaps possible utility of (vl-list*) function usage...

 

(defun last-pair-of-list ( lst )
  (if (not (atom (cdr lst)))
    (last-pair-of-list (cdr lst))
    (if (cdr lst)
      lst
      (cons nil lst)
    )
  )
)

(defun is-dot-list-p ( lst / last-pair-of-list )

  (defun last-pair-of-list ( lst )
    (if (not (atom (cdr lst)))
      (last-pair-of-list (cdr lst))
      (if (cdr lst)
        lst
        (cons nil lst)
      )
    )
  )


  (if (listp lst)
    (car (last-pair-of-list lst))
  )
)

(defun is-list-p ( lst / last-pair-of-list )

  (defun last-pair-of-list ( lst )
    (if (not (atom (cdr lst)))
      (last-pair-of-list (cdr lst))
      (if (cdr lst)
        lst
        (cons nil lst)
      )
    )
  )

  (if (listp lst)
    (not (car (last-pair-of-list lst)))
  )
)

(defun assocbylast ( val lst / last-pair-of-list lastvals pos )

  (defun last-pair-of-list ( lst )
    (if (not (atom (cdr lst)))
      (last-pair-of-list (cdr lst))
      (if (cdr lst)
        lst
        (cons nil lst)
      )
    )
  )

  (setq lastvals
    (vl-remove nil
      (mapcar
        (function (lambda ( x / v )
          (if (listp x)
            (if (atom (cdr (setq v (last-pair-of-list x))))
              (cdr v)
              (cadr v)
            )
          )
        ))
        lst
      )
    )
  )
  (if (setq pos (vl-position val lastvals))
    (nth pos lst)
  )
)

(defun butlast ( lst / last-pair-of-list pair ret )

  (defun last-pair-of-list ( lst )
    (if (not (atom (cdr lst)))
      (last-pair-of-list (cdr lst))
      (if (cdr lst)
        lst
        (cons nil lst)
      )
    )
  )

  (if (listp lst)
    (progn
      (if (not (car (setq pair (last-pair-of-list lst))))
        (setq ret (reverse (cdr (reverse lst))))
        (progn
          (while (not (equal lst pair))
            (setq ret (append ret (list (car lst))))
            (setq lst (cdr lst))
          )
          (setq ret (append ret (list (car lst))))
        )
      )
      ret
    )
  )
)

 

Quote
: (setq lst (list (vl-list* 1 2 3 4) (vl-list* 2 3 4 5) (vl-list* 3 4 5 6) (vl-list* 4 5 6 7) (list 5 6 7 8) (list 6 7 8 9)))
((1 2 3 . 4) (2 3 4 . 5) (3 4 5 . 6) (4 5 6 . 7) (5 6 7 8) (6 7 8 9))
: (assocbylast 7 lst)
(4 5 6 . 7)
: (assocbylast 8 lst)
(5 6 7 8)
: (butlast (assocbylast 7 lst))
(4 5 6)
: (butlast (assocbylast 8 lst))
(5 6 7)

 

 

Also this link may be of interest :

https://www.theswamp.org/index.php?topic=57748.0

 

Regards, M.R.

HTH.

Edited by marko_ribar
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...