If your favorite Lisp lacks a certain feature you want, it's easy to add, making Lisp the anti-Blub.
(And if your favorite Lisp makes it hard to add it, you've picked the wrong favorite!)
If your favorite Lisp lacks a certain feature you want, it's easy to add, making Lisp the anti-Blub.
(And if your favorite Lisp makes it hard to add it, you've picked the wrong favorite!)
How do you easily add that feature to your favorite Lisp?
(1) The quote from Guido: Programmable syntax is not in Python's future -- or at least it's not for Python 3000. The problem IMO is that everybody will abuse it to define their own language. And the problem with that is that it will fracture the Python community because nobody can read each other's code any more. (http://mail.python.org/pipermail/python-3000/2006-April/0002...)
Depends on which lisp you mean. There are many dialects of lisp and each have their own philosophies and ideals. Scheme, for example, is a minimalist lisp whose philosophy is probably not too different from python - although python has a far bigger standard library (but that is a separate issue).
I like Python and use it everyday, and I this is simply FUD. Sadly it's the kind of argument I hear coming too often from people in the Python community unfamiliar with Lisp when attempting to critique powerful Lisps.
It doesn't need to be hard-coded into the language though - a decent Standard Library showing how things should be done, and a culture maintained by the community would be enough. That would allow everyone the freedom to do what they want if they say a definate advantage in breaking with convention, whilst making it easy for people to generate libraries that are interoperable...
But I find things like extensive use of MOP also make maintenance of programming more challenging.
Common Lisp has never tried to take away 'power' from users.
Scheme had a different philosophy: reduce everything to the most basic and pleasing constructs. But that approach has its own disadvantages - if one arrives at the bottom of programming language constructs, working 'upwards' is a problem.
Take for example the argument lists: Common Lisp has things like keywords, optional and rest arguments. Plain Scheme only has rest arguments. Adding other argument interpretation is possible, but is only really use if the language would support it and would make use of it.
The use of macros that I've seen in CL source doesn't indicate that people are creating other programming languages out of Lisp. In fact, it makes the source easier to read by allowing a natural level of terseness by way of abstraction.
Python's method of abstraction is via encapsulation in it's class/meta-class/object model.
However, this is an argument for another post.
Funny how these Lisp posts continue to flame across the net.
Static typing consists of (a) tagging variables with their type and (b) running a program that uses these type tags to check and/or rewrite the program.
It's easy to add type tags to a lisp program. It's just that Lisp doesn't specify that second program that checks and transforms the first. So I would say Lisp is half way there when it comes to static typing.
That's a pretty contrived argument though... :-)
Declaring types? That has been done. In Common Lisp:
(defun twice (n)
(declare (number n))
(the number (* n 2)))
The difficult parts are:* the type system and its capabilities
* make the operations of the type system sound
* determining sub-types
* type inference
* integration with the rest of the language (where data objects also have something like types)
Common Lisp provides lots of infrastructure for all kinds of things, but very little for a type system. For example in Lisp one can determine the value of an expression via EVAL, but there is no function to compute the type of an expression (other than a type of the computed value).
If you want static typing, then I don't think trading out dynamic typing is a big deal to you.
Though as pointed out else where, many implementations allow you to give their compiler type hints... which is a sort of half-way "best of both worlds" system.
If you want a middle ground, you may lose some of the flexibility, and you still won't be able to prove as much as a full static type system. In the end, the "best of both world" could rapidly become the worst of both worlds.
As I see it, we have to compromise. When you design a type system, you want to maximize 3 virtues: flexibility, simplicity, and error sensitiveness. Alas, of these 3, you can only have 2. Dynamic type systems typically are simple and flexible, but hardly prove anything (which explain why unit tests are so useful). Advanced type systems like Haskell's are quite flexible and prevent many errors, but they are complex. Others, like Java's, are simpler but not as flexible (nor as error proof). And of course you have horrible type systems, like C++'s, which lacks all 3 virtues.