PicoLisp Snippets

Example of starting the server with logging:
./p projects/rss-reader/main.l -go -wait >> rss-reader.log 2>&1 &

Run a child process as a repl in a currently running server on port 80:
./p bin/psh 80

(setq Words (list))
(in "words.txt" 
  (while (line) (push1 Words (any (pack @)))))
(setq Words (sort (car Words)))
(balance 'Words2 Words)
(out "words" (print Words2))

Input is on the form of one “word” per line. Will read all words and create a balanced index tree and save it to the “words” file.

Importing the tree:

(setq *Words (any (in "words" (till NIL T))))

Rerouting the output buffer :

(pipe (xml El) (line T))

In the above case we know that (xml) is not printing line endings, (pipe) will in this case return all that is being printed in (xml) and no output will take place. Similar to ob_start() and ob_flush() in PHP.

Getting a page with CURL (provided that you have done apt-get install curl first):

(out "ongoing.xml" (prin (in '(curl "http://www.tbray.org/ongoing/ongoing.atom") (till NIL T))))

Shuffle list:

(de shuffle (L)
   (by '((El)(rand)) sort L))

Using the tilde (~) with a function expecting a variable amount of arguments. It will allow us to use a list and splice its members as arguments, very handy sometimes:

(dm splitContent> (L)
   (eval '(split L ~(getUniCodePunctuation> '+Gh))))

Here we split a list, for instance ‘(“h” “e” “+” “l” “l” “o”) by all unicode punctuation characters.

Summing a list, the below will return 10:

(sum + (list 3 3 3 1))

Blobs, extending +Entity:

(dm put> (Key Val)
   (ifn (== Key 'body)
      (super Key Val)
      (super 'body T)
      (out (blob This 'body)
         (prinl Val))))

The above will put the contents of Val in the blob relation with its name in Key. The blob has to be created first with (put!> This ‘body T), then we can use out combined with blob to put the contents of Val into the blob file.

This is how lose!> can be extended:

(dm lose!> ()
   (call 'rm (blob This 'body))
   (put!> This 'body NIL)
   (super))

First we remove the file with rm, then we put NIL where we usually would’ve had the filename (that step is probably redundant since we’re removing the whole entity anyway through the call to super).

Getting the contents of the blob file:

(dm blobCont> (Key)
   (in (blob This Key) (till NIL T)))

Note the way we call till with NIL and T to avoid getting the result back as a character list.

Flattening an arbitrary tree:

(de flatten (L)
   (make
      (recur (L)
         (for El L
            (if (lst? El)
               (recurse El)
               (link El))))))

I managed this one by myself, yay! We begin with initiating a make environment, then we use recur and recurse to create tail recursion. Reason being we don’t want to initiate any further make environments because that would result in lists being returned and that’s exactly what we do NOT want.

(let Tst '("t" "e" "s" "t")
   (if (match '(@A ~(chop "es") @B) Tst)
      (print @A)
      (print "no match")))

A good shortcut when matching with long strings, the above example is of course not representative but imagine if that “es” part had been 20 characters long instead.

(setq Str "ab")
(println 
   (make 
      (in (list 'echo Str) 
         (link (char)) 
         (link (char)))))

This one can come in handy when you already have a string in memory and want to use input channel functions without having to first save the string to disc.

(de mobileAgent? ()
   (let HttpAgent (pack *Agent)
      (for Agent '("Android" "iPhone" "iPad" "BlackBerry" "Symbian" "Nokia" "nook" "Kindle")
       (T (sub? Agent HttpAgent) Agent) ) ) )

The above will check if we have a visitor using a mobile device on our site. Feel free to extend with less common devices, here is a good page with user-agent strings.

“^J” is line feed and “^M” carriage return.