Quantum Mechanic

Content tagged Code

Link Dump Week of August 22

posted on 2016-08-22 22:05:00


Page Dewarping

Overview of algorithms for converting a warped image of text (e.g. from a photo of a printed page of a book) to a clean, black and white version. Wish I'd known more about this in school, though I probably wouldn't have had the time to make anything with it. Looks like a fun weekend project.

Writing Less Damn Code

Just a bit of a (justified) rant on the complexity of some solutions to web problems. Mostly here to remind me that I really want to take some time to learn about flex box. Well… really want to know about flex box with as little effort as possible.

Writing a JPEG decoder in Rust

Part 1 and Part 2. Good idea for an appropriate project to make something with Rust. Maybe I can do a tga one to see how I can improve cl-tga. Maybe I'll finally do RLE encoding.

Clack Static Asset Middleware

posted on 2016-05-12 02:01:00

As part of my glacial march to get Knttl running the way I'd like, I wrote a middleware for the clack web framework to help me out!

When you're serving javascript and css files for a website, you want to inform the browser to keep a local copy as long as possible, because then it won't bother your webserver to download it again and the page will render faster for your users, too. There's a popular quote about programming

There are only two hard things in Computer Science: cache invalidation and naming things.
It seems this was said by a Phil Karlton.

So, like many things related to the it-was-never-meant-to-be-used-this-way world of web technology, there are some interesting best practices that evolved around this idea that, ideally, only one copy of a static file should ever need to be sent to a user, if their browser works well.

There are ways to tell a browser how long to hold onto a file before checking if there's a new version of it, but that only gets you so far. Presumably, your javascript is going to change, some day, and then you'll feel silly when all of your users are still running a three week old version of it that's still cached by their browsers.

The next bit is the hack that makes it all shine.

"Why not just change the filename when the file's contents change?" asked some bright engineer, somewhere. So, we do. We just attach a hash of the file to the filename and serve that. When the file changes, the filename we show the web browser changes, and we can tell the browser to just cache the file forever, or as close to forever as we can!

It's kind of a pain to generate a copy of all of your files with hashes attached, so what clack-static-asset-middleware does is store calculate some hashes of your files and just pretends those files exist and serves up whatever you tell it about.

I also wrote some helpers you can load to use this stuff easily with Djula, like so:

<a href="/" class="logo u-pull-left" title="Home">
<img src="{% asset-path "small-logo.png" %}"
width="54" height="60"
alt="Knttl" />
</a>
So, to summarize:
  1. Have style.css
  2. Template asks for hashed filename, gets something like style_2867f3f83a6a91ad4a19a6cd45536152.css
  3. Browser asks for style_2867f3f83a6a91ad4a19a6cd45536152.css
  4. Server says "Aha! I have fooled you! Here's style.css! Keep it as long as you like!"
  5. Browser says "Golly gee! I will, mister Server! I'll never ask for style_2867f3f83a6a91ad4a19a6cd45536152.css again!"
  6. Hooray!
So check out clack-static-asset-middleware, which will hopefully be in quicklisp soon!

Blog Walk Roundup 2015-12-10

posted on 2015-12-10 13:34:00

I spent a bunch of time collecting things around the web today. I think some of these are worth a read, so I'll link a bunch here.

Additionally, I participated in my first Massdrop and got my Code WASD Clears keyboard, yesterday. It's really nice to type on! If you're interested in playing that game, consider using my referral thing (https://www.massdrop.com/r/D2EFXE), because I like what they've done and I'd like a goodie box!

Neat blog comment policies




From Tim Chevalier's Blog:
If you comment, I have a few requests:

  1. Refrain from phobic or discriminatory speech, or speech that (in the words of s.e. smith) suggests that "people don't deserve autonomy, dignity, and a place in society."

  2. Refrain from comments that have the effect of silencing or derailing (see Derailing for Dummies for additional examples).

  3. As a corollary, refrain from questioning the existence of privilege or systematic oppression. There are many resources available online and offline for learning about these issues.

  4. Provide a name or pseudonym that reflects a consistent online presence (as opposed to so-called "throwaway" or "sockpuppet" identities).



Apparently, this is stolen from Christie Koehler's.




Rust stuff




At work, we've been looking at using Go for a rewrite of a major project. I keep trying to dig into it and have been annoyed by a bunch of things. I still think it could be a nice idea, there, but I have this problem where I get strong affinities for things pretty quickly and I've gotten pretty interested in Rust as, perhaps, and alternative to Go.

I've barely used it yet, but it seems to have nice easy package management, immutable data, a helpful compiler, a type system I can get behind, and whose documentation I can find! For some reason, I feel like it's been difficult to find good explanation of Go.

In any event, I've started working through Rust's book, after using the emacs setup shared here. This has been a long time coming, because I've been hearing about Rust over the years and keep meaning to try it. Reading the blogs above, it turned out that Tim Chevalier worked on Rust, so there was a handy link to a presentation to remind me to check it out!

Both languages are current better than the python 2.7 we use at work, because they both use unicode! Something that should just be standard at this point!

extern crate rand;

use std::io;
use rand::Rng;
use std::cmp::Ordering;

fn main() {
println!("Guess the number!");

let secret_number = rand::thread_rng().gen_range(1, 101);

println!("Please input your guess:");

loop {
let mut guess = String::new();

io::stdin().read_line(&mut guess)
.ok()
.expect("Failed to read line");

let guess: u32 = match guess.trim().parse() {
Ok(num) => num,
Err(_) => continue,
};

println!("You guessed: {}", guess);

match guess.cmp(&secret_number) {
Ordering::Less => println!("Too small!"),
Ordering::Greater => println!("Too big!"),
Ordering::Equal => {
println!("Correct!");
break;
}
}
}
}



Making a knitting tool

posted on 2015-11-28 19:01:47

Hey there, friends!  Over the years, I've been aspiring to making interseting web apps in Common Lisp.  At the same time, Sarah's been kniting more and more and I've gotten to see some of that world.  Lots of people use Ravelry for posting their work and it's got a strong community.  I thought it might be interesting to try to make something that formatted knitting patterns in an easy to follow way.  Maybe eventually work up to some sort of markdown extension.  We'll see where it goes.

A few weeks ago, I stuck an early version up at knttl.co!  I'm sure there are all sorts of little bugs in it.  But it's fairly pretty and quick and runs on top of PostgreSQL and Common Lisp!  It's running Eitaro Fukamachi's woo web server, which is nice and snappy.  It's ona very low tier DigitalOcean VM and I haven't configured everything that well for the environment, so it crashes if it gets too much traffic.  While it's working, though, it's pretty darn quick.  I wish I had more time/effort available to work on it, but it's hard to find the motivation after full time programming work during the week.  If you find knttl interesting or useful, though, please let me know!

I have become Programmer

posted on 2015-07-11 23:54:00

As I mentioned last time, I've taken a new job in a new field. I've left academia, which I'd like to write more about, because it was important and difficult. Now, I'm working as a Software Engineer for Octopart, where I've been working in Python and Javascript, mostly doing fronted work.

It's been exciting doing something I've done for so long professionally. Octopart is a small team and it means I have a lot of freedom to work on things I think need work, but some of that is a bit disorienting, especially as someone working in the field for the first time. It's hard to know what expectations are in any situation, but people are trusting me to do what needs to be done and I'm working the confidence to believe my decisions about that are correct.

I also haven't really worked in Python before. It's always nice to learn a new language – especially with such a defined project – so that's been a plus. I am surprised again and again by how different languages handle importing files/packages/modules and how often it feels magic, weirdly difficult or some other sort of uncomfortable. Lisp has the strange duality of packages and ASDF systems, which aren't the same thing but often effectively are. Python has it's own difficulties, but in many ways is simpler. You pretty much just use paths with dots replacing slashes for folders. I'm not sure I'm a huge fan, but that's probably more stylistic than anything else. Even though python has a command line REPL and more sophisticated tools like IPython, I miss SLIME when I'm working in it.

Really, I miss lisp, generally. One downside of working in programming is that I have little enthusiasm left over after work for looking after my own projects. Hopefully, I'll get better at that in time. In any event, go check out Octopart if you're into electronics and let us know how we can make it more useful. It's made by a lot of nice people who care about what they're doing.

Cooking with websockets

posted on 2014-12-05 17:57:00

I finally got Chirp working with websockets! Well, it had worked before, but just sent down all the chirps that existed. Now it updates in real-time when someone else chirps. Though, it sends it to everyone, so don't say anything you'd want kept secret!


websockets.png


Eventually, I'd want to send messages only to followers and have them show up in the nav bar as notifications, but this was mostly meant as a proof of concept, anyway. I'd much rather go write a new sql library for lisp, now, that try to finish everything. At some point, paging chirps so you can scroll to fetch more would be good.

This was sort of my minimum product for this project, but I might polish it more as I have time.

Playing with the MOP

posted on 2014-12-01 20:30:00

I was poking around at my project, Chirp, today and finally decided to deal with a strange bug I was having. When I sent JSON down to the AngularJS controller that renders the page, dates were always coming back as the time the request was made at. This was strange, since the database records of the chirps store when they were created, and the time should have been that. The one I was testing was over a week old.

Eventually, I realized that in the slot definition

(created-at :type clsql:wall-time
:initform (clsql:get-time))


the time stamp would always be the current if the time wasn't set on the instance when the database was read.

I'd recently started using clsql-helper to get instances of classes back from complicated SQL queries. By 'complicated' I mean 'contains a basic join.' Apparently, CLSQL doesn't feel it needs to do that. I wish I knew why.

In any event, when I used clsql-helper, the dates were wrong, when I used clsql's built-in #'select, the dates were correct. So it slowly dawned on me that clsql-helper was doing something wrong. Sure enough, it wasn't converting the string that the time stamp returned into the wall-time instance that clsql expected.

So I took the chance to play around with the MOP a bit and wrote code to convert the values to the right type, looking at their slot definitions in the class.

(defun get-slot-by-name (name class)
(find name (closer-mop:class-direct-slots (find-class class))
:key (lambda (slot)
(intern (symbol-name (closer-mop:slot-definition-name slot))
*package*))))

(defun coerce-value-to-column-type (class column value)
(let ((type (clsql-sys::specified-type (get-slot-by-name column class))))
(coerce-value-to-db-type value type)))


With that code, you just do something like

(coerce-value-to-column-type class coulmn data)


and things come out the right way.

Literate Programming with Emacs

posted on 2014-11-21 22:17:00

Tried out literate programming a bit today using some info from Sacha Chua's blog (mostly). It's actually pretty difficult to figure out how to make it work and what was strangest for me was that I can't figure out how to put a whole bunch of code blocks into the same file. It seems like you need to specify a :tangle filename for every block!
#+begin_src clojure :tangle "chapter1.clj"
...
#+end_src

What I was really hoping for was defining a new file at each section. John Zahng invited me to work on SICP in Clojure with him and I thought it was a particularly good case for trying out org-mode's literate programming functionality. After an hour or two of trying, though, I don't know how to make it do what I want. I can get it to dump all of the code into a file with the same name as my .org file, but that's it. I'm not really sure how I'd want to use this to write a large project of any kind.

Getting Lisp to run on heroku

posted on 2014-11-13 16:33:00

For a while, I'd been working on cloning twitter in Lisp, since I'd been playing with Lisp web frameworks (weblocks, hunchentoot, caveman, clack) for a while. Now that I know so much more about web development, it seemed like a perfect chance. Also, with hunchensocket around, I could do push notifications with websockets, too, which Rails can't without third party services.

I have a site up now, at Chirp, after many hours of beating my head against the wall. I thought I'd write down some major points for others who try to sort the madness out.

  1. Your app will be compiled, don't expect it to behave like you're running it from the REPL.

    I had my configuration defined using envy's (defconfig) in the top level of a file. That meant that all of the configurations were defined at compile time, when the environment variables I was using weren't defined. So, I had a few nil's in my configurations.

    Now, I wrap the (defconfig)'s in a function call when the app starts up. Works like a charm.

  2. You don't own the database, you just get to use it.

    CLSQL doesn't have permission do do a number of things you might have been doing on your own database server. I had a helper function that made the database and tables if they didn't exist. I got a lot of complaining about "template1," which seems to be some internal postgres thing that administrators get access to. Don't use (clsql:probe-database) or (clsql:create-database), they both try to do things they're not allowed to.

  3. Getting environment variables is a necessary evil.

    Environment variables are not a first-class part of the lisp world, but they're not too hard to get to. Heroku uses a lot of them to show you your configuration, pay special attention to PORT and DATABASE_URL.

    You can get at these two ways. ASDF has a private (getenv) function, which is handy and generally available. If you're using SBCL, you can also (require 'sb-posix) and use (sb-posix:getenv). It has a sibling, (sb-posix:setenv), should you need it.


Hopefully, we'll make a better, more user-friendly buildpack, soon.

Starting Over All Over Again

posted on 2014-11-11 14:15:00

So, back in July I took the plunge and decided that I wasn't cut out for the world of Academia. Grad school was taking an emotional toll that was turning into a physical toll and wasn't paying the fulfillment dividends that it needed to. I'd spent years acquiring very specific skills in quantum computing research that people didn't value at all. The pay was terrible. The social environment was terrible. The management was terrible. It was time to leave.

So I went ahead and enrolled in App Academy, which my friend Scott had done before. So, for the last two months, I've spent every waking hour programming (well, maybe a few reading and playing Dota). I know Ruby, Rails, Javascript, Backbone (learning Angular) and I already knew Common Lisp.

Most importantly, I feel like it's a good life choice. I miss doing physics, but the universities have made it such a horrible environment to work in, it's not worth it to me, anymore. I'm happy I get to keep problem-solving in programming and, if I'm lucky, I'll find a job that uses my considerable skills in debugging and engineering.

The Job search starts today and I'm confident it will give me a fuller life than a career in Physics was offering.

Map Take 2: The Slicening

posted on 2012-11-30 22:05:50

It's been a while since I wrote about my scientific computing library for lisp: map.  Map is a great exercise for me -- in learning Lisp and learning algorithms and optimization.  Since I'm between jobs and not yet in grad school, the time has been ripe to work on the library with some toy cases and try to make it as usable as possible by the time I get back in a position where I could use it for real work.

Because of my copious free time, a lot has been changing lately, including the addition of matrix slices, which were important, and such important features as matrix inversion.  I'm also looking at adding parallelization at some point, as well as a matrix-defining macro in the style of the #v() one for vectors.

In any event, here's what's new:


Slices


I promised to write again when I had finished with matrix slices in map.  I'm sure they're not in their final state, but I have implemented them in a way that works. Now you can do things like:
(setf (mref m 1 #r(1 2) t) #2a((2.0d0 1.0d0 3.4d0) (3.1d0 3.2d2 4.2d1)))

Which already has a number of things going on in it.  This is setting a sub-matrix of m, a rank-3 matrix to a rank-2 matrix specified in the end of  the setf call.  Since we selected a single value for the first index of m, mref will not count that dimension as extant for the purposes of comparing with the shape of the matrix we're assigning.  This is really useful, because now things like multiplying matrices can be done like this:
(defmethod .* ((A simple-array) (B simple-array))
(with-result (result (list (array-dimension A 0) (array-dimension B 1)))
(do-matrix (result (i j))
(setf (aref result i j) (dot (mref a i t) (mref b t j))))))

There are three different ways you can specify subscripts to mref:

  1. Integers
    This will work like aref, and the dimension won't be included in the final output

  2. Ranges
    This will select all entries in the matrix that have indices inside the specified range in this dimension, for example, (mref #(1 2 3) #r(0 1)) ==> #(1 2)

  3. t
    This selects all elements in this dimension.  It's great for slicing rows/columns out of matrices a la (mref m t 0), which will take the first column out of m.


Matrix iteration


Since most of the functions in the library were operating on matrices and returning new ones, I thought some macros were in order.  I think it's the reflex of any lisper to write a macro when they see the same code in more than one place.

Of that urge were born (with-result) and (do-matrix)(with-result) is simply a convenient way of defining a new matrix at the start of a function and automatically returning it.  (do-matrix), though, I rather like because it allows looping over matrices in a rather intuitive way.

(defun mandelbrot (matrix)
(with-result (result (list 1001 1001) 'integer)
(do-matrix (matrix (r i))
(setf (aref result r i)
(loop
with c = (aref matrix r i)
with z = c
for i from 0 upto 80
if (> (abs z) 2)
return (1- i)
else
do (setf z (+ (expt z 2) c))
finally (return 80))))))

Here you can see (do-matrix) at work, testing whether each element of an array of complex numbers is in the Mandelbrot set.  It's definition is
(defmacro do-matrix (matrix &optional subscripts) ...)

which means you can then just write element-wise operations inside the loop with all of the indices figured out for you.

I'll end with the figure I made of the Mandelbrot set today on the [-2, 2] range in the complex plane. Along with the (mandelbrot) function above, you need the matrix to call it on,

(mute
(setq cm
(let ((center 500))
(with-result (result (list 1001 1001) '(complex double-float))
(do-matrix (matrix (r i))
(setf (aref matrix r i)
(complex (* (- r center) (/ 2.0d0 500))
(* (- i center) (/ 2.0d0 500)))))))))

and then you can run
(mute (setq r (mandelbrot cm)))
(image r)

.

The Mandelbrot set from -2 to 2 in the complex plane.
The Mandelbrot set from -2 to 2 in the complex plane.

Literary Programming

posted on 2012-11-15 21:27:40

I've been doing a terrible job of writing recently -- something I'm happy to put down to the general depressing-nature of the life of the unemployed -- and I'm definitely overdue on some writing. I've now moved out of Washington Heights in New York, and into Evanston, just north of Chicago. So far I'm liking it here. It's similar enough to New York City in a lot of ways, but with much more space, and less of the claustrophobia that is endemic in NYC.

Now that I've reached a moment of coherence, I'd like to just throw down a link I thought was particularly interesting.

If Hemingway Wrote Javascript



This was notable for a number of reasons.  First, it was an entirely new genre of thing to me.  I had never seen anyone write about writing styles in programming before.  I don't mean style guides or best practices, but just what you express by the way you choose to do things.  I think the author did something really cool here, ranging from his interpretation of Hemingway, who wrote a very clear, straightforward implementation, to the different failings of programming style he showed in some others.

Even though the example of Breton is obviously written to be a bit silly, framing it as an author made me think about the example in a different light.  I'm a fan of work of the Dadaists, who did strange things because things are strange and the things we are used to only seem normal because we are used to them.  The idea of renaming the push() function of arrays to something else -- maybe even something more expressive -- strikes me as potentially helpful.  In languages where the language itself can be dynamic, as in Lisp or Javascript (and I'm sure others, I just only know what I know), maybe it makes more sense sometimes, to rename things to reflect what they're being used for.  If Lisp has taught me anything, it's that programming is just code manipulating data, and trying to render that clearly is the greatest struggle.

Finally, I can't leave this without mentioning the work of the imagined Dickens, who is someone I found very frustrating to read.  I consider A Tale of Two Cities to be one of the worst books I've read, and it was only through sheer will that I finished it at all.  Apparently, as quoted in the article:
If we might hazard a definition of his literary character, we should, accordingly, call him the greatest of superficial novelists. We are aware that this definition confines him to an inferior rank in the department of letters which he adorns; but we accept this consequence of our proposition. It were, in our opinion, an offence against humanity to place Mr Dickens among the greatest novelists. For, to repeat what we have already intimated, he has created nothing but figure. He has added nothing to our understanding of human character.

What I mean with all of this, and think of A Tale of Two Cities and the imagined Dickens implementation of the Fibonacci function is that they each manage to be what they set out to be -- a novel and a function -- but just in the meanest sense of the words.  A Tale of Two Cities has a story -- but only in that it relates a series of related events -- and the function returns the right function and in both cases, I feel like I'm squinting at them with, "That's not quite right," on the tip of my tongue.

Map

posted on 2012-08-22 21:26:44

For a while now, I've wanted to make some of the great functionality of things like Octave (and it's parent Matlab) to Common Lisp.  Mostly, I want things like the slice assignments (arrays with ranges in the indices) and matrix math.  Also, it never hurts to make higher mathematical functions available in simple ways.  So, I started writing Map, which I hope will do just that.

Lately, I've been working in singular optics, largely with Spatial Light Modulators, which are like very tiny LCD screens in front of a mirror. They're cool because they can transform the wavefront of a laser beam into any sort of beam you'd like!  We use a fair bit of math to pump out the right images to put onto the SLM, and I'd been wanting to make a more general interface for that for a while.  I'm not there yet, but I'd like to share the few things I've done so far.

Vectors

In Octave, you can type

[1:10]
and it will automatically be expanded to
[1 2 3 4 5 6 7 8 9 10]
.  This is great notation and can be used both for generating a vector or setting a range.  In map, I've implemented those with
#r(1 10)
, which creates a 'range' class that just keeps track of the numbers, and #v(1 10), which will expand to
#(1 2 3 4 5 6 7 8 9 10)
, like the Octave code.  This means you can do things like
(reduce #'+ #v(1 100))

To add up the numbers 1 to 100.  That, of course, isn't hard, especially when Gauss came up with a much easier way, but you get the picture.

One further thing that's special, is that you can apply a function to the vector you're generating by passing another argument (you can also pass a step size by entering three numbers).

(reduce #' #v(1 .1 10 #'sin))

will give you the sum of the sine of the numbers 1, 1.1, ..., 9.9, 10!  Moving on...

Differential Equations

This is a much more meaty section, and was really fun for me, since I hadn't really implemented a ODE solver before (that I remember).  Map now contains a Runge-Kutta Feldberg 45 solver, which is supposed to have an adaptive step size, and currently doesn't seem to, so I didn't do everything right, but it works to a certain accuracy.

Here's a demonstration of finding the angular position and velocity ($\theta, \omega$) of a damped, driven pendulum, taken from some of my old computational physics notes.

(defun damped-pendulum (ti yi)
        (declare (type double-float ti)
(type (array double-float 2))
(ignore ti))
        (vector (+ (* -1d0 (sin (elt yi 1))) (* -1d0 .5d0 (elt yi 0)))
            (elt yi 0)))
(map::mute (multiple-value-setq (ts ys)
(map:rkf45 #'damped-driven-pendulum
#r(0d0 1d-7 4d1)
#(0d0 1d0) 1d-10)))

Now, ts holds the time values, and ys is a 2x(length ts) array of position and velocity values!  Once I implement array slices, it'll be easy to graph them, but for now, you need to manually extract one of the rows of ys to plot against ts. There's still a lot of work to be done. Anyway, the resulting graphs are:

Angular velocity, $\omega$.
Angular Position, $\theta$.

Thanks for reading, I'll probably post more once I've got slices sorted out.

Boxcar2d

posted on 2011-02-13 23:09:09

In the last few days, I've spent a lot of time zoning out and watching this play. It uses genetic algorithms to design cars out of combinations of wheels and vertices. For the first few generations, it's usually pretty stupid, and then gets a lot better as time goes on. Really fun to watch in any event. The website is here.


Nec Somno Nec Loquor

posted on 2009-08-23 02:05:00

I finally went through with my idea to make a C library for dealing with RESTful web interfaces. I have called it libunrest, because of their annoying nature. It can already talk to last.fm and discogs.com, and it will work for facebook once I decidee how to implement specifics of signing. I'll have to completely redo signing if I'm going to support oauth, which seems to be even vaguer than the REST interfaces I've already looked at. I've been working on this in hopes of getting rhythmbox to be able to use discogs, and to update the last.fm plugin to use their new, RESTful API. It's also fun to have code hosted online. I like gitorious.

Too aptly named

posted on 2009-08-12 07:11:00

When I set out to make a C library for simplifying interacting with RESTful web services, I named it "unrest" after all the angst that I had dealing with facebook's API (working on cl-facebook). Now it's 3AM (started working around 10:30PM), and I just ran my program for the first time without segfaulting. Hooray for apt naming. For posterity, I'm including the response here.

<?xml version="1.0" encoding="utf-8"?> <lfm status="ok"> <token>8f13b0dc95fbfff4a29701b1e91f385e</token></lfm>

Good night.

unum res plusquam

posted on 2009-08-05 05:44:00



I would also like to mention e-blog, which is the new tool that I am using to blog with. It is really awesome, and runs out of emacs, which is also awesome!

My linux can do what your Mac/PC can do

posted on 2009-07-09 19:44:00

Just recently got to try out gnome-shell, which is one of the coolest new things I've seen in linux lately. Right now, it's really just a new window manager with a really crappy dock/app-launcher hacked on, but, I think if those get replaced with some other technologies out there, it could be pretty amazing. I'd like to see gnome-do wired into the app-launcher and Zeitgeist is supposed to be integrated at some point.

Importantly (to me), it has exactly the level of eye-candy that neither metacity nor compiz had. There are nice animations and smooth minimizing of windows - things that are less flashy than compiz, but more flashy than metacity.

Right now, things crash fairly often for me, but, today's checkout has held up all day. I'm hoping that, at some point, I'll find some time to contribute to it.

De Novibus Locibus

posted on 2009-04-04 01:48:00

I'm proud to say that cl-facebook has a new life at common-list.net and I've set up a svn repository that's listed on that page. I hope someone finds it and starts using it. Maybe I'll have to get the word out.

De Libri Oris

posted on 2009-04-02 02:00:00

I have finally found a project for learning Common Lisp better. I've been implementing a lisp interface to facebook's REST API. I found some old code at common-lisp.net, which had lots of useful hashing/request forming code, but was using an out of date API and had no documentation.

I'm happy to say it is now much more useable. I applied for hosting on common-lisp.net. So, maybe I'll have a link to that for the interested soon

Project Euler

posted on 2009-03-21 04:36:00

Today is a marvelous day, because today I found out about Project Euler, which means I'll never want for programming tasks again. Sometimes I really think that all it takes is for someone to decide what (possibly) pointless task you should do, and then you can do it, as opposed to deciding to do it on your own, in which case, you are crazy. In any event, here is my first solution (working with Lisp):





;; Sum all of the multiples of 3 or 5 less than 1000



(loop for i from 1 to 999 when (or (= (mod i 5) 0) (= (mod i 3) 0))

sum i)





For the answer - you'll just have to run it yourself. This taught me a fair bit about Lisp loop forms. They are quite extensive and somewhat confusing. Just when you get used to putting everything into parenthesis, they decid you should actually be typing sentences.





Indeed, it seems like you barely need to write anything except the loop statement. This may just be me not quite getting function programming yet. For example, my solution to problem 2:





(defun fibonacci (n)

(if (<>

This is quite clunky, I think. We have to calculate the result of the fibonacci function many times (there are, apparently, around 180 even fibonacci numbers smaller than 4000000). I'm still not sure how to do this better, but, I fully intend to consider finding out.

View content from 2009-03-16 04:17:00, 2009-03-21 04:36:00, 2009-04-02 02:00:00, 2009-04-04 01:48:00, 2009-06-25 19:43:00, 2009-07-09 19:15:00, 2009-07-09 19:44:00, 2009-07-20 23:25:00, 2009-07-21 16:57:00, 2009-08-05 05:44:00, 2009-08-05 10:28:00, 2009-08-12 07:11:00, 2009-08-23 02:05:00, 2009-08-23 04:30:00, 2009-10-30 08:02:00, 2009-11-08 06:59:00, 2009-12-04 01:17:00, 2010-05-22 18:55:00, 2010-05-28 22:50:00, 2010-06-05 19:55:00, 2010-06-12 02:12:00, 2010-06-20 20:20:00, 2010-07-02 22:57:00, 2010-08-20 22:16:00, 2010-09-02 02:07:00, 2011-01-07 10:35:30, 2011-01-07 11:17:53, 2011-01-13 06:48:47, 2011-01-24 02:52:06, 2011-01-31 02:41:34, 2011-02-13 23:09:09, 2011-03-23 05:59:11, 2011-04-06 01:33:19, 2011-04-24 22:15:24, 2011-04-24 22:51:30, 2011-06-06 22:36:07, 2011-06-16 02:27:10, 2011-06-30 01:26:18, 2011-07-31 23:10:35, 2011-08-17 04:15:14, 2011-09-11 17:13:48, 2011-10-01 15:55:35, 2011-11-02 15:14:47, 2011-11-08 01:49:00, 2011-11-29 23:28:27, 2011-11-29 23:30:17, 2011-11-30 06:58:06, 2011-12-08 02:41:21, 2012-01-17 17:27:10, 2012-01-20 16:59:54, 2012-01-31 17:26:17, 2012-02-07 15:46:44, 2012-02-10 17:15:32, 2012-03-03 18:35:25, 2012-03-30 02:45:19, 2012-04-23 21:44:13, 2012-07-13 16:39:31, 2012-07-13 16:56:55, 2012-07-17 01:15:15, 2012-08-21 22:12:00, 2012-08-22 21:26:44, 2012-09-19 15:35:27, 2012-11-15 21:27:40, 2012-11-15 21:28:49, 2012-11-26 09:40:14, 2012-11-30 22:05:50, 2013-02-22 20:37:08, 2013-03-08 08:50:26, 2013-03-16 21:41:50, 2013-04-06 06:50:15, 2013-04-15 04:18:48, 2013-04-15 20:27:06, 2013-04-23 20:43:29, 2013-04-30 20:39:31, 2013-06-14 00:17:17, 2013-06-18 16:45:24, 2013-07-08 10:33:06, 2013-07-25 05:00:00, 2013-09-05 14:07:31, 2013-09-25 15:31:00, 2013-09-26 15:35:00, 2013-11-12 15:49:00, 2014-01-04 01:46:27, 2014-02-02 21:48:41, 2014-02-24 02:55:00, 2014-03-05 18:42:00, 2014-07-22 00:46:00, 2014-11-11 14:15:00, 2014-11-13 16:33:00, 2014-11-21 22:17:00, 2014-12-01 20:30:00, 2014-12-05 17:57:00, 2014-12-16 19:53:00, 2015-01-13 18:28:00, 2015-02-12 22:12:00, 2015-07-11 23:54:00, 2015-07-12 00:22:00, 2015-10-18 22:57:35, 2015-10-19 00:32:40, 2015-11-28 19:01:47, 2015-11-29 17:03:00, 2015-12-06 03:02:00, 2015-12-10 13:34:00, 2016-01-03 17:45:00, 2016-01-03 17:56:00, 2016-01-16 20:43:00, 2016-05-10 01:41:00, 2016-05-12 02:01:00, 2016-05-15 14:32:00, 2016-08-01 13:15:00, 2016-08-22 22:05:00, 2016-08-23 22:10:04, 2016-10-26 17:33:48, 2016-11-26 01:36, 2016-12-05 14:42:00, 2016-12-05 19:31:00, 2017-02-03 18:00