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).

Name: Anonymous 2013-12-09 20:54

>>38

Have you checked if SBCL is deriving the type of foo properly (with describe)? If not have you explicitly provided return type information (with the)?

Have you tried explicitly declaring the type of the function (instead of relying on your compiler's type inference) with e.g. (declaim (ftype (function (fixnum) (values (or ...))))

If SBCL already has the right static type for foo then maybe you have not appropriately advised the compiler to spit out warnings on type errors?

http://clhs.lisp.se/Body/d_optimi.htm

What does the manual say? (in SBCL you might want to look at e.g. describe-compiler-policy)

Type checking and inference is a responsibility of your implementation. Please read its manual.

I don't think you have read the manual, and this is probably why you are having so much trouble.

If you have, I apologize.

Also as a wise man once said (paraphrasing)
"Understand Agree Accept: The order in which you perform these tasks when confronted with new information says much about your character"

Name: Anonymous 2013-12-11 5:43

>>40
You're a moron if you write code but can't track the type of data of the variables you use.

Name: Anonymous 2013-12-11 7:28

>>43
>le pedophile sage

Name: Anonymous 2013-12-11 8:34

>>41

I wish to correct myself.

I said "It is not a STATICALLY typed language, except for the parts you choose to annotate (statically) with type information"

This is obviously incorrect. Common Lisp is *always* statically typed. The parts you choose not to annotate with type information are of type T of which all objects in Lisp are subtypes.

Also, this means everytime I compared contrasted Lisp with a "mandatory statically typed" language I did so in error. There is no such contrast. The contrast is with languages which do not have a universal type, some notion of subtyping, and (I suppose) don't assume that universal type unless otherwise specified.

Everything else is correct.

That is all.

Name: Anonymous 2013-12-14 14:10

Actually, you can create types at runtime even in a statically-typed language - just use existential types. So Lisp once again is not an original or superior language, just as it is with macros, closures, OOP, tail-call optimizations and every other feature of Lisp.
Common Lisp is, however, a good toy and educational language, especially suited for creating other toy languages.

Name: Anonymous 2013-12-14 18:53

Once again, Anonymous is flaunting his type system sophistry all over the place.

An existential type is not what you think it means, and no, existential types alone don't allow types to be created at run time, they just let you use types created at run time in already existing functions. Something else is required to create them.

Also, I agree Common Lisp is a great toy language, and it is a great educational language, as well as a great language for making other toy languages. This is because it is just great all around, so it is no wonder it would also excel at these things as well.

However I disagree that it is not original or superior.

The Common Lisp line has been very "original" in that it is the origin of many concepts and techniques. The extended Lisp line even more so.

To my knowledge it is also the most superior language. I do not know of any other language which rivals the versatility of Common Lisp, or which makes it easy for a skilled programmer to write performant, understandable, and large systems.

Of course Common Lisp has flaws. For one, it will make a bad programmer (while he remains bad, but they are known to improve) really bad, so it is not very good for use in many teams, in current development strategies, because many teams have at least one newbie.

Also Common Lisp has other flaws. However these flaws are difficult to understand, and require intense study of the standard and other Lisps. Furthermore there have been new ideas and techniques in the Lisp world, which when proven in the field, may make it into a future evolution of Common Lisp (e.g. those lexically scoped namespace thingoes).

One thing about the Common Lisp community is that it is very conservative. Common Lisp programmers have usually been writing programs for >30 years, and have written complicated systems in >15 languages. Common Lisp programmers usually know the origins, the reasons, and the short term and long term effects of various ideas in computer science. This is why a Common Lisp programmer looking at Rich Hickey (a newbie Common Lisp programmer) designing a language look at it not unlike the parent of a child with downsyndrome look at that child as he learns to read; with love and adoration. It is also why Common Lisp programmers look at something like Haskell and expecially it's community with utter disgust.

Finally while we're on the subject of toy languages (as a derogative), one way to know if your language is serious is to think: "Have real machines, and real operating systems, been written for and in this language? Have these been sold for hundreds of thousands of dollars a piece? Did they have a whole suite of applications for documentation preparation, 3D CAD, 3D animation and modelling, film production, image manipulation, computer algebra, robot control etc. that people actually paid for written in that language?" If the answer to any of these questions is no, it is your language which is a toy (derogative) language.

Name: Anonymous 2013-12-14 19:35

In nomine Symbolics, Genera et Sussman sancti

http://lispm.dyndns.org/symbolics-ui-examples/symbolics-ui-examples.html

Name: Anonymous 2013-12-14 19:47

>>47-48
old! dead!

Name: Anonymous 2013-12-14 19:52

>>49

I'm typing this from Genera right now :)

Name: Anonymous 2013-12-14 20:01

>>50
screenshot

Name: Anonymous 2013-12-14 20:44


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