Vector:
CL-USER 102 > (map 'vector #'char-code "foobar")
#(102 111 111 98 97 114)
CL-USER 103 > (reduce #'+ #(102 111 111 98 97 114))
633
Bitvector: CL-USER 105 > (reduce #'+ #*10101001010101)
7
2d-Array CL-USER 106 > (aref #2a((1 2) (3 4)) 1 1)
4 CL-USER 109 > (reduce #'+ (read))
(1 2 3)
6
reading and reducing a vector: CL-USER 110 > (reduce #'+ (read))
#(1 2 3)
6
I've changed only the opening bracket.You can use the #(...) syntax to include literal vectors in your code, but as the effects of modifying literal objects aren't defined, you should always use VECTOR or the more general function MAKE-ARRAY to create vectors you plan to modify.
CL-USER 111 > (defun maps (function sequence)
(map (type-of sequence) function sequence))
MAPS
CL-USER 112 > (maps #'1+ '(1 2 3))
(2 3 4)
CL-USER 113 > (maps #'1+ #(1 2 3))
#(2 3 4)
I can also write a compiler macro, so that the implementation is chosen at compile time, when a literal data object is used... stuff which a Common Lisp implementation already might do for MAP.Common Lisp chose to define the basic MAP to always specify the result sequence I want to create or NIL for no sequence.
> You can use the #(...) syntax to include literal vectors in your code, but as the effects of modifying literal objects aren't defined, you should always use VECTOR or the more general function MAKE-ARRAY to create vectors you plan to modify.
That's not different for lists and vectors. For both I need to know which I want to modify. Common Lisp has generic operations to create and copy sequences for that: I can call COPY-SEQ to copy the literal sequence or call MAKE-SEQUENCE to create the sequence type I want.
Here (and in many other places) Common Lisp is a low-level language, which exposes these things to the programmer.
You haven't even touched on sets, which in CL are not a built in type, even though there are functions that let you pretend a list is a set, it's not really the same thing when it's not an efficient underlying representation.
Personally I wouldn't call Common Lisp a low level language. A programmable language sure. Low level implies being close to the machine architecture, which it clearly is not.
I didn't admit anything like that. I showed you that vectors are well integrated in Common Lisp.
> Personally I wouldn't call Common Lisp a low level language.
I wouldn't either.
But then I didn't call Common Lisp a low level language. I said: 'Here (and in many other places) Common Lisp is a low-level language' - which means that Common Lisp is PARTLY a low-level language - for example no detection of modification of literal data is required/provided - the programmer has to make sure data can be modified when necessary. A higher-level data-structure would probably require detecting this or would provide only immutable data types. Common Lisp has many relatively low-level features, from cons cells to directives telling the compiler to avoid runtime type checks. Having singly-linked lists is much lower-level than persistent sequences of Clojure.
Generally it's not surprising that Common Lisp has lots of low-level features, since it has been used to write much of itself and large parts of its runtime - where Clojure is a hosted language: large parts of the runtime, the compiler and parts of the library are not written in Clojure: https://github.com/clojure/clojure/tree/master/src/jvm/cloju...
If you look at an unsafe CAR operation, it is often just a single machine instruction.
Take this function which calls FOO twice. FOO is just calling CAR and inlining this call.
(defun bar (a)
(declare (optimize (speed 3) (safety 0) (debug 0))
(type cons a)
(inline foo))
(the cons (foo (the cons (foo a)))))
The disassembly then shows that CAR is a MOV instruction: ; Size: 14 bytes. Origin: #x1002FB5E49
; 49: 488B40F9 MOV RAX, [RAX-7] ; no-arg-parsing entry point
; 4D: 488B50F9 MOV RDX, [RAX-7]
; 51: 488BE5 MOV RSP, RBP
; 54: F8 CLC
; 55: 5D POP RBP
; 56: C3 RET
For a language like Lisp this is low-level stuff: telling the compiler to optimize for speed, no runtime checks, provide no debug information, declare the type of a variable, declare return types and instruct the compiler to inline a function.Or take structures in CL. They are defined such that can be compiled to a linear vector-like data structure with slot-access to known and static offsets. No redefinition, no meta-data information - low overhead.
Two of the original goals of Common Lisp were defined as this:
> Portability
> Common Lisp intentionally excludes features that cannot be implemented easily on a broad class of machines. On the one hand, features that are difficult or expensive to implement on hardware without special microcode are avoided or provided in a more abstract and efficiently implementable form. (Examples of this are the invisible forwarding pointers and locatives of Zetalisp. Some of the problems that they solve are addressed in different ways in Common Lisp.) On the other hand, features that are useful only on certain ``ordinary'' or ``commercial'' processors are avoided or made optional. (An example of this is the type declaration facility, which is useful in some implementations and completely ignored in others. Type declarations are completely optional and for correct programs affect only efficiency, not semantics.) Common Lisp is designed to make it easy to write programs that depend as little as possible on machine-specific characteristics, such as word length, while allowing some variety of implementation techniques.
> Efficiency
> Common Lisp has a number of features designed to facilitate the production of high-quality compiled code in those implementations whose developers care to invest effort in an optimizing compiler.
I see a "cleaner syntax in the example" but the fragments of code you don't like, the literals, are something that you won't see in production code except for a few constants maybe. The difference in ~"characters to change" for switching from list to vector is far smaller than the amount of characters spent on this thread... (edit: even over the lifetime of a programmer)
I like Clojure for bringing maps and vectors into first class language constructs with simple syntax and the fact that it runs on the JVM means I have access to the entire Java ecosystem of libraries and tools.