Guido van Rossum has shown a multimethod implementation in Python. That implementation supports your example as well, as the rules which define what types invoke which methods are easily extensible.
Well, how about adding object-oriented programming to a language which previously did not include it?
Multiple pre-CLOS object-oriented extensions to Lisp were written using heavy-duty macrology.
How about adding Prolog-style logic programming to a language which previously did not include it?
You can do so in Lisp, and macros are the best tool for the job.
How about adding an English-like syntax for defining common looping constructs? Lisp's infamous LOOP macro could be and was developed by *users* who didn't have to wait for some language implementor to do it for them.
How about a whole book's worth of code?
What about allowing simple application-oriented forms to declare and define multiple associated functions and data structures?
The basic fact is that Lisp programmers f*cking INVENTED the use of closures in programming, and they STILL PREFER MACROS by a large margin to implement control structures. Do you think they all are brainwashed, or stupid amnesiacs, or what? Does learning "defmacro" somehow block all memory of "lambda"? If it were just a matter of "good closure syntax", we'd use defmacro to define a nicer syntax and use it. But the plain fact is that the syntax is superficial---the expressive power is fundamental.
The code transformations possible greatly outnumber the total number of closures it is reasonable to ask a higher-order-function user to pass it. Furthermore, forcing the use of closures means the user of your utility has to jump through more hoops to use it, and makes your design more complicated.
Why don't you just show an example of a macro that cannot be just-as-reasonably (or almost-as-reasonably) implemented without the quirky evaluation rules?
Ofcourse a language that has no macros is going to need to be very powerful in the first place. And indeed, when Smalltalk programmers wanted looping constructs, they also didn't have to implement new language features. They just implemented methods that take closures as arguments and create very nice and readable loops:
and in fact, that's exactly the kind of thing one has to do when working in functional languages with no macros, but (a) it's less elegant because you're making the programmer do some of the macro's work, and (b) this is still a pretty simple macro.
I find it a lot more elegant, as it uses simpler primitives to achieve the same goal. Also, it makes it very clear where the variables come from, even if I don't know the "with-file" function (explicit function arguments).
# This is not really longer than the macro example so you cannot say that you have to "do" some of the macro's work. What work?
data = with(open_file('/etc/passwd', 'rb', lambda stream: stream.read()))
Macros empower the developer by enabling the construction of syntactic abstractions -- each of which extends the syntax of the language. Like any other power, it is sometimes abused by the inexperienced; one can certainly write utterly unfathomable code using macros. But used well, macros greatly enhance the elegance, readability, and maintainability of code.
Instead of changing the syntax itself, one can have a rich syntax to begin with, and only overload the semantics of the syntax. Some things should never change, for readability's sake. Things such as when code is evaluated and when its not. Macros break this rule and make reading Lisp much harder. While I can read code that uses functions I do not know with relative ease, I have no idea what's happening when macros are used, because there are no evaluation rules that the code adheres to.
As for why macros are not more widely used, there are a couple of reasons. Lisp's minimalist syntax, so strange-looking at first glance, turns out to be one of its greatest advantages. The very simplicity of the syntax is exactly what makes it so powerful and general: user-defined constructs are invoked just like built-in constructs. While in principle a language with keywords and infix expressions could have an extensible grammar, syntactic extensions get much harder to manage in such a language because they tend to interact, causing ambiguities in the grammar.
Again, if you assume syntactic extensions are a good thing (as opposed to semantic extensions by overloading an existing rich syntax).
And the second reason is one the above post touches on when it mentions the representation of code as data. Lisp is the only major language to give programmers access to a standardized tree representation of source code. The fact that the representation is a tree makes Lisp macros powerful (contrast the pitifully weak "preprocessor macros" of C/C++, which operate on a character string representation), and the fact that the representation is standardized makes them portable.
Again, if you assume syntactic extensions are an advantage. (btw: Python does allow you access to its code tree, but its rather inconvinient).
I have plenty of experience in more mainstream languages, but when programming for myself, I almost always use Common Lisp. Macros are a major reason.
Just recently me and a friend of mine wrote a LazyExpression object in Python.
It indeed takes a few more lines (About a factor of 3), but it supports more functionality (and is simpler!). I can use the "promise" (my lazy object) in any context, and automagically, new "promises" are created.
What happens if you use (car my-promise)? Will it create a promise to run car on the result of the promise when it is evaluated, as you would want it to, or will it return an arbitrary piece of data that you did not mean for it to return?
These promises are a lot less useful than the Python Lazy object because everyone using them must be aware of the fact that they are not actual results.
You're not solving the basic problem that macros solve, however. Receiving a function as a closure doesn't allow you to manipulate the function. You can use it as-is, but a lot of very powerful constructs require that manipulation.
I think that useful manipulations of this type should not be a function of the actual content of the function, but manipulations of the function object, and of what happens before/after the function.
Many of the macros used in Common-Lisp programs could not be rewritten as a function taking a closure. A trival example is PUSH.
Push is really something that the sequence types must support. Any generic macro definition such as PUSH is going to fail to be optimized on new sequence types. It is also more readable to support this operation as part of the sequence protocol, and to not support it where it is extremely expensive. In Python, if it is not possible to insert an element to a sequence without a very expensive operation, Python exposes this by requiring the specification of the expensive operation with a bit of extra syntax, and this is an advantage.
Bigger examples are DEFUN, DEFCLASS, DEFMETHOD (pretty much all of CLOS, really), etc.
Your loop example is particularly good. Languages like Python rely on hard-coded syntaxes for their looping constructs, which invariably express only a very limited subset of the looping constructs the programmer wants to use.
Python is not actually the good example I was talking about, in this case. I was referring to how Smalltalk implements looping.
Something like CL's LOOP macro is far more powerful (and wisely used, can be every-bit as readable), but could not be implemented as a function taking a closure.
Again, look at Smalltalk. Such a macro can be implemented as a set of functions that take a closure.
As for "giving up a readable syntax", I consider Lisp's much more readable than C++. Lisp is readable if you're used to reading Lisp. Its unreadable if you're not. The same is true of C++. Before anybody complains about Lisp's syntax being unreadable, they should have at least a thousand lines of code (in an actual program, not some homework assignment!) under their belt.
A language must have appeal, and that includes its syntax. If people feel they have to decipher the code through highly-nested expressions that all look alike, they are not even going to write 1000 lines of code in the language. Other languages have a different syntax for the creation of builtin data types, for assignments, for attribute getting/setting, etc. This helps programmers read the program.
A thousand lines seems like a lot, but its a decent metric for seperating those who know Lisp and those who do not. Ask yourself: would you hire somebody who claimed to "know" C++, when they hadn't written more than a thousand lines in it?
I have written less than a thousand lines in Lisp, and indeed I wouldn't hire myself to write Lisp (unless I knew that I am a fast learner, and was hiring for at least a few years).
Lispers seem to miss the fact, that when millions of students are exposed to C++ or Java, they keep on using them after university. While when they are exposed to Lisp, they remember it as some really bad memory, a language they would never touch again.
Language design is like the opposite to mountain climbing:
Q: Why design a new language?
A: Because it isn't there yet.
We wouldn't have Python if people took your "why design a new language" argument seriously. Language design would have stopped years ago, with that parochial attitude.
My wording was bad. I did not mean "Why design a new language?" in the general sense, I meant: "Why design a new language in the context of every software project?".
Designing a new language such as Python, Haskell, etc. is great. I find every new language great exploration. But I think creating a language-design platform such as Lisp is silly as I believe designing a new language whenever you write software is far from useful.
Peaker, carefully read what "sickofthisshit" wrote about Lisp macros -- he hit the nail on the head: they're extremely important and Python suffers from not supporting them.
I already replied as to why "sickofthisshit" is wrong, and explained how his example of a useful macro can be implemented just as nicely without a macro.
You are dead wrong about there being few cases where domain specific languages are useful.
Domain-specific languages are useful in many cases, but they are still a small percentage of most programming work. But even domain-specific languages, as I have shown, do not require a new syntax. They can be created in Python by overloading a new semantic to existing syntax (Operator overloading and instance composition).
I love Python and I write a lot of code in it, but the one big thing it's missing is macros. You can't just strap a decent macro system onto Python (or Java), because of Python's non-lisp-like syntax. Sure, Python has a parse tree api, but seriously, have you ever actually taken a look at it?!? It's *HORRIBLY* low level and totally inappropriate to implement a macro system with.
But as I explained, a macro's main power is that it takes its arguments unevaluated. This is possible by wrapping args in closures and not evaluating them. Python supports this (although with a bit cumbersome syntax), and thus almost every useful macro in Lisp can be rewritten as a function-that-takes-closures in Python.
Lisp's parenthesis are just as easy to get used to as Python's indentation. There's nothing unreadable about Lisp syntax, unless you simply don't know the language, in which case you're not qualified to criticize it.
There is a huge consensus about Lisp's syntax. Its the main point against its acceptance. It is very important to programmers how their language looks. Lisp syntax is harder to read, even after a few weeks of using it. Python syntax was immediately amazingly readable, after 2 days of toying around with it.
Sure, Python is great for whacking off web servers, but as you point out, it's not compiled, it's interpreted by its very design (which is why you seem to think that evaluating strings is as powerful as macros).
I don't think evaluating strings is nearly as powerful as macros, I just don't think that there are many cases in which that is requried (again, see my above claim about passing around closures).
You don't seem to get how important it is that Lisp code can be efficiently compiled, and that the programmer can deeply extend the compiler and tailor the language with macros.
I agree that the main point of macros is more optimized code, but I believe that:
The vast majority of software written is not about localized performance, but about minimizing round-trips and doing "the smart thing". Thus, much Python software is actually faster than much competing lower-level language software.
The effect of an optimized Lisp macro can be achieved by inlining the called function and the closure calls it uses. This should achieve the peformance gain in almost all uses of macros.
Optimization macros can be supported by the language, ones that let you control register allocation policy, inlining, etc. Lisp macros cannot currently do this. I believe this is much more difficult, though, than just writing the smaller portions that need to be fast in a lower-level language.
Lisp can pass around functions as well, *without* any performance hit, because our anonymous functions are compiled to machine code in advance just like our named functions are. But--guess what?--we don't use that mechanism to implement control structures because it turns out to be LESS readable and LESS convenient than real Lisp macros.
Maybe in Lisp, but in a language that has good closure syntax, what's the advantage of macros?
Why do I want macro transformations, if the same features can be achieved by passing around closures? Even if there's a very slight syntatic overhead of using a closure to basically denote: "I dont want this evaluated now", many would consider this an advantage because it makes it clear what code is evaluated when, and there's no need to look for "magic" in every used function.
To "prove" the point either way, please show any expressive power macros grant you, that is not possible without macros, using closures alone. By "possible without macros" I mean possible with the roughly the same amount of work for the macro user, up to a small factor of change. This means that if you can find a macro that reduces the amount of syntax I need to use to do something by a large factor, or by an order of magnitude, you win. If you can't, macros are unnecessary.
(with-open-file (stream "foo.txt")...code to work on foo.txt...)
My point is that the above is already implementable without macros.
In Python, for example, I can create a generic "with" that's even more powerful than (with-open-file) that does: def with((initializer, finalizer), func):
result = initializer()
try:
func(result)
finally:
finalizer(result)
Lisp macros are somewhat like a function that receives its arguments unevaluated. Sure, the function executes at read-time, but it could, in principle, do all the logic in run-time - as long as its arguments are unevaluated.
Now, suppose we provide the reverse feature, of saying "dont-eval-this" (much like Lisp's quote), and use normal functions instead of macros.
We may lose some performance (moving work from read-time to run-time), but we gain simplicity and readability.
In most dynamic languages, there is no "quote" operator, but instead there are first-class function objects which are, for most purposes, practically equivalent (as any piece of unevaluated code can be enclosed in a closure definition). So that in practice, aside for trivial syntax issues, (almost) every macro can be converted to a function call with a closure argument.
For example, the "loop" macro can be converted to a set of functions (for/while/etc) that receive the conditional as a closure, and the loop body as a closure. This approach is used by Smalltalk.
Advantages of this macro alternative: A. Simpler to enhance language, much easier than to write a macro B. More predictability and explicitness about the evaluation of code C. Does not require code to be representable as data
Disadvantages: A. Some macros may provide more syntatic sugar B. Performance, read-time work is moved to run-time.
I would say that Disadvantage A is moot because a nice readable syntax is something Lispers must give up in order to support macros in the first place. And that advantage B is not relevant for the vast majority of software development.
Thus, contrary to popular oppinion, macros don't really empower the developer, they just make it possible to create really powerful performance hacks at read-time. Their disadvantages far outweigh their advantages, and that is why they haven't won out.
Why design a new language to solve the problem? We have Python...
The main feature you get from Lisp macros that allow new features to solve specific problems, is a performance enhancement. The vast majority of features that use macros in Lisp, can be implemented via passing around functions in Python (very similar to unevaluated arguments). Sure, performance-wise it sucks, but in Python, that doesn't matter.
There are very very few cases where an actual new syntax or language is useful for a specific domain, and in those cases you can use an ugly String for parsing.
The real tradeoff in most cases is between a readable syntax (Python) and performance (Lisp macros).
Python is strongly typed, Perl isn't Python is polymorphic, Perl isn't Python has a few concise operators that implement hundreds of possible operations via polymorphism, Perl has hundreds of operators to implement hundreds of possible operations Python allows named arguments and reflection on those, Perl doesn't Python has proper exception handling, Perl doesn't Python has real classes and instances, Perl doesn't Python has real data structures with no arbitrary restrictions on what they can contain, Perl differentiates "scalars" from other objects, requiring reference hacks to build real data structures, and may actually cause dangling references(!)
But it's not just respect for the law, but respect for the artist that create this stuff, and a respect and understanding that it takes money to make this stuff.
It doesn't matter how much money it takes, the free market is to decide its value. It also takes money to create GPL software, it does not mean people must pay the author to use it. The only thing that "means" people need to pay the author, is the law. Copyright law is unjust in the eyes of the people or they would respect it.
Laws that are not enforced should be abolished, thus copyright should be abolished or enforced.
If copyright is enforced, then the people will vote to abolish it.
Think how much money it takes to make a movie, a video game, etc. This stuff doesn't happen for free. Get a job and some real life experience.
Are the extra movies or video games really good justification for copyrights? Another video game, or a movie with less acting and more effects, are those really worth criminalizing of the entire society?
Is it worth policing everything that's being copied by everyone?
Put things in proportions. What is more important? Another effect in a movie, another video game, or freedom and respect for the law?
A world where copying is all legal, is it really that bad?
Think of all the derivative works that are now illegal and could be created. Of all the developers and artists liberated from the financial instutitions as they crash, and starting to compete on artistic grounds alone...
A central repository of packages, and a GUI with more than 10000 packages, all installable with 2 clicks.
Automatic upgrading of all these packages.
Uniform interface to install, remove or upgrade all of these packages.
Automatic installation of packages according to file access attempts (auto-apt).
GUIs:
Desktop/network integration (i.e: ftp exploration works just like local file exploration) (and no, this does not work, not even in Windows XP, try copying files from one ftp to another, for example).
Panel applets bringing usefulness to the panel, as well as quick browsers/bookmark lists in the panel (Microsoft copied some of this)
Tabbed command-line consoles
Password-keeping wallets for all applications, allowing the user to remember just one password
Customization of desktop behavior, shortcut keys to basic operations such as minimizing/maximizing, and any other feature in the desktop.
Division of responsibility, window management keeps working even when applications hang.
Search feature in Configuration Manager.
Countless other innovations
Development tools:
The diff/patch tools.
gcc: A single compiler handling the compilation of a huge collection of languages, in a large set of platforms.
xemacs: An environment platform that allows extensions via a dynamic language with seamless on-the-fly compilation of the extension code you write. Also, the most featureful platform out there for this purpose, with powerful macro recorders/editors, customizable key binding, etc.
Languages: Python, Perl, Ruby. Microsoft is still behind in this area, despite its.NET technology, which is less innovation, and more an extension of the Java platform (I would even say, Java done right). Many more languages are Open Source, but I simply don't recall the exact history of other language to tell for sure.
Vast libraries in each of these languages, many of which are filled with technical innovation (i.e: Twisted Matrix, SDL, pygame)
Transparent RPC's for: Python, Ruby, Smalltalk. Microsoft, to the best of my knowledge, does not implement a single transparent RPC. (Transparent means that the server needs not be aware of what objects the client will use, nor does it require any code to explicitly export the object's features to the client, as Microsoft's COM/.NET technologies require).
Emulation:
CoLinux [colinux.org]: Modifying the Linux Kernel to run in kernel-mode side-by-side a host operating system.
bochs: Unprivileged, 100% user-space emulation of an entire PC.
qemu: Like bochs, but with dynamic code translation.
All in all, I may have misattributed a few innovations, but most of these are from Open Source. Also, there are many others I can't remember or simply don't know. Microsoft has done less innovation than Open Source, that much is obvious.
I would appriciate information fillers on innovations from other projects I'm less familiar with, such as Apache, the Kernel.
Actually, nobody needs to type in anything. They just click "add/remove programs" icon (kynaptic or synaptic), and then click the applications they want to install in a gui. Or they click "upgrade all".
Its much easier than browsing for your programs, downloading them without any knowledge of how spyware-infested they're going to be, answering multiple questions, and/or getting annoying nag-screens or usage obstacles meant to encourage you to buy the "real" program.
Guido van Rossum has shown a multimethod implementation in Python. That implementation supports your example as well, as the rules which define what types invoke which methods are easily extensible.
I am not dismissing closures. I do think Python could enjoy more powerful closure syntax (It does have closures, they just require a lot of syntax).
Python was just an example. As some other poster showed, Ruby can use closures to achieve the same feat just as well.
Well, how about adding object-oriented programming to a language which previously did not include it?
Multiple pre-CLOS object-oriented extensions to Lisp were written using heavy-duty macrology.
How about adding Prolog-style logic programming to a language which previously did not include it?
You can do so in Lisp, and macros are the best tool for the job.
How about adding an English-like syntax for defining common looping constructs? Lisp's infamous LOOP macro could be and was developed by *users* who didn't have to wait for some language implementor to do it for them.
How about a whole book's worth of code?
What about allowing simple application-oriented forms to declare and define multiple associated functions and data structures?
The basic fact is that Lisp programmers f*cking INVENTED the use of closures in programming, and they STILL PREFER MACROS by a large margin to implement control structures. Do you think they all are brainwashed, or stupid amnesiacs, or what? Does learning "defmacro" somehow block all memory of "lambda"? If it were just a matter of "good closure syntax", we'd use defmacro to define a nicer syntax and use it. But the plain fact is that the syntax is superficial---the expressive power is fundamental.
The code transformations possible greatly outnumber the total number of closures it is reasonable to ask a higher-order-function user to pass it. Furthermore, forcing the use of closures means the user of your utility has to jump through more hoops to use it, and makes your design more complicated.
Why don't you just show an example of a macro that cannot be just-as-reasonably (or almost-as-reasonably) implemented without the quirky evaluation rules?
Ofcourse a language that has no macros is going to need to be very powerful in the first place. And indeed, when Smalltalk programmers wanted looping constructs, they also didn't have to implement new language features. They just implemented methods that take closures as arguments and create very nice and readable loops:
(pseudo-Smalltalk):
(1 to: 10) do: [ i |
stdout write: i
]
[i < 10] do: [
stdout write: i
]
and in fact, that's exactly the kind of thing one has to do when working in functional languages with no macros, but (a) it's less elegant because you're making the programmer do some of the macro's work, and (b) this is still a pretty simple macro.
I find it a lot more elegant, as it uses simpler primitives to achieve the same goal. Also, it makes it very clear where the variables come from, even if I don't know the "with-file" function (explicit function arguments).
# This is not really longer than the macro example so you cannot say that you have to "do" some of the macro's work. What work?
data = with(open_file('/etc/passwd', 'rb', lambda stream: stream.read()))
Macros empower the developer by enabling the construction of syntactic abstractions -- each of which extends the syntax of the language. Like any other power, it is sometimes abused by the inexperienced; one can certainly write utterly unfathomable code using macros. But used well, macros greatly enhance the elegance, readability, and maintainability of code.
Instead of changing the syntax itself, one can have a rich syntax to begin with, and only overload the semantics of the syntax. Some things should never change, for readability's sake. Things such as when code is evaluated and when its not. Macros break this rule and make reading Lisp much harder. While I can read code that uses functions I do not know with relative ease, I have no idea what's happening when macros are used, because there are no evaluation rules that the code adheres to.
As for why macros are not more widely used, there are a couple of reasons. Lisp's minimalist syntax, so strange-looking at first glance, turns out to be one of its greatest advantages. The very simplicity of the syntax is exactly what makes it so powerful and general: user-defined constructs are invoked just like built-in constructs. While in principle a language with keywords and infix expressions could have an extensible grammar, syntactic extensions get much harder to manage in such a language because they tend to interact, causing ambiguities in the grammar.
Again, if you assume syntactic extensions are a good thing (as opposed to semantic extensions by overloading an existing rich syntax).
And the second reason is one the above post touches on when it mentions the representation of code as data. Lisp is the only major language to give programmers access to a standardized tree representation of source code. The fact that the representation is a tree makes Lisp macros powerful (contrast the pitifully weak "preprocessor macros" of C/C++, which operate on a character string representation), and the fact that the representation is standardized makes them portable.
Again, if you assume syntactic extensions are an advantage. (btw: Python does allow you access to its code tree, but its rather inconvinient).
I have plenty of experience in more mainstream languages, but when programming for myself, I almost always use Common Lisp. Macros are a major reason.
You are one of a very tiny minority.
Just recently me and a friend of mine wrote a LazyExpression object in Python.
It indeed takes a few more lines (About a factor of 3), but it supports more functionality (and is simpler!). I can use the "promise" (my lazy object) in any context, and automagically, new "promises" are created.
What happens if you use (car my-promise)? Will it create a promise to run car on the result of the promise when it is evaluated, as you would want it to, or will it return an arbitrary piece of data that you did not mean for it to return?
These promises are a lot less useful than the Python Lazy object because everyone using them must be aware of the fact that they are not actual results.
You're not solving the basic problem that macros solve, however. Receiving a function as a closure doesn't allow you to manipulate the function. You can use it as-is, but a lot of very powerful constructs require that manipulation.
...
I think that useful manipulations of this type should not be a function of the actual content of the function, but manipulations of the function object, and of what happens before/after the function.
Many of the macros used in Common-Lisp programs could not be rewritten as a function taking a closure. A trival example is PUSH.
Push is really something that the sequence types must support. Any generic macro definition such as PUSH is going to fail to be optimized on new sequence types. It is also more readable to support this operation as part of the sequence protocol, and to not support it where it is extremely expensive. In Python, if it is not possible to insert an element to a sequence without a very expensive operation, Python exposes this by requiring the specification of the expensive operation with a bit of extra syntax, and this is an advantage.
Bigger examples are DEFUN, DEFCLASS, DEFMETHOD (pretty much all of CLOS, really), etc.
This is not true:
def defun(name, func):
func.func_name = name
caller_namespace()[name] = func
return func
defun('a', closure)
def defclass(name, bases, items):
return new.class(name, bases, items)
Your loop example is particularly good. Languages like Python rely on hard-coded syntaxes for their looping constructs, which invariably express only a very limited subset of the looping constructs the programmer wants to use.
Python is not actually the good example I was talking about, in this case. I was referring to how Smalltalk implements looping.
Something like CL's LOOP macro is far more powerful (and wisely used, can be every-bit as readable), but could not be implemented as a function taking a closure.
Again, look at Smalltalk. Such a macro can be implemented as a set of functions that take a closure.
As for "giving up a readable syntax", I consider Lisp's much more readable than C++. Lisp is readable if you're used to reading Lisp. Its unreadable if you're not. The same is true of C++. Before anybody complains about Lisp's syntax being unreadable, they should have at least a thousand lines of code (in an actual program, not some homework assignment!) under their belt.
A language must have appeal, and that includes its syntax. If people feel they have to decipher the code through highly-nested expressions that all look alike, they are not even going to write 1000 lines of code in the language.
Other languages have a different syntax for the creation of builtin data types, for assignments, for attribute getting/setting, etc. This helps programmers read the program.
A thousand lines seems like a lot, but its a decent metric for seperating those who know Lisp and those who do not. Ask yourself: would you hire somebody who claimed to "know" C++, when they hadn't written more than a thousand lines in it?
I have written less than a thousand lines in Lisp, and indeed I wouldn't hire myself to write Lisp (unless I knew that I am a fast learner, and was hiring for at least a few years).
Lispers seem to miss the fact, that when millions of students are exposed to C++ or Java, they keep on using them after university. While when they are exposed to Lisp, they remember it as some really bad memory, a language they would never touch again.
This is not unimportant.
Q: Why design a new language?
A: Because it isn't there yet.
We wouldn't have Python if people took your "why design a new language" argument seriously. Language design would have stopped years ago, with that parochial attitude.
My wording was bad.
I did not mean "Why design a new language?" in the general sense, I meant: "Why design a new language in the context of every software project?".
Designing a new language such as Python, Haskell, etc. is great. I find every new language great exploration. But I think creating a language-design platform such as Lisp is silly as I believe designing a new language whenever you write software is far from useful.
Peaker, carefully read what "sickofthisshit" wrote about Lisp macros -- he hit the nail on the head: they're extremely important and Python suffers from not supporting them.
I already replied as to why "sickofthisshit" is wrong, and explained how his example of a useful macro can be implemented just as nicely without a macro.
You are dead wrong about there being few cases where domain specific languages are useful.
Domain-specific languages are useful in many cases, but they are still a small percentage of most programming work. But even domain-specific languages, as I have shown, do not require a new syntax. They can be created in Python by overloading a new semantic to existing syntax (Operator overloading and instance composition).
I love Python and I write a lot of code in it, but the one big thing it's missing is macros. You can't just strap a decent macro system onto Python (or Java), because of Python's non-lisp-like syntax. Sure, Python has a parse tree api, but seriously, have you ever actually taken a look at it?!? It's *HORRIBLY* low level and totally inappropriate to implement a macro system with.
But as I explained, a macro's main power is that it takes its arguments unevaluated. This is possible by wrapping args in closures and not evaluating them. Python supports this (although with a bit cumbersome syntax), and thus almost every useful macro in Lisp can be rewritten as a function-that-takes-closures in Python.
Lisp's parenthesis are just as easy to get used to as Python's indentation. There's nothing unreadable about Lisp syntax, unless you simply don't know the language, in which case you're not qualified to criticize it.
There is a huge consensus about Lisp's syntax. Its the main point against its acceptance. It is very important to programmers how their language looks. Lisp syntax is harder to read, even after a few weeks of using it. Python syntax was immediately amazingly readable, after 2 days of toying around with it.
Sure, Python is great for whacking off web servers, but as you point out, it's not compiled, it's interpreted by its very design (which is why you seem to think that evaluating strings is as powerful as macros).
I don't think evaluating strings is nearly as powerful as macros, I just don't think that there are many cases in which that is requried (again, see my above claim about passing around closures).
You don't seem to get how important it is that Lisp code can be efficiently compiled, and that the programmer can deeply extend the compiler and tailor the language with macros.
I agree that the main point of macros is more optimized code, but I believe that:
Lisp can pass around functions as well, *without* any performance hit, because our anonymous functions are compiled to machine code in advance just like our named functions are. But--guess what?--we don't use that mechanism to implement control structures because it turns out to be LESS readable and LESS convenient than real Lisp macros.
Maybe in Lisp, but in a language that has good closure syntax, what's the advantage of macros?
Why do I want macro transformations, if the same features can be achieved by passing around closures? Even if there's a very slight syntatic overhead of using a closure to basically denote: "I dont want this evaluated now", many would consider this an advantage because it makes it clear what code is evaluated when, and there's no need to look for "magic" in every used function.
To "prove" the point either way, please show any expressive power macros grant you, that is not possible without macros, using closures alone. By "possible without macros" I mean possible with the roughly the same amount of work for the macro user, up to a small factor of change. This means that if you can find a macro that reduces the amount of syntax I need to use to do something by a large factor, or by an order of magnitude, you win. If you can't, macros are unnecessary.
You are missing my point.
...code to work on foo.txt...)
(with-open-file (stream "foo.txt")
My point is that the above is already implementable without macros.
In Python, for example, I can create a generic "with" that's even more powerful than (with-open-file) that does:
def with((initializer, finalizer), func):
result = initializer()
try:
func(result)
finally:
finalizer(result)
def openfile(*args):
def initializer(): return open(*args)
def finalizer(file): file.close()
return (initializer, finalizer)
And then I can use:
with(openfile('filename', 'wb'), write_to_file)
Or I can use:
with(mymutex(blah.lock), blah.do_stuff)
Can you find an example that is implementable with macros, but not implementable without the quirky evaluation rules?
You missed my point.
My point is that such macros are implementable, including with-open-file (See my reply to the sibling post).
Lisp macros are somewhat like a function that receives its arguments unevaluated. Sure, the function executes at read-time, but it could, in principle, do all the logic in run-time - as long as its arguments are unevaluated.
Now, suppose we provide the reverse feature, of saying "dont-eval-this" (much like Lisp's quote), and use normal functions instead of macros.
We may lose some performance (moving work from read-time to run-time), but we gain simplicity and readability.
In most dynamic languages, there is no "quote" operator, but instead there are first-class function objects which are, for most purposes, practically equivalent (as any piece of unevaluated code can be enclosed in a closure definition). So that in practice, aside for trivial syntax issues, (almost) every macro can be converted to a function call with a closure argument.
For example, the "loop" macro can be converted to a set of functions (for/while/etc) that receive the conditional as a closure, and the loop body as a closure. This approach is used by Smalltalk.
Advantages of this macro alternative:
A. Simpler to enhance language, much easier than to write a macro
B. More predictability and explicitness about the evaluation of code
C. Does not require code to be representable as data
Disadvantages:
A. Some macros may provide more syntatic sugar
B. Performance, read-time work is moved to run-time.
I would say that Disadvantage A is moot because a nice readable syntax is something Lispers must give up in order to support macros in the first place. And that advantage B is not relevant for the vast majority of software development.
Thus, contrary to popular oppinion, macros don't really empower the developer, they just make it possible to create really powerful performance hacks at read-time. Their disadvantages far outweigh their advantages, and that is why they haven't won out.
Why design a new language to solve the problem? We have Python...
The main feature you get from Lisp macros that allow new features to solve specific problems, is a performance enhancement. The vast majority of features that use macros in Lisp, can be implemented via passing around functions in Python (very similar to unevaluated arguments). Sure, performance-wise it sucks, but in Python, that doesn't matter.
There are very very few cases where an actual new syntax or language is useful for a specific domain, and in those cases you can use an ugly String for parsing.
The real tradeoff in most cases is between a readable syntax (Python) and performance (Lisp macros).
I'd take the former any day.
Python is strongly typed, Perl isn't
Python is polymorphic, Perl isn't
Python has a few concise operators that implement hundreds of possible operations via polymorphism, Perl has hundreds of operators to implement hundreds of possible operations
Python allows named arguments and reflection on those, Perl doesn't
Python has proper exception handling, Perl doesn't
Python has real classes and instances, Perl doesn't
Python has real data structures with no arbitrary restrictions on what they can contain, Perl differentiates "scalars" from other objects, requiring reference hacks to build real data structures, and may actually cause dangling references(!)
I'd say the languages are pretty different.
But it's not just respect for the law, but respect for the artist that create this stuff, and a respect and understanding that it takes money to make this stuff.
It doesn't matter how much money it takes, the free market is to decide its value. It also takes money to create GPL software, it does not mean people must pay the author to use it. The only thing that "means" people need to pay the author, is the law. Copyright law is unjust in the eyes of the people or they would respect it.
Laws that are not enforced should be abolished, thus copyright should be abolished or enforced.
If copyright is enforced, then the people will vote to abolish it.
You're an idiot.
Think how much money it takes to make a movie, a video game, etc. This stuff doesn't happen for free. Get a job and some real life experience.
Are the extra movies or video games really good justification for copyrights?
Another video game, or a movie with less acting and more effects, are those really worth criminalizing of the entire society?
Is it worth policing everything that's being copied by everyone?
Put things in proportions. What is more important? Another effect in a movie, another video game, or freedom and respect for the law?
Think about it.
A world where copying is all legal, is it really that bad?
Think of all the derivative works that are now illegal and could be created. Of all the developers and artists liberated from the financial instutitions as they crash, and starting to compete on artistic grounds alone...
I could say the same about some Slashdot comments.
But I won't, because I chose to read your comment, it was not shoved down my throat.
Don't ask what your KDE can do for you.
Ask what YOU can do for your KDE.
Or do they rely on much user testing?
GUIs:
Development tools:
Emulation:
All in all, I may have misattributed a few innovations, but most of these are from Open Source. Also, there are many others I can't remember or simply don't know. Microsoft has done less innovation than Open Source, that much is obvious.
I would appriciate information fillers on innovations from other projects I'm less familiar with, such as Apache, the Kernel.
If you don't care much about speed, why use Java and not Python?
Python has a better learning curve, better readability, much more power and yes, better portability.
So why Java?
Actually, nobody needs to type in anything.
They just click "add/remove programs" icon (kynaptic or synaptic), and then click the applications they want to install in a gui. Or they click "upgrade all".
Its much easier than browsing for your programs, downloading them without any knowledge of how spyware-infested they're going to be, answering multiple questions, and/or getting annoying nag-screens or usage obstacles meant to encourage you to buy the "real" program.
Then you've got nutcases like Stallman and his war on semantics and ESR and his general dumbass tendencies weighing down the entire community.
The nutcases are those who think the purpose of Free Software is to create a good quality/price ratio of software.
Stallman simply emphasizes that Free Software is about emancipating the users of software, and about nothing else.
Having muscle tissue that supports less isn't necessarily less "fit" as it may be more energy-efficient or fault-tolerant, etc.
If we don't need to support the extra weight, there's probably good reason not to, as to gain other conflicting features.
What contract of the "ticket" am I signing exactly?
Also, on what law is the EULA's legal power based?