From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: egnarts-ms Newsgroups: gmane.emacs.devel Subject: CL package serious deficiencies Date: Mon, 6 Feb 2012 06:18:37 -0800 (PST) Message-ID: <33271707.post@talk.nabble.com> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit X-Trace: dough.gmane.org 1328537941 7115 80.91.229.3 (6 Feb 2012 14:19:01 GMT) X-Complaints-To: usenet@dough.gmane.org NNTP-Posting-Date: Mon, 6 Feb 2012 14:19:01 +0000 (UTC) To: Emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Mon Feb 06 15:18:57 2012 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([140.186.70.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1RuPPF-0003VZ-AD for ged-emacs-devel@m.gmane.org; Mon, 06 Feb 2012 15:18:57 +0100 Original-Received: from localhost ([::1]:37783 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RuPPE-00079t-N6 for ged-emacs-devel@m.gmane.org; Mon, 06 Feb 2012 09:18:56 -0500 Original-Received: from eggs.gnu.org ([140.186.70.92]:46636) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RuPP3-00079F-Bf for Emacs-devel@gnu.org; Mon, 06 Feb 2012 09:18:54 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1RuPOx-0000FJ-0b for Emacs-devel@gnu.org; Mon, 06 Feb 2012 09:18:45 -0500 Original-Received: from sam.nabble.com ([216.139.236.26]:55881) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RuPOw-0000FC-Q6 for Emacs-devel@gnu.org; Mon, 06 Feb 2012 09:18:38 -0500 Original-Received: from isper.nabble.com ([192.168.236.156]) by sam.nabble.com with esmtp (Exim 4.72) (envelope-from ) id 1RuPOv-0005qP-PT for Emacs-devel@gnu.org; Mon, 06 Feb 2012 06:18:37 -0800 X-Nabble-From: egnartsms@gmail.com X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 2) X-Received-From: 216.139.236.26 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:148258 Archived-At: Hello to everyone ! In this message I would like to share my (mostly negative) experience with CL package of Elisp. I'm sure, some Emacs/Elisp gurus are already familiar with many of these, but I still believe I have to say something new. Let's start. 1. The most striking thing is the way symbol macros are implemented: authors of CL merely put cons cells ("symbol-name" ) onto `cl-macro-environment' variable, and when the time of possible macroexpansion comes, this alist is searched with assq -- that it, strings are compared with `eq'. This obviously is not correct. Look at this example: (defmacro test-macro () (let* ((symbol-1 'sym) (symbol-2 (make-symbol (symbol-name symbol-1)))) `(let ((v1 0) (v2 0)) (symbol-macrolet ((,symbol-1 (incf v1)) (,symbol-2 (incf v2))) ,symbol-1 ,symbol-2 (list v1 v2))))) (princ (test-macro)) This code prints (0 2), when it should print (1 1): that's because the same string object serves the purpose of being the symbol name for 2 distinct symbols. This situation is only possible if we deal with uninterned symbols (and in more-or-less serious Lisp programming this practice is quite common). I tested this exampe (as well as all the following ones) in CLISP 2.41.1; it prints (1 1). 2. Generalized variables. `get-setf-method' works by calling `macroexpand' when it cannot find a setf-method for a form. `macroexpand' honestly expands this form the whole way down, without regarding to all the intermediate forms; http://www.lispworks.com/documentation/HyperSpec/Body/05_abg.htm Common Lisp uses `macroexpand-1' for the same purpose. This means that in case of any intermediate macroexpansion result having a setf-method defined, it will be ignored. Only the end non-macro-call form is considered for setf-method. I cannot give right away a good example of a harm this may cause. Nevertheless, this behavior seems fishy.. for instance, defining setf-methods for macro names may lead to counterintuitive things: imagine there is some other macro named B that expands into the call of this macro (named, say, A), and A expands into a non-macro form X (for instance, just car of smth). Given that B has no setf-method defined, when `get-setf-method' searches for the setf-method for B, the setf-method for A doesn't count at all: it is just skipped. X is what is searched in this case. `macroexpand-1' is absent in Emacs Lisp. 3. The way `get-setf-method', `incf', `decf', `push', `pushnew' and `pop' deal with symbol macros. Look at this: (defun get-setf-method (place &optional env) (if (symbolp place) (let ((temp (make-symbol "--cl-setf--"))) (list nil nil (list temp) (list 'setq place temp) place)) ... `get-setf-method' is absolutely ignorant of symbol macros: the fact that "place" satisfies "symbolp" doesn't in any way mean it is a simple variable, since we have a concept of symbol macro in the language. The same thing is true about all 5 functions listed above. To see a real example, consider the following: (cl-macroexpand-all '(symbol-macrolet ((s (cadr (get-some-list)))) (incf s))) which results in (let* ((--cl-x-- (get-some-list))) (setcar (cdr --cl-x--) (1+ (cadr (get-some-list))))) this calls "get-some-list" 2 times, which is apparently erroneous. Again, Common Lisp makes only 1 call. 4. `cl-macroexpand-all'. This should be blamed for 2 things. First, it doesn't macroexpand all, in contrast to what its name states. Try out this: (cl-macroexpand-all '(let (((car x) 10)) (body-1))) You get the following result: (letf (((car x) 10)) (body-1)), and this is not the result of the macroexpansion ! Yes, I agree that this case is unlikely: `let' is not supposed to bind places, this feature was supposed to be internal to CL implementation.. but wait, this function is nevertheless cheating. It doesn't do what it must; it reckons upon someone else to finish the job. In some advanced, sophisticated code this hidden flaw may suddenly show itself. Second, look at the following code: ((eq (car form) 'setq) (let* ((args (cl-macroexpand-body (cdr form) env)) (p args)) (while (and p (symbolp (car p))) (setq p (cddr p))) (if p (cl-macroexpand-all (cons 'setf args)) (cons 'setq args)))) This is actually a cond clause from `cl-macroexpand-all'. See, it looks whether any of "setq" targets in not a simple symbol, and if it's not, we end up with a "setf" form being processed instead of original "setq" form. We have already discussed that problem: full expansion of "setq" arguments. No intermediate setf-methods have a chance to come up and be considered. 5. Loop facility, if/when/unless clause. This is the most violent point of all above. To put it short, in the loop clause that follows "if" we can access the result of evaluation of the condition with the name "it". But have a look at how they have implemented that "it": (setq form (list* 'if (list 'setq temp cond) (subst temp 'it form))) Just subst, and that's all. There's no surprise that when I put my anaphoric "awhen" construct (inspired by Paul Graham) inside the clause following "when" in a loop, I got something uncompilable. Conclusion I can draw the only conclusion from all above: Elisp has not been used much to create true Lispy programs. Features like symbol macros and generalized variables were introduced to be quite close to those respective concepts of Common Lisp, but they are still not that mature. I've managed to fix all above (except `pop', `push', `incf'.. -- they proved hard to be changed and recompiled correctly), and I'm still using Emacs, and I'm still programming in Elisp. I'm sure Elisp does his job of being an excellent training ground for learning Lisp concepts. -- View this message in context: http://old.nabble.com/CL-package-serious-deficiencies-tp33271707p33271707.html Sent from the Emacs - Dev mailing list archive at Nabble.com.