Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

Common Lisp is not...

Name: Mr. Irrational 2013-12-04 20:13

Common Lisp is not a functional programming language.

It is a mutli-paradigm programming language.

Imperative programming is featured in e.g. various prog forms, and mutation through setq and various abstractions built ontop of setq e.g. setf.

Structured imperative programming is featured in e.g. various do forms e.g. [/code]dotimes[/code] and of course
do itself.

Unstructured imperative programming is featured in e.g. the go and tagbody forms.

Now, functional programming is featured through the special forms lambda and function, and the many many forms built ontop of them (apply, funcall etc.).

Object oriented programming is supported through CLOS (defclass, defgeneric, defmethod). CLOS is also the most advanced object oriented system I know if in a serious language*

Metaprogramming is, of course, what makes Common Lisp (and its predecessors) famous. Metaprogramming is accomplished through
defmacro. Unfortunately, ANSI Common Lisp has less features for Metaprogramming than CLTL1 or CLTL2. Luckily, most implementations also implement the latter two standards.

Logic programming is easily accomplished, although ANSI provides no standard interface. A simple implementation of Prolog can be found in Norvig's PAIP book (recommended reading after SICP :)

Common Lisp is also useful for symbolic programming (for example writing symbolic differentiation or integration programs). It is also trivial to implement auto-differentiation in Common Lisp, which is very useful (for example, this was useful in my previous job which involved image processing).

Numerical programming is also very well supported. Specifically the arrays dictionary is very powerful. You are able to create multiple "views" into the same array of different size and rank.

Common Lisp is strongly typed. Types can be declared using a simple syntax, and advanced implementations of Common Lisp have type inference. There are libraries for typed collections, e.g. LIL.

Common Lisp runs in a live image that you interact with. The development environments for Common Lisp are very advanced, because various Lisps were some of the pioneers in this field (e.g. InterLisp and the work of Warren Teitelman).

Last but not least, some Common Lisp implementations (e.g. SBCL and CCL) are systems programming languages. You can write inline assembler, and manual memory allocation with all the pointer arithmetic you want. This means that even a Common Lisp running on a UNIX and not a Lisp Machine can be used to write device drivers and kernel modules.

Common Lisp is the most widely used language of an old tradition of Lisps. Lisp 1.5 -> MACLISP -> ZETALISP -> Common Lisp. Common Lisp also has some InterLisp thrown in, which is from the same tradition, and a teensy bit of Scheme. Common Lisp was not an amalgamation of dialects. It was an evolution of the original Lisp.

There are other evolutions of this tradition, beyond Common Lisp. None are as popular as Common Lisp (for better or worse).

The tradition can be described as any language with the following features:
+ Lexical non-local exits.
+ Unwind protection.
+ A condition system with restarts.
+ Lexical binding.
+ Dynamic binding (thread local)
+ First class functions with optional, keyword and rest parameters.
+ A meta object protocol
+ Powerful, low level macros (and all this implies e.g. first class symbols).
+ Multiple return values.

Some languages in this tradition are EULisp, ISLisp, Dylan, Goo and PLOT (afaict).

A note on Scheme: I think Scheme is a Lisp, however it is not in the tradition of the original Lisps (it's not general purpose, nor multi paradigm, it is its own branch). However, the larger Scheme implementations (e.g. Racket) are closer to the Lisp tradition.

The Lisp tradition has nothing to do with languages such as Haskell, ML, Miranda or other "Functional" programming languages. These other languages are very restrictive, and are at odds with the Lisp tradition in almost every way. Lisp is not a functional programming language for one, it is an imperative, structured, unstructured, functional, object oriented, meta programming systems language. It doesn't care about being pure.

No language with mandatory static typing can ever be a Lisp. There is a huge difference between run-time and compile time typing, just as there is with run-time and compiletime code generation. I think these two quotes sum it up the best

From the Common Lisp mailing list in 1981, Richard Stallman said
"But =member= is supposed to work on any type which does or ever will
exist. It should not be necessary to alter the definition of =member=
and 69 other functions, or even recompile them, every time a new type
is added...

The extensible way of thinking says that we want to make it as easy as
possible to get to as many different useful variations as possible. It
is not one program that we want, but options on many programs."

Ray Dillinger said (in an LtU thread)
"I flatly refuse to limit the inputs to analysis to just the text of
the program. I will use whatever information I have available about
the current state of the program as well, including information that
does not become available before runtime, such as inputs...

That view of type theory (static typing) does not encompass the case
in which the source code may change during a program's run, nor the
case where the definition of a type may change during a program's run."

In conclusion, please stop treating Common Lisp as a functional programming language. I find calling it one is a put off to many good programmers that do not want to use a restrictive and annoying language such as Haskell. Common Lisp is more than that.

Name: Anonymous 2013-12-09 18:57

>>38
It's obviously not an UNTYPED language as values have types. That means its typed. Moreover, the type system is very expressive; a predicate written in Common Lisp can also serve as a type. e.g. you can have a type for sorted lists.

However, it's not a STATICALLY typed language, except for the parts you choose to annotate (statically) with type information.

You can accurately say "static type information is not mandatory" but you cannot say "it is untyped" because that is just false.

Now, it is obviously not the case that inexhaustive tests "don't prove anything". They are programs that prove what you write them to prove. You could for example write a test which walks your function definition and checks for type errors ;)

(really, this could be a useful exercise for you, because you seem to be very confused about what typing is. You think it is magical, it is not. A starting point might be function-lambda-expression. For "extra credit" make your type checker prompt the programmer for fixes, and then apply those fixes.)

I'm not sure what you were trying to explain with your prime number example. However, I do know that programs can deduce proofs according to some rules, and I also know that programs have proved things about prime numbers in the past. I am not sure why you think that the only way to write a program to prove properties about prime numbers involves listing them.

For example, here is a computer program which proves your example; that there are infinitely many primes:

http://www.cs.utexas.edu/users/moore/acl2/v3-3/distrib/acl2-sources/books/quadratic-reciprocity/euclid.lisp

Note that the above proof was written in Common Lisp (using ACL2). The proof itself can be a type in Common Lisp (using satisfies). A conforming ANSI Common Lisp implementation may then be able to do type checking (and or inferencing) using this information, if you choose to supply your programs with it statically. However conforming implementations are not required to do so.

You do make the correct claim that compulsory static typing *forces* the programmer to prove some properties of his program. Namely properties about types. These can be very useful properties, but in many cases they are not. Furthermore, introducing static constraints to your program necessarily limits what it may do at run time, and this is not always desirable, so it should not be forced on to programmers.

Now, in your example the function bar might lead to a type error if called with the wrong inputs. However it also might not. So, just because a programmer might combine foo with another function in a way that the other function is not defined for *some* inputs does not mean that that other function should not exist, or should not be allowed to use the functionality that foo provides.

(If you ever program in Smalltalk (another great language) or various languages in the core Smalltalk family (self, strongtalk, newspeak etc.), you will learn to think about programs as services to other programs. Judging by your confused posts, I think this might be a good exercise for you as well).

This is why you will sometimes hear the claim that (compulsory) static typing is premature optimization. Static typing limits how procedures in your program can be combined, before you even know about all the useful ways they could be combined.

The problems with restricting your program with static type declarations everywhere are even larger when the program can change during it's run.

Also, I noticed you were using SBCL. Please read SBCL's manual (and documentation on its confusingly named "Python" compiler) if you wish to know how to make the most out of static type annotations. Manuals often explain to users of a system how the system and related tools work. ANSI Common Lisp only provides some guidelines and suggestions on how a particular implementation might work, and what it means to be conforming. However conforming implementations may be very different, especially with regard to environment sorts of things (debugging, compiling, introspection etc.).

>>40

I think this more applies when you work in teams, and you are not very familiar with the latest changes your team member has made to his program. I think having executable guarantees is important in a team. Some of these guarantees can be made by executing your compiler with type annotated program text as input, but not many; many guarantees cannot be made a priori.

By the way, even when working in a language with compulsory static typing, you should be writing tests (especially if it is a collaborative project).

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List