As part of my project to learn common lisp, or at least write more common lisp as part of my day to day work and life, I've
This is a total rip off of this blog post, with a few minor changes:
I hacked some
makefile goodness so that it will automatically create
binaries for all
.lisp files, and means that you can drop a script
in the directory and not have to edit the makefile to get the magic
TARGETS := $(subst .lisp,,$(wildcard *.lisp)) all:$(TARGETS) %:%.lisp @echo [build]: creating $@ @buildapp --load $< --entry script:run --output $@ @echo [build]: created $@ clean: @rm -f $(TARGETS)
(cl:defpackage #:script (:use #:cl) (:export #:run)) (cl:in-package :script) (defun run (argv) (format t "hello world~%"))
As an aside, I also updated the buildapp aur package.
Common lisp scripts.
The ability to integrate writing lisp into your existing Linux/Unix workflow and processes.
Not having to think about packaging or build architecture for trivial operations.
~40+ meg executable.
Only one source file per script.
The backstory: I'm trying to learn Common Lisp. It's sort of an arcane programming language with a few aspects that I rather like, and I'm viewing this as an exercise to generalize my programming experience/knowledge.
I've written some common lisp over the years, mostly because I use stumpwm, but I've been struggling to find a good project to start on my own or hack on an existing project.
A few weekends ago, I started hacking on coleslaw, which is a static site generator written in common lisp. The reasons are simple:
I know something about the static site generator domain, so I'm only trying to learn one thing.
Coleslaw is typical in many respects of site generators, but the architecture makes sense, and it's reasonably simple and hasn't been overly optimized.
There are three features I'm interested in adding:
I want make it so that Coleslaw builds content incrementally: there's no reason that programs like this should have to rebuild all content on every build. There are two missing concepts "which pages changed," and "if one page changes, what other pages must change."
I want to make the entire build process more configurable. Thise includes expanding the options that are available in the site configuration, and allowing users to define and edit themes within their projects.
It feels wrong to leave the program signally threaded, particularly when build systems are inherently parallel, and Common Lisp real threads.
I want to make this blog more blog-like. The current site works fine, but I'm growing restless, and I want to explore
So I began hacking and managed to learn a lot about the codebase, and am getting into the swing of this project. I played with a naive concurrency approach but it didn't stick. For about a day of work, I:
Made the docutils package usable from coleslaw and fixed some issues there. See pull request.
Added a lot of configuration and made more things customizable. Pull requests.
There's a lot of little things that I like or feel like I will shortly like, but the sticking points at the moment are:
A lot of things have started to make sense.
let forms feel very
natural. The object system is pretty great. I feel comfortable with
the organization of code within a function. I don't mind the
I remain pretty confused by the variable binding system outside of
let forms. I'm never sure about
policy thus far has just been to
setf and troubleshoot if it
doesn't do what I want.) If Python is all about the power of the
namespace, it feels like CL is all about the power of scopes and I
haven't yet learned all of them.
Oddly, conditionals feel really hard and cumbersome. The
is more limited and not particularly clear,
cond is pretty useful
but often feels like a sledge hammer.
when are clear
but not perfect.
I've not found the idiomatic way to perform "set a variable to the return of a function if it's current value is 0/null/false, otherwise pass" which I find myself reaching for pretty frequently (and awkwardly.)
More to come, I'm sure!
Learning how to make computer software is hard. Not fundamentally hard: lots of people can do it, and even more people do things that are functionally equivalent to programming though they wouldn't think of it as such. But teaching people how to write good computer software is a challenge, and one that I'm generally interested in exploring more.
For a long time, I've been interested in this problem from the outside: I didn't really know how to program in any meaningful sort of way and I was interested in deconstructing the process of making software. Then something clicked and years of tinkering with systems administration and reading about programming languages and practices clicked and while I think I have a lot left to learn, I've started thinking about the problem from the other side.
We accumulate many skills and kinds of knowledge in an incremental sort of way: you study and practice and little by little our brains (and bodies) form new connections and we "learn." Other kinds of learning follow a more "step-based" approach: we practice and study for a long period of time without much discernible change in understanding or skill until at some point we experience some sort of larger improvement in ability.
At least for me (and perhaps you as well,) things like dance, knitting, writing, and most structured/classroom-based topics tend to be incremental, mostly. Other things, like programming (at least initially) and singing/music tend to be step-based.
This isn't to say that step-based areas of focus don't require regular ongoing practice, just that the observable markers of progress may lag inconsistently behind effort and pedagogy.
When I was doing more non-professional writing, I was fond of the school of writing advice that said "the way to learn how to write (fiction) is to have a good story to tell;" when I think about learning to program I think the first step has to be a need to automate something on a computer.
I've even started a wiki page on the topic.
Hackers describe this as the "scratch your own itch" method (from CatB and elsewhere.)
Neither the idea of step-based versus incremental learning nor the notion of using a personal need to drive learning are new, but I think they illuminate eachother well.
Since I stopped being a student somewhat abruptly in 2007, I've become increasingly glad both that my education and personal development has continued and I've had the opportunity to explore things in ways that didn't make sense in a structured context (e.g. "I want to learn about how databases work without formal CS/systems training," or "I want to learn how to sing and withouta lot of music theory.")
For most of the past year I've been pretty heads-down on the "learning to program" project, and I've had a number of interesting problems that I've used to help explore the topic:
generalized Sphinx publishing toolkit.
Sphinx is a great tool for producing text, and I'm quite fond of it. At the same time, I'm not a fan of its architecture (and have a number of approaches to optimize the build process,) and there are a number of tasks: dependency resolution, version management, theme management, and deployment that any reasonably complex Sphinx-based project needs to address.
While this project requires ongoing development and improvement, it's basically feature complete, and it's given
I've had a couple of personal side projects that I've used to explore different kinds of programming problems, with greater and lesser success.
Buildcloth, which is pretty cool and needs more work but I fear may be too complicated for the use-case.
csc, which isn't fully off the ground and may not provide a significant improvement upon Sphinx for most cases.
dtf, which is a decent idea, but I've not had time to really implement and exercise the program and I fear that the core code quality isn't great.
More recently I've begun working on a dependency analytics package with a co-worker/friend to help him and his teammates understand and untangle a larger C++ project.
It's been nice to be able to actively work on a project with another developer, and to be able to focus on performance and architecture issues while someone else focuses on feature prototyping and use-cases.
In a lot of ways this is a good "capstone" project for me because I've gotten to use and apply many of the things I've learned from writing concurrent/parallel Python, as well as moderate sized Python programs comes together well here.
Most of the projects that had been open and on my plate for the last few months have mostly wrapped up. There's more work to be done on them, I could do a lot more work, and I think I will, but none of them are lacking a feature that I really need in order to accomplish something that I want to do.
I'm interested in learning more: about writing (documentation, science fiction, etc.), about software development and computing.
I'm interested in using metaphors and methods from programming and engineering to make documentation better. There are some obvious elements that are ripe for stealing in terms of process (scrum, iteration, etc.) as well as tooling (issue tracking, version control.) As I've continued to explore the connections and metaphors have become less obvious, but remain very helpful.
Recently I've been thinking about and using the idea of inheritance to help address content duplication issues. The new approach tocontent is one of these applications. Actually, this is a bit of retroactive intellectualizing: the need for reuse came first, and relating this back to inheritance is an idea that I want to explore.
I'm thinking about inheritance in the same way that we talk about the inheritance of classes in object oriented programs.
In the past, I've talked about the failure of the promise of single sourcing to solve the complexity problems in documentation as being related to the failure of object oriented programming styles to resolve code duplication and promote widespread code reuse. Or, if not related, symptoms of related causes.
For code, I think the issue is that while there are a couple of applications for inheritance (i.e. representing trees, some basic templating,) it's not a universally applicable metaphor. The mantra composition over inheritance draws attention to the fact that "has a" relationships are more prevalent and useful than "is a" relationships.
Tactically, speaking, using inheritance rather than simple inlining or inclusion is quite helpful for thinking about content reuse in documentation. Inlining is technically easy to implement, but doesn't actually help facilitate content reuse because it's hard to write content for inclusion that's sufficiently "context free," whereas using inheritance makes it possible to reuse structures and portions of content without requiring writers to write context-free content.
Inheritance isn't perfect of course: if you have to overload all or most inherited elements you end up with a confusing mush that's hard to untangle, but it's a decent starting point.
Onward and upward!
See the rhizome archive for more posts.