27 Jul 2015
Being used to Continuous Integration at work, I wanted to use it for my Lisp projects too. Looking around, the choice was pretty easy: TravisCI is a very nice platform developed by a company in Berlin, which offers free testing for open-source projects hosted at Github.
I saw that Luís Oliveira preceded me, so I followed the instructions at cl-travis and created a .travis.yml for all my libraries. Cl-travis contains a script that is run in the setup phase of the test and relies on CIM to provide a wrapper for common command line parameters of Lisp compilers. For the task at hand CIM works very well. Unfortunately, cl-travis has a few shortcomings:
- it hard-codes the implementation versions, so you can't test on multiple versions, e.g. the one you use at work for internal projects, and the latest one for the benefit of open-source developers
- it has to install a few system packages required for running the Lisp implementations, which means it forces the test to use the old infrastructure based on VMs that are setup for every single test, taking a few minutes to boot. If we can avoid installing packages from within the .travis.yml file, we can use the new infrastructure based on light-weight containers which are spawn almost instantaneously
- it lacks integration with the TravisCI UI, e.g. to distinguish between the implementation used for a test run and proper build parameters
All that works, but there could be better because Travis allows adding community support for a language, for which there is an excellent documentation. In short, a group of at least three people are required to guarantee support, given that Travis generally updates the base image every three months. Extensions must be written in Ruby(for the core build infrastructure) and CoffeeScript(for the UI). I'm looking for help so if you're interested I've opened a mailing list and a Github project.
Update: Fernando Boretti also blogged here about using cl-travis
27 Jul 2015 10:04pm GMT
22 Jul 2015
The Common Lisp Object System (CLOS) is pretty powerful. It gives you multiple inheritance, multiple dispatch, and many different ways to extend the behavior of methods. Underneath, most implementations use the Metaobject Protocol (MOP), a way of defining CLOS in terms of itself. As part of the MOP, classes are implemented as objects with several instance variables. Among those are variables that hold the class's name, its superclasses, and a list of the class's own instance variables. If you don't believe me, take the point class from the previous post:
(defclass point () ((x :accessor point-x :initarg :x :initform 0) (y :accessor point-y :initarg :y :initform 0)))
And use the Slime Inspector to inspect the point class object, which can be obtained by calling find-class:
The advantage of using the MOP is that it makes it possible to fine tune the behavior of CLOS by using ordinary object-oriented programming. A great example of this is the filtered-functions library which adds arbitrary predicate based dispatch to CLOS. But enough about the MOP.1 In this post I'm going to talk about one tiny piece of CLOS, update-instance-for-redefined-class.
Update-instance-for-redefined-class is a method which is called whenever a class is redefined (at runtime). By overriding it, you can customize what exactly happens at that point in time. For example, let's say you are using the above point class to represent complex numbers for some sort of simulation. As part of the simulation, you have a point object saved inside of the *location* variable:
After profiling the simulation, you find that one of the bottlenecks is complex multiplication. Since multiplication of complex numbers is much more efficient when they are represented in polar form, you decide that you want to change the implementation of the point class from Cartesian to polar coordinates. To do that (at runtime), all you need to do is run the following code:
(defmethod update-instance-for-redefined-class :before ((pos point) added deleted plist &key) (let ((x (getf plist 'x)) (y (getf plist 'y))) (setf (point-rho pos) (sqrt (+ (* x x) (* y y))) (point-theta pos) (atan y x)))) (defclass point () ((rho :initform 0 :accessor point-rho) (theta :initform 0 :accessor point-theta))) (defmethod point-x ((pos point)) (with-slots (rho theta) pos (* rho (cos theta)))) (defmethod point-y ((pos point)) (with-slots (rho theta) pos (* rho (sin theta))))
Basically, the code extends update-instance-for-redefined-class to calculate the values of rho and theta for the polar implementation in terms of the variables x and y from the Cartesian one. After extending update-instance-for-redefined-class the code then redefines the class, causing all of the existing instances to be changed over to the new implementation.2 Finally, two methods are defined, point-x and point-y, which preserve the interface for the point class.3 After running the code and then inspecting the contents of *location*, you should see:
Even though the object inside of *location* is still the same object, it is now implemented using polar coordinates! To make sure that it was converted from Cartesian to polar correctly, you decide to call point-x on the object to check that the x-coordinate is still the same:
Amazingly, all of the code continues to work even though the implementation of an entire class was completely changed. So anytime you want to change the implementation of a class that is part of a service that needs to be up 24/7 and just happens to be written in Common Lisp, remember to use update-instance-for-redefined-class.
22 Jul 2015 8:00am GMT
20 Jul 2015
Franz, Inc., a medium size software company in Oakland, CA (2 blocks from BART) is looking for a Software Developer to join their AllegroGraph group.
Links to the two positions:
20 Jul 2015 5:06pm GMT
14 Jul 2015
This is part 2 of Debugging Lisp. If you haven't read part 1, you can find it here.
In this post I am going to discuss another tool used for debugging Common Lisp - the Slime Inspector. The Slime inspector makes it possible to manipulate objects directly from the repl. You can do many different things with it, including clicking on objects to look at their contents and being able to copy and paste objects in order to reuse them in future function calls.1 Let's say you have the following point class:
(defclass point () ((x :accessor point-x :initarg :x :initform 0) (y :accessor point-y :initarg :y :initform 0)))
If you were to make an instance of the above class:
(make-instance 'point :x 10 :y 20)
You can then right click on it and click on the "inspect" option, or just use the Emacs shortcut "C-c C-v TAB" to peek inside the object:
This will show you the current values of all of the instance variables of the object. Not only can you look at the object's instance variables, you can modify them as well. Note that the power comes from being able to do all of this from within the debugger at runtime.
To make sure that the value of that object was actually changed, you can copy and paste the point object and then call the point-x function on it.
One more really cool tool that hooks into the Inspector is the Slime Trace Dialog. The Slime Trace Dialog is like ordinary trace, but it also allows for inspection on the objects that were passed to or returned from the traced functions. For example, let's say you are writing a tail call optimized function, sum, that sums all of the numbers in a list.
(defun sum (xs &optional (acc 0)) (if (null xs) acc (sum (cdr xs) (+ (car xs) acc)))) (sum '(1 2 3)) => 6
You can toggle the use the Slime Trace Dialog to trace sum by typing the shortcut "C-c M-t" and then typing in the name of function, "sum". After tracing it and running the code, you can press "C-c T" to enter the interactive Trace Dialog buffer. From there you can press "G" to refresh it and obtain the most recent trace.
The trace will look like the output from ordinary trace, except it will have some addition goodies. As I said above you can inspect all of the arguments and return values. You can also hide/show branches of the trace tree in order to make it easier to find what you are looking for.
The Slime Trace Dialog is invaluable when you have code which is passing lots of objects around and you aren't exactly sure what the value of each variable in each object is. You can just use the Slime Trace Dialog and have it keep track of all of the information for you.
All in all, the Slime Inspector is another amazing part of the Common Lisp debugging tool set. It comes in handy when the program crashes and you are unaware of the current state of the program. When combined with the rest of the features for debugging Common Lisp, the Slime Inspector is just incredible.
14 Jul 2015 9:12pm GMT
14 Jul 2015 3:42pm GMT
13 Jul 2015
Declt 2.0 "Kathryn Janeway" is out. This release doesn't contain any change in functionality, yet deserves a major version upgrade since it contains 3 important changes: an infrastructure revamp (along the lines of what Clon endured not so long ago), a license switch from the GNU GPL to a BSD one, and finally a system / package name change. The prefix is now
net.didierverna instead of
com.dvlsoft. Do I need to apologize for this again? :-)
Find it at the usual place...
13 Jul 2015 12:00am GMT
10 Jul 2015
This Quicklisp update is supported by my employer, Clozure Associates. If you need commercial support for Quicklisp, or any other Common Lisp programming needs, it's available via Clozure Associates.
- check-it - A randomized property-based testing tool for Common Lisp. - LLGPL
- cl-gists - Gists API Wrapper for Common Lisp. - MIT
- cl-git - A CFFI wrapper of libgit2. - Lisp-LGPL
- cl-opsresearch - Common Lisp library for Operations Research. - GPL3
- cl-scripting - Utilities to help in writing scripts in CL - MIT
- hu.dwim.graphviz - Graphviz layouting using CFFI bindings. - public domain
- jp-numeral - A printer for Japanese numerals. - MIT
- quickapp - A utility library to automate much of the app creation process - Modified BSD License
- simple-tasks - A very simple task scheduling framework. - Artistic
- terminfo - Terminfo database front-end. - copyrights
- trivial-main-thread - Compatibility library to run things in the main thread. - Artistic
- trivialib.type-unify - unifies a polimorphic type specifier with type variables against actual type specifiers - LLGPL
Updated projects: arrow-macros, binascii, birch, bit-smasher, buffalo, burgled-batteries.syntax, caveman, cerberus, cl-ana, cl-ansi-term, cl-async, cl-charms, cl-clon, cl-coveralls, cl-dbi, cl-freetype2, cl-growl, cl-isaac, cl-ledger, cl-libssh2, cl-libuv, cl-marklogic, cl-mongo-id, cl-netstring-plus, cl-olefs, cl-rabbit, cl-readline, cl-reexport, cl-rethinkdb, cl-rss, cl-sdl2, cl-slug, cl-spark, cl-string-match, cl-uglify-js, cl-voxelize, cl-yaclyaml, clack, clfswm, closer-mop, coleslaw, colleen, com.informatimago, command-line-arguments, common-doc-plump, commonqt, croatoan, dbus, declt, defclass-std, dexador, dissect, djula, docparser, drakma, dyna, eazy-gnuplot, fare-csv, fast-http, flexi-streams, frpc, generic-sequences, glass, glyphs, hemlock, hu.dwim.common, hu.dwim.def, hu.dwim.logger, hu.dwim.uri, hu.dwim.util, hu.dwim.web-server, hunchentoot, immutable-struct, integral, intel-hex, iolib, jonathan, jsown, lack, legion, let-over-lambda, lisp-interface-library, lisp-invocation, lisp-unit2, lucerne, madeira-port, marching-cubes, mathkit, mcclim, media-types, mexpr, mk-string-metrics, nibbles, ningle, optima, osicat, perlre, pileup, postmodern, pounds, pp-toml, priority-queue, prove, qlot, qmynd, qt-libs, qtools, quadtree, quicklisp-slime-helper, quri, rutils, sb-cga, screamer, scriba, serapeum, slime, smackjack, staple, stumpwm, sxql, transparent-wrap, trivial-download, trivial-features, trivial-lazy, trivial-signal, trivial-update, type-r, uiop, unix-opts, varjo, verbose, vgplot, weft, woo, wookie, workout-timer, x.fdatatypes, x.let-star, yaclml.
10 Jul 2015 7:59pm GMT
07 Jul 2015
This post is the start of a series on how to debug Common Lisp code, specifically with Emacs, Slime, and SBCL. If you do not understand Common Lisp, you should still be able to follow along and recognize just how powerful the facilities provided by the Common Lisp debugger are. Nathan Marz asked me to write these posts since he thought many of the tools for debugging Common Lisp were pretty cool.
The first thing you need to do in order to get started debugging Common Lisp is to set your Lisp's optimization qualities. Optimization qualities are basically a group of settings which allow you to specify what the compiler should optimize for. These qualities include speed, space, compilation speed, safety, and debugging. If you do not run the code below, which tells the compiler to optimize for debugging, almost none of the examples in this post will work.
CL-USER> (declaim (optimize (debug 3))) NIL CL-USER> (your-program) ...
With the compiler optimized for debugging, it becomes possible to do pretty much everything at runtime. This post will show you how Tom, an experienced Lisp developer would debug and patch a buggy function at runtime. Let's say that Tom has the following code which implements the well known Fibonacci function:
(defun fib (n) (if (<= 0 n 1) (/ 1 0) (+ (fib (- n 1)) (fib (- n 2)))))
There's just one problem, the code isn't correct! Instead of returning n in the base case, the code winds up dividing by zero. When Tom tries to calculate the tenth Fibonacci with this code, a debugger window pops up because an error was signaled.
Realizing that he has entered the debugger, Tom wonders what has gone wrong. In order to find the bug, Tom decides to insert a breakpoint into the function.1 In Common Lisp, breakpoints are implemented as a function called 'break'.2 To insert his breakpoint, Tom adds a call to break at the beginning of fib. After adding the breakpoint, Tom then puts his cursor next to one of the frames and hits the 'r' key in order to restart it. In this case, Tom decided to restart the frame where n was three.
By restarting the frame, Tom basically traveled back in time to the beginning of the frame he restarted. After restarting the frame, the debugger immediately hits the breakpoint Tom had just added. From there Tom steps through the code by hitting the 's' key. He eventually realizes that the base case is implemented incorrectly and that that is why he received the error.
After finding the source of the problem, similar to how he had previously inserted the breakpoint, Tom patches the code. He replaces the base case with n and removes the breakpoint he had previously inserted.
After recompiling the code, Tom once again restarts one of the frames. Since he was previously stepping through code, the debugger starts stepping through the frame Tom decided to restart. Tom just taps the '0' (zero) key in order to invoke the step-continue restart3 and continue normal execution. Because Tom restarted a frame which occurred before the bug, and now that the bug is gone, the code runs as if there had never a bug in the first place!
Let's recap what happened. After the code signaled an error, Tom found himself in the debugger. Tom was able to insert a breakpoint and poke around until he found the source of the problem. After finding the problem, Tom patched the code and restarted the process from a point before it had signaled an error. Because Tom had corrected the code, after he restarted the frame, it acted as if nothing had ever gone wrong!
The ability to recompile code at runtime is just one of the many incredible features provided by Common Lisp. Next time, I'm going to talk about the Slime inspector, which makes it possible to look into and modify objects from within debugger.
07 Jul 2015 8:37pm GMT
06 Jul 2015
Here are the top 100 downloads for June, 2015:
06 Jul 2015 3:51pm GMT
01 Jul 2015
I gave a talk at ELS 2015 in London in April about the past, present, and future of Quicklisp. The "future" part detailed several things I'd like to accomplish before removing the beta label from Quicklisp.
The slides and script of the talk are available on github. But since there are over a hundred slides and about twenty pages of script, I thought I'd summarize things in this post.
First, what's Quicklisp for, anyway? The slogan I put in the talk is: Make it easy to confidently build on the work of others. (Also, work on as many Common Lisps on as many platforms as possible.)
Quicklisp achieves part of that already. It runs well on almost all Common Lisp implementations on all platforms. It's easy to install, use, and update. Things are tested together so everything usually works. But if something breaks on update, you can revert to a previous working version. And with those features you can build on hundreds of libraries already.
If it can do all that, why not drop the "beta" already? There are still a number of things that I want Quicklisp to do before I'm ready to say "Here, this is what I had in mind from the start."
First, I'd like to improve the confidence in the code you download and run. By adding HTTPS, signature checking, and checksum validation, you can be sure that there is nobody intercepting and modifying the software provided by Quicklisp. The signature and archive integrity checks must be made complete and automatic to have the best results.
Second, I'd like to add comprehensive user and developer documentation. For users, that means being able to learn each command, feature, and behavior of Quicklisp, to be able to use it to its fullest. For developers, that means being able to build your own solutions on a Quicklisp foundation without starting from scratch.
Third, I'd like to make it easy to find the project that does what you need, evaluate its quality and popularity, and find out if its license is compatible with your goals. If you want to make changes to a project, I want it to be easy to get the original source of a project and send fixes or improvements to the upstream maintainer.
Fourth, I'd like to make it easy to hook into the archive-fetching component of Quicklisp in a way that makes it easy to support additional integrity checks, support local development policies, and add local mirrors or caches for Quicklisp software.
These changes and improvements will take time. When they're done, I'll be happy to drop "beta" from Quicklisp.
01 Jul 2015 3:44pm GMT