I started looking at Edi Weitz's CL-FAD to pick up some good coding practices. One thing caught my eye when looking at cl-fad.asd. In defsystem Weitz uses :serial t which, if I understand correctly based on the docs, instructs ASDF to include :components in order of appearance. This, it seems to me, should make :depends-on redundant in such a context. Is there a reason why Weitz included the :depends-on anyway, or is it just an oversight?
Here's the defsystem part (latest Github clone):
(asdf:defsystem #:cl-fad
:version "0.7.2"
:description "Portable pathname library"
:serial t
:components ((:file "packages")
#+:cormanlisp (:file "corman")
#+:openmcl (:file "openmcl")
(:file "fad")
(:file "path" :depends-on ("fad"))
(:file "temporary-files" :depends-on ("fad")))
:depends-on (#+sbcl :sb-posix :bordeaux-threads :alexandria))
(asdf:defsystem #:cl-fad-test
:version "0.7.2"
:serial t
:components ((:file "packages.test")
(:file "fad.test" :depends-on ("packages.test"))
(:file "temporary-files.test" :depends-on ("packages.test")))
:depends-on (:cl-fad :unit-test :cl-ppcre))
Friends don't let friends use cl-fad.
cl-fad is the wrong place for "best practices" of any kind. It's a quick and dirty not-so-portable portability layer.
Use UIOP instead.
It is possible that doing both serial and on-depends would create a conflict, i.e. that the acyclic graph defined by the on-depends wouldn't be compatible with the ordering given by sequence of the components. I doubt, but who knows, if asdf actually checks for that.
So sure, that's redundant. But yeah, redundant isn't necessarily a bad thing. Stating the on-depends in addition to the serial might provide a bit-o-info for the reader about the structure of the code.
And the developer might occasionally comment out the serial to gain the benefits that follow from that.
Related
Over the weekend, I had a name clash that was very hard to track down, but I managed to boil it down to a short example - thing is, I thought the package system was supposed to protect me from this, so I'm wondering how it can in future.
If I do this:
(ql:quickload "cl-irc")
(defpackage #:clash-demo
(:use #:cl
#:cl-irc))
(in-package #:clash-demo)
;; This is the name that clashes - I get a warning about this if I compile
;; this interactively (i.e. from slime) but not if I quickload the whole project.
(defun server-name (server)
(format nil "server-name ~a" server))
;; This needs an IRC server to work - if you have docker
;; then this will do the trick:
;;
;; docker run -d --rm --name ircd -p 6667:6667 inspircd/inspircd-docker
(defparameter *connection*
(cl-irc:connect :nickname "clash-demo"
:server "localhost"
:port 6667
:connection-security :none
:username "username"))
After the above, I get the following warning when defining server-name:
WARNING: redefining CL-IRC:SERVER-NAME in DEFUN
And the following error if I try and print *connection* (in my more full-fledged project I got a missing slot in a class that I'd defined - I think the root cause of both the problem I found and the minimal example above is the same though):
Control stack guard page temporarily disabled: proceed with caution
While I get the warning if I define things interactively, in practice I moved a bunch of code into a quickproject:make-project'd and ql:quickload-ed it, which I think silenced the warning as it always loaded cleanly, hence why it took me so long to track down the name clash.
My questions are:
Isn't the package system supposed to protect me from this? I think I can sort of see why the above happens - the reader's already seen the symbol server-name so it thinks I'm referring to the already defined cl-irc:server-name, and re-uses that - but surely the package system should somehow allow me to work around this?
I'm assuming the warning when I quickload-ed the project was silence because quickload assumes I don't want to see warnings from projects, is there a way I can make this more forceful when I load projects I'm making so that it raises an error, or at least warns me of these name clashes? For all I know there are a bunch more that just haven't caused me a problem yet.
I was expecting either (i) the names not to clash (i.e. my file would define the symbol clash-demo:server-name, not re-use cl-irc:server-name and cause it to be redefined) or (ii) this to be an error, or at least a warning when I quickload the project.
Thanks very much in advance for any advice!
Suppose you really like packages A and B and want to :use both of them in your package MINE. They have a hundred external symbols each and you don't want to have to type any package prefixes. However, they both export a symbol with the same name, a:frob and b:frob. If you simply :use them, you will get a symbol conflict.
To resolve the conflict, there are three options to decide what to do when you're in package MINE and you refer to the unqualified symbol frob:
Prefer A so it refers to the the symbol a:frob: (defpackage mine (:use a b) (:shadowing-import-from a frob))
Prefer B so it refers to the symbol b:frob: (defpackage mine (:use a b) (:shadowing-import-from b frob))
Prefer neither so it refers to mine::frob: (defpackage mine (:use a b) (:shadow frob)) - then, to use one from A or B you must write a:frob or b:frob explicitly
Any of these three cases may be preferable depending on your situation. Common Lisp will not automatically choose one for you. I think this is a reasonable design choice.
Briefly, no: the package system is not meant to protect you against this. If you use a package CL-IRC then you're saying that you want, for instance, to get the symbol CL-IRC:SERVER-NAME when you type server-name. What you are not saying is whether you should be allowed to modify the values associated with that symbol in any way, which is an orthogonal question. The package system is just about names, not values.
In the case of functions, then it's very often (but not always! consider loading patches) a mistake to define a function with a given name in multiple contexts. In the case of variables that's slightly less clear: it's probably a mistake if there are multiple def* forms for a given variable in different contexts, but simply assigning to the variable might well be fine.
So what is needed is a way for defining macros (defun etc) to be able to detect this and complain about it.
CL does not provide such a mechanism. Many implementations do however, either by detecting 'different contexts' (which I have been vague about) or by providing a way of saying that certain packages are sacred and redefinitions should not be allowed, or both.
In this case, the implementation has warned you about the redefinition, but Quicklisp may have suppressed that. I am not sure how to desupress warnings like this in Quicklisp.
In summary the answer is that the problem of controlling and limiting redefinition is orthogonal to what the package system does, and unfortunately CL does not provide a standard solution to this second problem.
If you are interested I have a little shim which uses the condition system to make very sure warnings are treated as errors in contexts like this. I could append it to this answer, but not until after Christmas probably.
I am working with SBCL (SBCL 1.2.13.84-7d75f89) learning Common Lisp from this book. I have run into a problem, trying to find and load the package named multiprocessing.
(This is in Chapter 29 of the book)
I have tried doing (ql:system-apropos "multiprocessing"), (ql:system-apropos "thread"), (ql:system-apropos "smp") trying to see if there is a quicklisp package that uses it.
I have also searched using google, and even at Quickdocs but I seem to be failing somewhere.
I would be grateful for any assistance.
The example in the book uses the web server AllegroServe from Franz Inc. and the corresponding Allegro Common Lisp (ACL). ACL has a package named multiprocessing which provides the needed multiprocessing facilities.
The book proposes to use PortableAllegroServe for those who don't use Allegro Common Lisp. See chapter 26 in the book.
PortableAllegroServe has a package named acl-compat.mp, which provides the necessary functionality in a portable way. For example acl-compat.mp:with-process-lock, acl-compat.mp:make-process-lock, ...
You thus need to either
AllegroServe and Allegro Common Lisp
PortableAllegroServe and a Common Lisp implementation it runs in
The names of the packages will be slightly different, though.
Note that this chapter is one which might need some updating. I'm not sure how much PortableAllegroServe is used these days...
I have been using Emacs since version 18. Emacs Lisp isn't my routine programming language, but years ago I invested some time studying it to the point of creating a .emacs that's better (for me) than any GUI IDE to date.
That was a one-time effort and since then, I forgot completely how to program in lisp.
Alas, every time I upgrade my Emacs (18 > 19 > 20 > 21 > 22 > 23), something in my .emacs breaks, and I end up spending way too many hours (sometimes days) fixing these.
In many other languages I program routinely, it is possible to write code that never becomes obsolete. In emacs, on the other hand, I can never predict how things will change. For example [M-TAB] that used to work up until version 21.4.1, no longer works in version 23 and must be replaced with "\M-\t". Another example is dired-omit-toggle that used to work in version 21 but stopped working in version 22, being replaced by dired-omit-mode.
Now, I know that if a .emacs doesn't do much, it's possible to write "an almost empty" .emacs that can (probably) stay compatible with future versions.
But my .emacs is huge, designed to run on many different operating systems (and their different flavors, editions and versions, including non-GUI systems) without a single change. I wish there was a core-API or subset that is guaranteed to always work.
Is there really such a way to write a .emacs that will always stay upward compatible?
If so, where can I find a "cook book" or authoritative guidelines for accomplishing this?
Use (when (boundp 'some-variable) …) or (when (fboundp 'some-function) …) around any piece of code that relies on a specific feature. (While you're at it, start with (require 'cl) for those older versions that don't have when built-in.)
When all else fails, discriminate on emacs-major-version, emacs-minor-version and running-xemacs (defined as (string-match "XEmacs\\|Lucid" emacs-version)).
Avoid syntax and library functions that are only supported in newer versions.
It's rare that something breaks when you stick to documented interfaces. So try to look for a way to do things that's mentioned in the manual, and only fall back to modifying some random non-customizable variable if you see no other way. In my experience there is always a reasonably easy way to get something to work in all versions (at least with GNU Emacs, XEmacs is sometimes harder to please) if you allow the occasional conditional.
For example, "\e\t" has always worked for M-TAB. With dired-omit-mode, fall back to dired-omit-toggle if the former does not exist:
(set (if boundp 'dired-omit-mode 'dired-omit-mode 'dired-omit-toggle) t)
Yes, it's slightly painful, but not as dramatic as you make it out to be. I maintain a .emacs that works with anything since 19.23 (IIRC, it's been a while since I tested with anything older than 19.34) on all of DOS, Windows and unix. Compatibility with Windows is in fact more of a burden than keeping up with GNU Emacs version changes.
As for a cookbook, well, most differences between versions have to do with features that aren't very widely used (otherwise the maintainers would give more importance to strict upward compatibility). Since Emacs is big, there's undoubtedly plenty of it that you use but the cookbook writer wouldn't have heard of. You'll have to play it by ear. Fortunately it's not too hard.
Since Its impossible to predict future changes of anything, no one can guarantee the future compatibility.
I think the following points are few of many general ways to make it easy to maintain .emacs or init.el (which I am practicing right now.)
put .emacs.d/ version control (MUST one)
split init file into several small files.
use when to load specific customizations for a version of emacs.
for eg:
(when (= emacs-major-version 24)
;;load my settings for 24
)
I sympathize, and I share your pain. The answer is no, there is no such holy grail, I'm afraid. As you said, if your init file is simple enough then you might not need to change anything. Actually, even that's not true: the init file name and where Emacs looks for it have both changed over time.
Just recently, I made some changes to my org configuration as I had been making some changes in my daily work framework. That broke a part of my configuration.
(tags-todo "School"
((org-agenda-skip-fuction '(org-agenda-skip-entry-if 'scheduled))
(org-agenda-overriding-header "School Work for today: ")))
Particularly, agenda entries which are scheduled are not being skipped. A typical such entry is as follows:
** TODO Make weekly test papers for next week, classes 9-12, for Maths, Sci etc.
SCHEDULED: <2010-10-09 Sat +1w>
Earlier after a lot of effort, I had created a regular expression check which used to skip such entries. Of course, org-agenda-skip-entry-if 'scheduled is much better than that.
I know c#, but no lisp as such. Kindly help.
Super-old question, but just in case this helps you or someone else: the code you pasted in has org-agenda-skip-fuction instead of -function. =)
I've been wanting to teach myself Lisp for a while. However, all the interpreters of which I've heard involve some flavor of emacs.
Are there any command line interpreters, such that I could type this into the command line:
lispinterpret sourcefile.lisp
just like I can run perl or python.
While I'd also like to become more familiar with Emacs (if only not to be frustrated when I work with somebody who uses Emacs), I'd rather decouple learning Emacs from learning Lisp.
Edit: I actually want to follow SICP which uses Scheme, so an answer about Scheme would be more useful. I'm just not that familiar with the differences.
You could also try DrScheme, which whilst not exactly a standalone interpreter, isn't emacs :)
It's basically a simple IDE that has an area to type in code that can be executed as a file, and then another area that is the running interpreter that you can interact with.
(Also, find the UC Berkeley CS61A podcasts and listen to them, as well as reading SICP)
It looks like Steel Bank Common Lisp (SBCL) also caters to what you want:
http://www.sbcl.org/manual/#Shebang-Scripts
SBCL is both top rate and open source.
Checkout CLISP wiki-link that ie. was used by Paul Graham
Direct link
I often write lisp shell scripts which start with this line:
#!/usr/bin/clisp
Then you don't even need to type "lispinterpret" on the command-line. Just mark the script executable and run it directly.
Most scheme interpreters that I am familiar with can be run from the command line. (Much of the list below is extracted from the comparative table at Alexey Radul's Scheme Implementation Choices page. There is a more extensive list at schemewiki but that page does not immediately provide command-line invocation syntax.)
Here's how you run a number of implementations at the command line:
Chez Scheme: scheme, petite
MIT Scheme: mit-scheme
Scheme 48: scheme48
RScheme: rs
Racket: racket (But I recommend trying the DrRacket IDE, especially for beginners.)
Guile: guile
Bigloo: bigloo
Chicken: csi
Gambit: gsi
Gauche: gosh
IronScheme: IronScheme.Console
Kawa: kawa, java kawa.repl
Larceny: larceny
SCM: scm
If you are looking for Scheme to work with the SICP, take a look at MIT/GNU Scheme
http://groups.csail.mit.edu/mac/projects/scheme/
http://www.gnu.org/software/mit-scheme/index.html
The most widely used IDE for Common Lisp, particularly in the free software subset of the community, is in fact SLIME, which runs on Emacs. You can use whatever CL compiler you prefer and invoke Lisp source files the way you describe, but if you do that, you won't be taking advantage of many of Lisps dynamic features that are so incredibly useful while developing your application.
I suggest you take a look at this SLIME demonstration video to see what I mean, even though it might be a bit outdated at this point.
If the problem is that you (think you) don't like Emacs, I seriously suggest you try to learn it. Seriously. No, really, I mean that. However, there are alternatives, such as the IDEs provided by commercial Lisp implementations such as Allegro and Lispworks (free trials available), or an Eclipse plug-in called Cusp.
Did you try Allegro CL from http://www.franz.com/?
#Nathan: I've upmodded the Common Lisp links, because you asked about Lisp (especially with reference to Emacs Lisp). However, Common Lisp is very different from Scheme. A program written for one is unlikely to run on the other.
As you mentioned, SICP is for learning Scheme, not Lisp (or at least, not Common Lisp and not Emacs Lisp). There are some overlap in principles, however you can't simply cut and paste code from SICP and expect it to run on any Common Lisp or Emacs Lisp system. :-)
No "interpreter" requires emacs.
Also, emacs can run elisp in a headless manner.
It seems like scheme shell is suitable for your purpose.
Take a look at http://www.scsh.net/index.html
Another good dialect of lisp is cmucl. They used to love to brag about being the "fastest" lisp.