28 Apr 2016

feedPlanet Lisp

Zach Beane: New version of ZS3 supports AWS4 auth

I just published ZS3 1.2.8. It's available on my website and will be in the next Quicklisp dist update in May. The main difference is support for the latest AWS authentication system. This makes ZS3 work properly with the latest AWS regions like Frankfurt and Seoul.

If you have any trouble using it, please let me know!

(This work was for a paying customer; if you are interested in specific updates and features in ZS3 or any of my other software, get in touch.)

28 Apr 2016 4:42pm GMT

22 Apr 2016

feedPlanet Lisp

ECL News: New website look

I've imported the old archives and genearated ECL website with help of the coleslaw and the sclp. Now we have a proper RSS feed and posting news is less annoying then before.

For posterity, here is the ugly hack I've used to import archives from JSON:

(defparameter *archives-template*
  ";;;;;
title: ~A
tags:
date: ~A
author: ~A
format: md
;;;;;

~A")

(setf *json-posts*
  (with-open-file (f #P"/home/jack/linki/repo/ecl-website/static/files/misc/news-ecl-backup-2015-08-25.json"
                     :direction :input
                     :external-format '(:line-termination :cr :character-encoding :utf-8))
    (cl-json:decode-json f)))

(mapcar (let ((cnt 0))
          #'(lambda (post)
              (with-open-file (f (format nil "/tmp/archives/archive-~A.post" (incf cnt))
                                 :direction :output
                                 :if-exists :supersede
                                 :external-format (make-external-format :line-termination :unix))
                (format f *archives-template*
                        (cdr (assoc :title post))
                        ;; (cdr (assoc :labels post))
                        (substitute #\- #\/
                                    (subseq (cdr (assoc :url post)) 40 47))
                        (let ((author (cdr (assoc :author post))))
                          (if (string-equal author "dkochmanski")
                              "jackdaniel" author))
                        (remove #\Return (cdr (assoc :text post)))))))
        (cdar *json-posts*))

You may find a guide how to use the Sample Common Lisp Project template for your own project here. The clnet theme is inspired by the css in most of the common-lisp.net projects.

Best regards, Daniel

22 Apr 2016 12:00am GMT

Daniel Kochmański: Creating a project homepage with the SCLP

Introduction

In this short tutorial I'll describe how to bootstrap easily a project website. In fact that's what I did today with the Embeddable Common-Lisp website in order to provide the RSS feed and make putting there the news easier.

Additionally I'm showing here, how to create a standalone executable for coleslaw with clon after providing quicklisp independant bundle of systems.

Quick start

First clone the repository:

$ cd /home/p/ecl
$ git clone https://gitlab.common-lisp.net/dkochmanski/sclp.git website
$ cd website

Now you should adjust the appropriate files. Edit .coleslawrc (file is self-explanatory), static pages and posts.

Each file with the extension *.page is a static page. pages/main.page is an example template with a static page - don't forget to link it in the .coleslawrc's sitenav section. Exact URL of the page is declared in the file's header.

Files named *.post represent blog/news posts which appear in the RSS feed. They are indexed and accessible from the root URL. Supported file formats are markdown, html and cl-who (if enabled).

When you're done, you could just load coleslaw with your favorite CL implementation, using Quicklisp load coleslaw and call the function main on the website directory:

(ql:quickload 'coleslaw)
(coleslaw:main "/home/p/ecl/website/")

We will take more ambitious road - we'll create a standalone executable with a proper command line arguments built from a clean bundle produced by Zach Bane's Quicklisp. CLI arguments will be handled by Clon - the Command-Line Options Nuker, an excellent deployment solution created by Didier Verna.

Creating the bundle

Bundle is a self-containing tree of systems packed with their dependencies. It doesn't require internet access or Quicklisp and is a preferred solution for the application deployment.

Some dependencies aren't correctly detected - Quicklisp can't possibly know, that our plugin will depend on the cl-who system, and it can't detect cl-unicode's requirement during the build phase - flexi-streams (this is probably a bug). We have to mention these systems explicitly.

Clon is added to enable the clonification (keep reading).

(ql:bundle-systems '(coleslaw flexi-streams
                     cl-who cl-fad
                     net.didierverna.clon)
                   :to #P"/tmp/clw")

Clonifying the application

(in-package :cl-user)
(require "asdf")

(load "bundle")
(asdf:load-system :net.didierverna.clon)
(asdf:load-system :coleslaw)
(asdf:load-system :cl-fad)

(use-package :net.didierverna.clon)
(defsynopsis (:postfix "DIR*")
  (text :contents "Application builds websites from provided directories.")
  (flag :short-name "h" :long-name "help"
        :description "Print this help and exit."))

(defun main ()
  "Entry point for our standalone application."
  (make-context)
  (when (getopt :short-name "h")
    (help)
    (exit))
  (print (remainder))
  (handler-case (mapcar
                 #'(lambda (p)
                     (coleslaw:main
                      (cl-fad:pathname-as-directory p)))
                 (remainder))
    (error (c) (format t "Generating website failed:~%~A" c)))
  (terpri)
  (exit))

(dump "coleslaw" main)

You may generate the executable with sbcl and ccl (ecl has some problems with the coleslaw dependency - esrap, I'm working on it). I have used ccl, because it doesn't "derp" on the symbol exit and produces slighly smaller executable than sbcl.

Issue the following in the bundle directory (/tmp/clw):

ccl -n -l clonify.lisp

This command should create native executable named coleslaw in the same directory. On my host ccl produces binary with the approximate size 50M.

Executable usage

This is a very simple executable definition. You may extend it with new arguments, more elaborate help messages, even colors.

To generate a websites with sources in directories /tmp/a and /tmp/b you call it as follows:

./coleslaw /tmp/a /tmp/b

That's all. Deployment destination is set in the .coleslawrc file in each website directory.

Adding GIT hooks

You may configure a post-receive hook for your GIT repository, so your website will be automatically regenerated on each commit. Let's assume, that you have put the coleslaw standalone executable in place accessible with the PATH environment variable. Enter your bare git repository and create the file hooks/post-receive:

cd website.git

cat > hooks/post-receive <<EOF
########## CONFIGURATION VALUES ##########

TMP_GIT_CLONE=$HOME/tmp-my-website/

########## DON'T EDIT ANYTHING BELOW THIS LINE ##########

if cd `dirname "$0"`/..; then
    GIT_REPO=`pwd`
    cd $OLDPWD || exit 1
else
    exit 1
fi

git clone $GIT_REPO $TMP_GIT_CLONE || exit 1

while read oldrev newrev refname; do
    if [ $refname = "refs/heads/master" ]; then
        echo -e "\n  Master updated. Running coleslaw...\n"
        coleslaw $TMP_GIT_CLONE
    fi
done

rm -rf $TMP_GIT_CLONE
exit
EOF

That's all. Now, when you push to the master branch your website will be regenerated. By default .gitignore file lists directory static/files as ignored to avoid keeping binary files in the repository. If you copy something to the static directory you will have to run coleslaw by hand.

Conclusion

Coleslaw is a very nice project simplifying managing project website with easy bootstrapping the site without any need to maintain working lisp process on the server (this is static content which may be served with nginx or apache) and allowing easy blogging (write a post in markdown and push to the repository).

Sample Common-Lisp Project is a pre-configured website definition with a theme inspired by the common-lisp.net projects themes with some nice features, like RSS feed and blog engine (thanks to coleslaw).

We have described the process of creating a simple website, creating a standalone executable (which may be shared by various users) and chaining it with git hooks.

References

22 Apr 2016 12:00am GMT

21 Apr 2016

feedPlanet Lisp

Quicklisp news: April 2016 Quicklisp dist update now available.

Quicklisp's 67th monthly update is now available!

Thank you to all the people who signed up for the recurring Supporter Club in the last month. The "big" fundraiser is still in the works, and I'll let you know more when there's more info to share.

New projects:

Updated projects: 3d-vectors, alexandria, architecture.service-provider, arrow-macros, asdf-flv, asteroids, binfix, burgled-batteries, ceramic, cl+ssl, cl-ana, cl-async, cl-autowrap, cl-bson, cl-geometry, cl-hash-util, cl-itertools, cl-jpeg, cl-l10n, cl-lexer, cl-llvm, cl-marklogic, cl-mock, cl-mtgnet, cl-mysql, cl-ohm, cl-opengl, cl-opsresearch, cl-pango, cl-rabbit, cl-rethinkdb, cl-sdl2, cl-slug, cl-string-match, cl-strings, cl-tasukete, cl-tetris3d, cl-wordcut, cl-yaclyaml, clack-errors, classimp, clinch, closer-mop, clx, common-doc, common-doc-plump, common-html, commonqt, copy-directory, croatoan, dartsclemailaddress, deeds, defpackage-plus,dissect, docparser, esrap, esrap-liquid, fare-utils, fast-io, form-fiddle, gendl, hyperluminal-mem, jp-numeral, kenzo, lake, lisp-interface-library, local-time, macrodynamics, mcclim, mito, north, osicat, paiprolog,parse-js, path-parse, projectured, qtools, qtools-ui, quickutil, rpm, rtg-math, rutils, safe-queue, scalpl, sdl2kit, serapeum, simple-date-time, simple-tasks, skitter, smug, snark, south, spinneret, staple, stumpwm, sxql,teepeedee2, temporal-functions, trivia, trivial-channels, trivial-extract, usocket, utilities.print-tree, which, workout-timer.

To get this update, use (ql:update-dist "quicklisp").


21 Apr 2016 7:55pm GMT

20 Apr 2016

feedPlanet Lisp

Michael Malis: How to Generate Self-Referential Programs

In this post, I am going to show you how to write programs that are self-referential. By self-referential, I mean programs which are able to obtain their own source code without any external input. In other words, they won't just read from their own files. This post is based on section 6.1 of the book Introduction to the Theory of Computation.

Before we can start generating self-referential programs we are first going to need some techniques for generating programs in general. The first technique we need is a method of taking a given program and writing a second program that outputs the given program. As an example, given (+ 2 2), we would need to write a program that outputs (+ 2 2). In most languages this is easy. One way to do it in Lisp is to put a quote in front of the program:

'(+ 2 2)
=> (+ 2 2)

We are also going to need a function that automates this process. Such a function would take a program as its argument and return a new program that when ran, outputs the program that was originally passed to the function. In most languages doing this is fairly tricky. In Lisp, we can write this function easily through backquote:

(defun code-that-generates (program)
  `',program)

(code-that-generates '(+ 2 2))
=> '(+ 2 2)

If you don't understand how backquote works, you can read this. Even though it's for Emacs Lisp, everything there is still applicable to other Lisps. Just make sure that you understand that code-that-generates can be used to generate a program that outputs a given program.

Now that we have these two techniques, we can begin writing programs that are able to refer to themselves. The first self-referential program we will write will be an example of a quine. If you don't know, a quine is a program that outputs its own source code. The quine we are going to write is made up of two parts, part A and part B, where part A is a function that is applied to part B:

(A B)

To describe how the quine works, it is easiest to start with part B. All that part B needs to do is return the source code of part A:

(A 'A)

Part A's job is to take its own source code, and use it to obtain the source code of the entire quine. Since B is a program that outputs A, A can use code-that-generates on its own source code in order to obtain the source code of B. Once A has the source code of both A and B, it becomes trivial to combine the two to obtain the source code of the entire quine. Here is the complete quine, with the call to code-that-generates inlined:

((lambda (a)
   (let ((b `',a))
     `(,a ,b)))
 '(lambda (a)
    (let ((b `',a))
      `(,a ,b))))
=>
((lambda (a)
   (let ((b `',a))
     `(,a ,b)))
 '(lambda (a)
    (let ((b `',a))
      `(,a ,b))))

Now this is where things start getting interesting. A quine can be thought of as a program that generates its own source code, and immediately returns it. What if instead of immediately returning its own source code, the quine applied a function to it first, and then returned the result of that. The steps for building such a program are almost exactly the same as the steps we took for building the quine. This time, there is a third part F, for the function we want to call. The structure of the program will look like the following:

(F AB)

Where AB has a similar structure to our quine. After breaking AB into the two parts, A and B, the program looks like the following:

(F (A B))

Part B in the above program has the same responsibilities as B in the quine, it returns the source code for A:

(F (A 'A))

Then once A has the source code for itself, it can use code-that-generates to obtain the source code for B. Now that it has the source of A and B, it is easy for it to construct AB. Once part A has the code for AB, it can easily generate the source of the entire program. Here is what the program becomes after filling in everything except F:

(F
 ((lambda (a)
    (let ((b `',a))
      (let ((ab `(,a ,b)))
        `(F ,ab))))
  '(lambda (a)
     (let ((b `',a))
       (let ((ab `(,a ,b)))
         `(F ,ab))))))

What makes this so awesome is that F can be any function we want, and the above program will run F with the source code of the entire program! For example, replacing F with identity causes the program to become a quine:

(identity
 ((lambda (a)
    (let ((b `',a))
      (let ((ab `(,a ,b)))
        `(identity ,ab))))
  '(lambda (a)
    (let ((b `',a))
      (let ((ab `(,a ,b)))
        `(identity ,ab))))))
=>
(identity
 ((lambda (a)
    (let ((b `',a))
      (let ((ab `(,a ,b)))
        `(identity ,ab))))
  '(lambda (a)
    (let ((b `',a))
      (let ((ab `(,a ,b)))
        `(identity ,ab))))))

But we can also do some much more impressive things. We can replace F with a function that lists its argument twice, and get a program that returns a list containing its own source code twice:

((lambda (x) (list x x))
 ((lambda (a)
    (let ((b `',a))
      (let ((ab `(,a ,b)))
        `((lambda (x) (list x x)) ,ab))))
  '(lambda (a)
     (let ((b `',a))
       (let ((ab `(,a ,b)))
         `((lambda (x) (list x x)) ,ab))))))

=>

(((lambda (x) (list x x))
  ((lambda (a)
     (let ((b `',a))
       (let ((ab `(,a ,b)))
         `((lambda (x) (list x x)) ,ab))))
   '(lambda (a)
      (let ((b `',a))
        (let ((ab `(,a ,b)))
          `((lambda (x) (list x x)) ,ab))))))
 ((lambda (x) (list x x))
  ((lambda (a)
     (let ((b `',a))
       (let ((ab `(,a ,b)))
         `((lambda (x) (list x x)) ,ab))))
   '(lambda (a)
      (let ((b `',a))
        (let ((ab `(,a ,b)))
          `((lambda (x) (list x x)) ,ab)))))))

To make writing these self-referential programs easier, we can define a function that fills in F for us. It just requires a little nested backquote trickery.1

(defun self-referential-version-of (f)
  `(,f
     ((lambda (a)
        (let ((b `',a))
          (let ((ab `(,a ,b)))
            `(,',f ,ab))))
       '(lambda (a)
          (let ((b `',a))
            (let ((ab `(,a ,b)))
              `(,',f ,ab)))))))

(self-referential-version-of '(lambda (x) (list x x))
=>
((lambda (x) (list x x))
 ((lambda (a)
    (let ((b `',a))
      (let ((ab `(,a ,b)))
        `(,'(lambda (x) (list x x)) ,ab))))
  '(lambda (a)
     (let ((b `',a))
       (let ((ab `(,a ,b)))
         `(,'(lambda (x) (list x x)) ,ab))))))

Now that we've got a function that can generate self-referential programs for us, I am going to show you how to build something called a quine-relay. A quine-relay is like a normal quine, except it passes through multiple languages. The quine-relay we are going to write is a Lisp program that outputs a C program that outputs the original Lisp program. All we have to do is write a function that takes its argument and writes a C program that prints the argument it was given. Then we can pass that function to self-referential-version-of to get the quine-relay! That's it! Here is a program that will generate the quine-relay:

(self-referential-version-of
  '(lambda (self)
     (format t

"#include <stdio.h>~%int main(){printf(\"%s\",~(~s~));}"

             (remove #\newline (prin1-to-string self)))))

I've omitted the actual quine-relay for brevity, but you can find it here if you are curious. There are a few idiosyncrasies in the above program and in the quine-relay because of the differences in behavior between Lisp and C. For example, in C you can't have multi-line strings, so it becomes easier to remove all of the newlines from the Lisp program, than it is to keep them.

And that's all it takes to write self-referential programs. After seeing how easy it is to generate a quine-relay, it shouldn't be hard to imagine how to write one with many more steps. You may even be able to get up to 100 if you work at it long enough.

The post How to Generate Self-Referential Programs appeared first on Macrology.

20 Apr 2016 5:39am GMT

14 Apr 2016

feedPlanet Lisp

Wimpie Nortje: Keep Quicklisp and Qlot out of your application binary.

'How do I create a Lisp application binary without including Quicklisp or Qlot?'

Quicklisp helps you work faster because it knows where to find libraries and Qlot keeps you mostly out of dependency hell. Without these two tools application development would be dead slow. However, applications distributed as standalone binaries should not contain them.

Quicklisp adds unnecessary code and it will likely try to create a ~/quicklisp directory on your user's machine. This can fail for any number of reasons (such as file permissions or lack of internet access) which will only cause headaches.

Qlot also adds unnecessary code and it will cause the same problems as Quicklisp.

The process of building a binary using Buildapp and Quicklisp without actually having them inside the final application is as follows:

  1. Load your project using the normal Quicklisp method, i.e. (ql:quickload).
  2. Export a manifest file which lists the absolute path to every ASDF system currently loaded into the Lisp image. This is done using (ql:write-asdf-manifest-file).
  3. Exit from Lisp.
  4. Use Buildapp to create your binary. The manifest file must be passed as a parameter, --load-system must be used to load your system and Quicklisp must NOT be loaded.

@xach explained the procedure in this Stack Overflow answer.

When Qlot is employed in a project, the above process becomes:

  1. Load Qlot.
  2. Load your project using Qlot's method, i.e. (qlot:quickload).
  3. Export the manifest file using (qlot:with-local-quicklisp (ql:write-asdf-manifest-file)).
  4. Exit from Lisp.
  5. Use Buildapp to create your binary.

Since Quicklisp is not aware of Qlot (ql:write-asdf-manifest) must be wrapped with (qlot:with-local-quicklisp) in order to generate paths to the project-local Qlot managed libraries instead of the system wide Quicklisp managed libraries.

Example

This is an excerpt of a makefile from a project which uses Qlot. The makefile is used to create a standalone binary that does not contain Quicklisp or Qlot. The prep-quicklisp.lisp script is used to setup Quicklisp for loading the project system from an arbitrary location.

# CCL Flags for manifest build
MANIFEST_FLAGS =  --no-init 
MANIFEST_FLAGS += --batch 
MANIFEST_FLAGS += --load prep-quicklisp.lisp
MANIFEST_FLAGS += --eval '(ql:quickload :qlot)'
MANIFEST_FLAGS += --eval '(qlot:install :$(QL_SYSTEM))'
MANIFEST_FLAGS += --eval '(qlot:quickload :$(QL_SYSTEM))'
MANIFEST_FLAGS += --eval '(qlot:with-local-quicklisp :$(QL_SYSTEM) (ql:write-asdf-manifest-file \#P"$(MANIFEST)" :if-exists :supersede :exclude-local-projects nil))'
MANIFEST_FLAGS += --eval '(quit)'

# Buildapp settings
B_FLAGS =  --output $(OUTDIR)/$(TARGET)
B_FLAGS += --manifest-file $(MANIFEST)
B_FLAGS += --load-system $(QL_SYSTEM)
B_FLAGS += --entry app:main

make_manifest: 
        $(LISP) $(MANIFEST_FLAGS)

make_app: 
        $(BUILDAPP) $(B_FLAGS) 

14 Apr 2016 12:00am GMT

13 Apr 2016

feedPlanet Lisp

Michael Malis: Loops in Lisp Part 4: Series

This is part four of Loops in Lisp. Follow one of the following links for part one, two, or three).

One of the many advantages of programming in a functional style (by this, I mean manipulating your data through the operations, map, fold, and filter) is that your program winds up being made up a bunch of tiny and composable pieces. Since each piece is so small, usually only a few lines each, it becomes trivial to unit test the entire program. Additionally, it is easy to express new features as just the composition of several existing functions. One disadvantage of programming through map and friends, is that there is fairly large time penalty for allocating the intermediate results. For example, every time filter is called on a list, a new list needs to be allocated. These costs add up pretty quickly and can make a functional program much slower than its imperative equivalent.

One solution to this problem is laziness. Instead of allocating a new list every time an operation is performed on a list, you instead keep track of all of the transformations made on the list. Then when you fold over the list, you perform all of the transformations as you are folding over it. By doing this, you don't need to allocate intermediate lists. Although laziness doesn't allocate any intermediate lists, there is still a small cost for keeping track of the laziness. An alternative solution that makes functional programming just as fast as imperative programming is provided by the Series library.1 Series lets you write your program in a functional style without any runtime penalty at all!

Personally, the Series library is my favorite example of the magic that can be pulled off with macros. In short, Series works by taking your functional code and compiling it down into a single loop. In this loop, there is one step per transformation performed on the original list. The loop iterates over the values of the original sequence on at a time. On each iteration, the loop takes a single element, performs all of the transformations performed on the list on that single element, and then accumulates that value into the result according to the folding operation. This loop requires no additional memory allocation at runtime, and their is no time penalty either! As an example, here is a program that sums the first N squares, written using Series:

(defun integers ()
  "Returns a 'series' of all of the natural numbers."
  (declare (optimizable-series-function))
  (scan-range :from 1))

(defun squares ()
  "Returns a 'series' of all of the square numbers."
  (declare (optimizable-series-function))
  (map-fn t 
          (lambda (x) (* x x)) 
          (integers)))

(defun sum-squares (n)
  "Returns the sum of the first N square numbers."
  (collect-sum (subseries (squares) 0 n)))

(sum-squares 10)
=> 385

The above code certainly looks functional, there are no side effects in sight. Now let's look at the code generated by Series. Here is what the macroexpansion of collect-sum looks like:

(common-lisp:let* ((#:out-969 n))
  (common-lisp:let ((#:numbers-966
                     (coerce-maybe-fold (- 1 1) 'number))
                    #:items-967
                    (#:index-965 -1)
                    (#:sum-959 0))
    (declare (type number #:numbers-966)
             (type (integer -1) #:index-965)
             (type number #:sum-959))
    (tagbody
       #:ll-970
       (setq #:numbers-966
             (+ #:numbers-966
                (coerce-maybe-fold 1 'number)))
       (setq #:items-967
             ((lambda (x) (* x x)) #:numbers-966))
       (incf #:index-965)
       (locally
          (declare (type nonnegative-integer #:index-965))
         (if (>= #:index-965 #:out-969)
             (go end))
         (if (< #:index-965 0)
             (go #:ll-970)))
       (setq #:sum-959 (+ #:sum-959 #:items-967))
       (go #:ll-970)
     end)
    #:sum-959))

What series does it looks at the entire lifetime of the sequence from its creation until it is folded. It uses this information to build the above loop which simultaneously generates the original sequence, maps over it, filters elements out of it, and folds it into the final result. Here is the breakdown of the expansion. Lines 1-9 are just initialization. They define all of the variables the loop will be using and set them to their starting values. The important variables to keep track of are #:NUMBERS-966, #:ITEMS-967, and #:SUM-959. As the code "iterates" over the original sequence, #:NUMBERS-966 is the value of the original sequence, #:ITEMS-967 is the square of that value, and #:SUM-959 is the sum of the squares so far. The rest of the code is the actual loop.

The loop first takes #:NUMBERS-966, the previous value of the sequence, and increments it in order to set it to current value of the sequence (since the sequence is the range from 1 to infinity). Next the loop takes the square of #:NUMBERS-966 to get the ith square number and stores that in #:ITEMS-967. Then the loop checks if it ha taken more than N elements out of the sequence, and if so, terminates. Finally the loop takes the value in #:ITEMS-967 and accumulates that into #:SUM-959.

Although the imperative version is equivalent to the original functional code, it is much faster than the functional code if the functional code were to allocate intermediate results or use laziness. This idea of turning transformations on a list into a loop doesn't just work for this simple example, it also works for much more complicated programs. I just find it incredible that Series is able to take such pretty code and compile it into code that is extremely fast.

The post Loops in Lisp Part 4: Series appeared first on Macrology.

13 Apr 2016 8:06am GMT

11 Apr 2016

feedPlanet Lisp

Lispjobs: FRONT-END DEVELOPER (CLOJURESCRIPT), Vital Labs, San Francisco

http://vitallabs.co/jobs/full-stack.html

FRONT-END DEVELOPER (CLOJURESCRIPT)

We are looking for a generalist developer with a front-end focus and strong interest in working with the Clojure ecosystem who can lead or contribute to all aspects of a modern technology stack. Our production systems are built almost entirely in Clojure/Clojurescript with help from Java/Javascript libraries as needed. We leverage Cassandra and Datomic as our data storage infrastructure and orchestrate all these tools with Ansible. We build our web interfaces with React, as well as our current mobile interfaces. We will be expanding our platforms into native iOS/Android and are exploring new tools such as React Native.

We emphasize simplicity and elegance to combat the inherently complex nature of healthcare. If you are a jack-of-all-trades with a deep interest in building front-end systems that involve complex client-server IO, data visualization, and helping people make sense of machine learning dat, then we'd love to talk to you.

YOU SHOULD HAVE

IT'D BE GREAT IF YOU HAD

OTHER STUFF THAT IS VERY RELEVANT


11 Apr 2016 2:58pm GMT

07 Apr 2016

feedPlanet Lisp

Wimpie Nortje: Explaining version priority handling in Qlot.

How do I specify a library version that is newer than the specified Quicklisp distribution?

While struggling to match a database, Linux libraries, database drivers and all the correct Quicklisp library versions one question I struggled a lot with was 'How do I specify a library version that is newer than the specified Quicklisp distribution?'

The Qlot documentation says about library priorities: 'If multiple distributions provide the same library, lower one would take priority over higher ones.'

This can be interpreted in more than one way which can lead to confusion. The correct interpretation is that the 'lower one' in the documentation refers to the order of the declarations in the qlfile.

To explain Qlot's priority handling more clearly: The order of the declarations in qlfile determines the priority. When multiple distributions provide the same functionality, later statements override the the earlier ones.

The two examples demonstrate the Qlot priority handling.

Using Clack from the latest Quicklisp distribution.

ql :all 2014-01-13
ql clack :latest

Using Clack from the 2014-01-13 distribution.

ql clack :latest
ql :all 2014-01-13

07 Apr 2016 12:00am GMT

Fernando Borretti: Using LMDB from Common Lisp

LMDB is a fast key-value store. This talk is useful for those who want to learn more. The design of LMDB means many of the things that are standard in other databases - write-ahead logs, and all the filesystem housekeeping necessary to implement concurrent transactions - is unnecessasry in LMDB.

The bindings are implemented as two separate libraries: liblmdb, a low-level, autogenerated CFFI binding; and lmdb, the high-level CLOS binding.

Usage

Using LMDB requires some work. A simple query requires setting up (and tearing down) a whole stack of objects, namely:

  1. An environment, which is, essentially, a collection of databases. You create the environment object by passing a directory where LMDB will store its data.
  2. A transaction within that environment. All queries have to take place inside a transaction.
  3. A database access object, which is created from a transaction, after the transaction's been started. The database object keeps the name of the database we're accessing within the environment.

Or,

LMDB lifecycle diagram

When you have the database object, you can set, retrieve and delete key-value pairs. For more complex operations, you have to use cursors, which add another level of lifecycle management within databases.

Examples

Starting by loading LMDB and Alexandria,

CL-USER> (ql:quickload '(:lmdb :alexandria))
To load "lmdb":
  Load 1 ASDF system:
    lmdb
; Loading "lmdb"
.............
To load "alexandria":
  Load 1 ASDF system:
    alexandria
; Loading "alexandria"

(:LMDB :ALEXANDRIA)

We'll store the database in your home directory under lmdb-test/, and use a hardcoded named LMDB database:

CL-USER> (defparameter +directory+
           (merge-pathnames #p"lmdb-test/" (user-homedir-pathname)))
+DIRECTORY+

CL-USER> (defparameter +db-name+ "mydb")
+DB-NAME+

First, let's abstract away all of the housekeeping:

CL-USER> (defmacro with-db ((db) &body body)
           (alexandria:with-gensyms (env txn)
             `(let ((,env (lmdb:make-environment +directory+)))
                (lmdb:with-environment (,env)
                  (let ((,txn (lmdb:make-transaction ,env)))
                    (lmdb:begin-transaction ,txn)
                    (let ((db (lmdb:make-database ,txn +db-name+)))
                      (lmdb:with-database (,db)
                        (prog1
                          (progn
                            ,@body)
                          (lmdb:commit-transaction ,txn)))))))))
WITH-DB

We can retrieve keys using the get function:

CL-USER> (with-db (db)
           (lmdb:get db #(1)))
NIL

Obviously this returns NIL, since we haven't actually set anything. To add or overwrite a key value pair, you use put:

CL-USER> (with-db (db)
           (lmdb:put db #(1) #(1 2 3)))
#(1 2 3)

CL-USER> (with-db (db)
           (lmdb:get db #(1)))
#(1 2 3)

That's better. But raw byte vectors are unwieldy: how can we store actual data?

First, let's get rid of this key/value pair so we can get back to a blank slate. We use the del function for that:

CL-USER> (with-db (db)
(lmdb:del db #(1))) T

CL-USER> (with-db (db)
           (lmdb:get db #(1)))
NIL

Alright, so, real data. These bindings only handle byte vectors: fancier datatypes are explicitly anti-features. Serialization of more complex data structures to byte vectors should be done by a higher-level library - maybe I'll write a Moneta clone for Common Lisp.

Storing strings is pretty simple, all you need is the trivial-utf-8 library:

CL-USER> (ql:quickload :trivial-utf-8)
To load "trivial-utf-8":
  Load 1 ASDF system:
    trivial-utf-8
; Loading "trivial-utf-8"

(:TRIVIAL-UTF-8)

CL-USER> (defun str->vec (str)
           (trivial-utf-8:string-to-utf-8-bytes str))
STR->VEC

CL-USER> (defun vec->str (vec)
           (trivial-utf-8:utf-8-bytes-to-string vec))
VEC->STR

Now we can use this like this:

CL-USER> (with-db (db)
           (lmdb:put db (str->vec "Common Lisp")
                        (str->vec "An ANSI-standarized Lisp dialect")))
#(65 110 32 65 78 83 73 45 115 116 97 110 100 97 114 105 122 101 100 32 76 105
  115 112 32 100 105 97 108 101 99 116)

CL-USER> (with-db (db)
           (vec->str (lmdb:get db (str->vec "Common Lisp"))))
"An ANSI-standarized Lisp dialect"

How about integers? We use bit-smasher for that:

CL-USER> (ql:quickload :bit-smasher)
To load "bit-smasher":
  Load 1 ASDF system:
    bit-smasher
; Loading "bit-smasher"
...
(:BIT-SMASHER)

CL-USER> (defun int->vec (int)
           (bit-smasher:int->octets int))
INT->VEC

CL-USER> (defun vec->int (vec)
           (bit-smasher:octets->int vec))
VEC->INT

And usage:

CL-USER> (with-db (db)
           (lmdb:put db (str->vec "Common Lisp/age")
                        (int->vec 21)))
#(21)

CL-USER> (with-db (db)
           (vec->int (lmdb:get db (str->vec "Common Lisp/age"))))
21

This works with Common Lisp's arbitrary-precision integers, as well. Let's try ten to the three hundredth power1:

CL-USER> (expt 10 300)
1e300

CL-USER> (integer-length *)
997

Nine hundred and ninety seven bits is larger than the average machine word, and will be until we start dismanting planets into computers2. Let's see how it works:

CL-USER> (with-db (db)
           (lmdb:put db (str->vec "big integer")
                        (int->vec (expt 10 300))))
#(23 228 60 136 0 117 155 165 156 8 225 76 124 215 170 216 106 74 69 129 9 249
  28 33 197 113 219 232 77 82 217 54 244 74 190 138 61 91 72 193 0 149 157 157
  11 108 200 86 179 173 201 59 103 174 168 248 224 103 210 200 208 75 193 119
  247 180 40 122 110 63 205 163 111 163 179 52 46 174 180 66 225 93 69 9 82 244
  221 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
  0 0)

CL-USER> (with-db (db)
           (vec->int (lmdb:get db (str->vec "big integer"))))
1e300

So all of this is fine, but what if we don't know the contents of the database? That's what cursors are for, but we don't need to deal with them directly because this wrapper abstracts them:

CL-USER> (with-db (db)
           (lmdb:do-pairs (db key value)
             (format t "~A: ~A~%~%" key value)))
#(67 111 109 109 111 110 32 76 105 115 112): #(65 110 32 65 78 83 73 45 115 116
                                               97 110 100 97 114 105 122 101
                                               100 32 76 105 115 112 32 100 105
                                               97 108 101 99 116)

#(67 111 109 109 111 110 32 76 105 115 112 47 97 103 101): #(21)

#(98 105 103 32 105 110 116 101 103 101 114): #(23 228 60 136 0 117 155 165 156
                                                8 225 76 124 215 170 216 106 74
                                                69 129 9 249 28 33 197 113 219
                                                232 77 82 217 54 244 74 190 138
                                                61 91 72 193 0 149 157 157 11
                                                108 200 86 179 173 201 59 103
                                                174 168 248 224 103 210 200 208
                                                75 193 119 247 180 40 122 110
                                                63 205 163 111 163 179 52 46
                                                174 180 66 225 93 69 9 82 244
                                                221 16 0 0 0 0 0 0 0 0 0 0 0 0
                                                0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
                                                0 0 0 0 0 0 0 0 0)

NIL

Which is not very informative, since these are just byte vectors.

Finally, you don't want to keep the database directory:

CL-USER> (uiop:delete-directory-tree +directory+ :validate t)
#P"/home/eudoxia/lmdb-test/"

Footnotes

  1. I replaced the actual integer representation from the REPL with 1e300 for brevity.

  2. A 1024-bit wide machine word is probably overkill even then.

07 Apr 2016 12:00am GMT