Lispworks from SublimeText

Create a “build script” to dump a headless image:

(in-package "CL-USER")
(load-all-patches)
(save-image "~/lw-console"
                        :console t
                        :environment nil
                        :multiprocessing t)

Run it

~ /Applications/LispWorks\ 8.0\ \(64-bit\)/LispWorks\ \(64-bit\).app/Contents/MacOS/lispworks-8-0-0-macos64-universal -build ~/tmp/resave.lisp
; Loading text file /Applications/LispWorks 8.0 (64-bit)/Library/lib/8-0-0-0/private-patches/load.lisp
LispWorks(R): The Common Lisp Programming Environment
Copyright (C) 1987-2021 LispWorks Ltd.  All rights reserved.
Version 8.0.0
Saved by LispWorks as lispworks-8-0-0-arm64-darwin, at 06 Dec 2021 17:56
User agambrahma on agams-mbp.lan
; Loading text file /Users/agambrahma/tmp/resave.lisp
;  Loading text file /Applications/LispWorks 8.0 (64-bit)/Library/lib/8-0-0-0/private-patches/load.lisp
Build saving image: /Users/agambrahma/lw-console
Build saved image: /Users/agambrahma/lw-console
Build split image: /Users/agambrahma/lw-console.lwheap
Build executable: /Users/agambrahma/lw-console

Install SublimeREPL and Slyblime

Modify settings

Within sly.sublime-settings, you should have something like:

  "inferior_lisp_process": {
    "command": ["/Users/agambrahma/lw-console"],
    "autoclose": true,
    "loading_time": 2,
    "setup_time": 1
  },

(where command points to the executable generated above)

Kick start SLY

Run SLY: Start and connect to an inferior lisp instance

Enjoy REPLing !!

Shen lives

Discovery

I remember coming across “Qi” a long time ago, a work of brilliance by one Dr. Mark Tarver.

He happened to have a lot of quirky essays as well, and had … interesting interests.

Several years ago Qi morphed into Shen, a “kernel” that could be hosted on a variety of languages but exposed the ability to build

Loss

It seemed like something new was coming to pass, then … all of a sudden he deleted a bunch of web pages, stopped working, and I didn’t see anything new for a while, and … I lost touch.

Renaissance

Recently I wondered again (“what happened to that guy?“) and it turns out the project is very much alive and kicking!

Resources

  • The “Book of Shen” has been updated to a 4th edition
  • There is a new website that describes its unique features with examples

All this is encouraging, and worth checking into again soon.

Simple web programming (in Common Lisp)

It can be really simple.

Stumbled across this …

… and (yes, questionable aesthetics aside) decided to recreate it:

Really does work as advertised:

One-time stuff I had to run:

(ql:quickload 'lass)
(ql:quickload 'spinneret)
(ql:quickload 'hunchentoot)

That’s it. Out of the box. Didn’t start any project, or any framework. Scales up and down, and starts small.

This was less than 10 minutes.

Lisp, CLOS and Math

What, you say, mathematicians just have to use Haskell ??

Stop right there, and read this.

Technically, there’s nothing new to see here at all. Lisp is high-level and low-level. Lisp is multi-paradigm. Lisp has uniform syntax. Blah blah blah. You’ve heard it all.

Still, some people seem to require an “argument from authority” (and usually still keep looking) … in which case you might be persuaded by this.

An extract (describing how defclass and defgeneric can be handily abused to yield whatever you like):

For example, a mathematician who installs under CLOS the traditional mathematical categories must organize his work as follows:

  • The defclass statements will be used to define what a “set” object is, what a “group” object is, what a “chain complex” object is, and so on.

  • The defgeneric statements will be used to define functions working on these objects, but these “functions” are traditionally called in this case functors in mathematics; therefore one defgeneric statement for the sum functor, another defgeneric for the classifying space functor, and so on.

  • Finally each generic function will have various methods to adapt the generic function to specific cases; for example the product of two objects of some category is also an object of this category with the corresponding structure to be defined. Therefore one product method for the sets, another product method for the magmas, another method for the monoids, and so on. The call-next-method and change-class functions will allow these methods to possibly refer to the less specific ones.

Summing up

I came across this post talking about numerical speed in Clojure, so I thought I would try out the equivalent in Common Lisp (Clozure CL) on my Macbook:

CL-USER> (let* ((arr-size 3000000)
        (double-arr (make-array arr-size :element-type 'single-float)))
       (dotimes (i arr-size)
         (setf (aref double-arr i) (random 1.0)))
       (time (loop for i from 0 below arr-size
            summing (aref double-arr i))))
(LOOP FOR I FROM 0 BELOW ARR-SIZE SUMMING (AREF DOUBLE-ARR I))
took 45,649 microseconds (0.045649 seconds) to run.
During that period, and with 4 available CPU cores,
     45,558 microseconds (0.045558 seconds) were spent in user mode
         57 microseconds (0.000057 seconds) were spent in system mode
1500183.5

So — 45 milliseconds, not bad.

Lispium ?

What if you did the following:

  • Take a chromebook
  • Modify the chromium build running to run Sbcl within it.
  • Create lisp bindings to the internal surface, so that all UI elements can be created and manipulated within the Lisp image.
  • Allow downloading, compiling and running arbitrary lisp code
  • One of the tabs is always a Repl
  • Add a caching filesystem that would persist part or whole of the image

… might this create a modern-day Lisp machine? Maybe.

Did I miss anything obvious here? If not, this sounds doable in a few years.

I’m lazy, do you if you like this idea (I’m sure there’s a guaranteed niche market for these machines), go ahead and throw it on to Kickstarter. Or something.

Baktoo: Taking baby steps with generative art

Continuing (or stumbling) along a path to using Common Lisp for stuff I consider fun, I came up with this.

As mentioned in the `README`, I need to work on making this more efficient.

Stuff I learned along the way:

  • I love how I can focus on “making it work” _before_ worrying about “making it fast”
  • Utilities exist for a reason. _Use them_ (I’ve decided to stick with `:rutils`)
  • Don’t be afraid of using libraries. I found `:cl-log`, which is amazingly well-written and I will never use all of it, but just the basic use case of toggling levels of verbosity is good enough for me, and something that would normally be hard to do.
  • Building up the system works really well. This is the first time I’ve had an experience of writing stuff that sort of _just worked_, since it felt like I was **directly translating my thoughts into code**.
  • It’s easy to rapidly create and modify functions, stubs, what not, while keeping them all in view, in the same 100 or so lines of vertical space (contrast with switching between (say) multiple `.java` files)

Anyway, here are a couple of samples I made with this (click to see detailed image):
Baktoo - 2

Baktoo - 1

SDL on OSX

(ql:quickload 'lispbuilder-sdl) worked right away on an ubuntu box, but failed (couldn’t find `cocoahelper) when I tried the sam on my Macbook.

The fix is to install SDL, then go to ~/quicklisp/dists/quicklisp/software/lispbuilder-20140113-svn/lispbuilder-sdl/cocoahelper and type make. After this, the ql:quickload form succeeds.

However, the same dummy blank screen test program that worked fine on the linux box doesn’t seem to work anymore:

(defpackage :simple-sdl
  (:use :common-lisp
    :lispbuilder-sdl))

(in-package :simple-sdl)

(defun main-screen ()
  (sdl:with-init ()
    (sdl:window 300 300
        :title-caption "Simple SDL"
        :icon-caption "Simple SDL")
    (sdl:with-events ()
      (:quit-event () t)
      (:key-down-event ()
               (sdl:push-quit-event)))))

It fails with this backtrace:

Backtrace:
  0: ("bogus stack frame")
  1: ("foreign function: CGSScanconverterRenderRGBMask")
  2: ("foreign function: create_rgb_bitmap")
  3: ("foreign function: CGGlyphBitmapCreateWithPath_32")
  4: ("foreign function: CGFontCreateGlyphBitmap")
  5: ("foreign function: _ZN14CGGlyphBuilder22create_missing_bitmapsEPK17CGGlyphIdentifiermPPK13CGGlyphBitmap")
  6: ("foreign function: render_glyphs")
  7: ("foreign function: draw_glyph_bitmaps")
  8: ("foreign function: ripc_DrawGlyphs")
  9: ("foreign function: draw_glyphs")
 10: ("foreign function: CTFontDrawGlyphsAtPositions")
 11: ("foreign function: -[CUITextEffectStack drawGlyphs:inContext:usingFont:atPositions:count:lineHeight:inBounds:atScale:]")
 12: ("foreign function: -[CUICatalog drawGlyphs:atPositions:inContext:withFont:count:stylePresetName:styleConfiguration:foregroundColor:]")
 13: ("foreign function: -[NSLineFragmentRenderingContext drawAtPoint:inContext:]")
 14: ("foreign function: _NSStringDrawingCore")
 15: ("foreign function: _NSDrawTextCell")
 16: ("foreign function: -[NSTitledFrame _drawTitleStringIn:withColor:]")
 17: ("foreign function: -[NSThemeFrame _drawTitleStringInClip:]")
 18: ("foreign function: -[NSThemeFrame drawFrame:]")

Just when I was getting excited about it … so what other platform-independent Lisp GUI should I use 😦 ?

BTW, while we’re knocking this (unfairly, of course), I should point out it doesn’t support SDL 2.x

I then stumbled on this library which seemed better maintained, and modified my example:

(defun main-screen ()
  (sdl2:with-init (:everything)
    (sdl2:with-window (win :w 300 :h 300
               :title "Simple SDL")
    (sdl2:with-event-loop (:method :poll)
      (:quit () t)
      (:keydown ()
        (sdl2:push-quit-event))))))

Now a window did get created, but it didn’t play well with OSX (it wasn’t a “window” so much as a blank square of real estate on the screen, with a spinning beachball and no response).

So … the search for a basic simple drawing facility continues 😦