help-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: why are there [v e c t o r s] in Lisp?


From: Pascal J. Bourguignon
Subject: Re: why are there [v e c t o r s] in Lisp?
Date: Sun, 18 Oct 2015 03:07:40 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3 (gnu/linux)

Emanuel Berg <embe8573@student.uu.se> writes:

> "Pascal J. Bourguignon" <pjb@informatimago.com>
> writes:
>
>> You are asking why apples are of a certain color,
>> even as peaches have a kernel.
>
> OK - why is that?


Because the presence of a data type in a language is unrelated to the
presence of a syntax for literal objects of that type.

For example, in lisp, there is a syntax for a list data type.

But there is no list data type in lisp! 
Non-empty lists are actually cons cells, 
and the empty list is actually a symbol!

And in emacs lisp, there's a buffer type, but there's no literal syntax
for buffers objects!

    Syntax:        Type:
    -------        -------
    (1 2 3)        No type
    [1 2 3]        vector
    No syntax      buffer
(And of course, you have the case:
    No syntax      No type
for nothing).

So all the combinations are possible, which shows that having a literal
syntax for objects and having types in a language are two totally
unrelated things.



>> I don't know what you mean by "this" in "figure this
>> out on its own".
>
> As I know you know, there are languages (e.g., SML)
> that do have types but still it isn't compulsory to
> spell them out in the code. The types are instead
> inferred, "leaving the programmer free to omit type
> annotations while still permitting type checking." [1]

Again, you are confusing everything.  This type inference has nothing to
do with what has been discussed so far, this is yet another totally
unrelated thing.

Type inference let the compiler infer the type of the _variables_, so
you don't have to declare the type of the _variables_.  

But in lisp, variables are not typed, it's the values that are typed,
therefore type inference is mostly useless.

Type inference can still be useful in a lisp compiler, since it allows
to produce code that is a little more efficient: you can avoid
generating type dispatches and type checks in expressions using a
variable, when you can infer that this variable will always hold values
of a certain type.

For inference, writing

    (let ((a (vector 1 2 3)))
       (aref a 2))

    (let ((a [1 2 3]))
       (aref a 2))

have the exact same effect: in both case the compiler can infer that a
is always bound to a vector of 3 elements, and therefore it can avoid
testing whether 2 is bigger or smaller than the size of the vector, or
that the value bound to a is indeed a vector before calling aref.

In the case of emacs lisp since aref can be used with the disjoints data
types: vector, string, char-table, bool-vector and byte-code, there are
actually five different aref functions!  The aref function must test the
type of the first argument, and depending on this type, it calls one of
the five type-specific aref functions.  With type inference, it could
call directly the aref for vectors.

But as you can see from the two examples above, this has absolutely
nothing to do with literal syntaxes or the existance of a given data
type.



>> The speed is irrelevant here, there are semantic
>> differences:
>>
>> (setf print-circle t) (loop repeat 3 collect [1 2 3])
>> --> (#1=[1 2 3] #1# #1#) (loop repeat 3 collect
>> (vector 1 2 3)) --> ([1 2 3] [1 2 3] [1 2 3])
>
> It is since several posts clear that lists and vectors
> are two different general-purpose data structures,
> with different properties with respect to access times
> and memory allocation policy, and also with different
> methods to interact with the data - because they are
> different types.

Why are you writing this paragraph in the context of an example showing
only vector objects?

You are completely blind, you didn't realize what happened there.

In the first case, since [1 2 3] is one single literal object, it is
always this single literal object that is collected.  We obtain
therefore a list containing three times this very same single literal
object, which is represented with the #=/## syntax.

In the second case, since (vector 1 2 3) is an expression that builds a
new vector, called 3 times it will produce 3 different vectors!  And
therefore we obtain a list with 3 different unrelated vectors.


In the first case, since we have a list of literal vectors, we cannot
modify thse literal vectors (the single unique literal vector), without
obtaining nasal daemons.  So instead I will produce a list containing
three times the same mutable vector unique, to show you what happens
when we modify a slot in the first vector of the list:

    (let* ((unique (copy-seq [1 2 3]))
           (vs (loop repeat 3 collect unique)))
      (setf (aref (elt vs 0) 0) 0)
      vs)
    --> (#1=[0 2 3] #1# #1#)

    (setf print-circle nil)
    (let* ((unique (copy-seq [1 2 3]))
           (vs (loop repeat 3 collect unique)))
      (setf (aref (elt vs 0) 0) 0)
      vs)
    --> ([0 2 3] [0 2 3] [0 2 3])
          *       *       *

Since we have a unique single vector, when we modify it, we see the
modification in all the occurences of the very same single vector.

On the other hand, in the second case, where we have tree different
vectors, if we modify the first slot of the first vector, then only the
first vector is modified, and the modification is seen only in the first
vector which is different from the two others:

    (let ((vs  (loop repeat 3 collect (vector 1 2 3))))
      (setf (aref (elt vs 0) 0) 0)
      vs)
    --> ([0 2 3] [1 2 3] [1 2 3])
          *       *       *

-- 
__Pascal Bourguignon__                 http://www.informatimago.com/
“The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.” -- Carl Bass CEO Autodesk


reply via email to

[Prev in Thread] Current Thread [Next in Thread]