Introducing Seed, an interactive software environment built on ASDF

Andrew Sengul ml at imagegardenphoto.com
Sun Nov 5 23:18:26 UTC 2017



On 11/02/2017 02:12 AM, Faré wrote:
>
> I'm a bit confused. Is it a Lisp DSL, a graphical programming system,
> the two next to each other, or the two at the same time, etc.?
> When you program graphically, how do you specify the division in files
> and/or systems?
Seed is an interactive programming system that uses graphics more than
mainstream programming tools. I wouldn't say it's purely a graphical
system since you could use it with a text-based interface, but it's much
more graphical than your standard IDE. Seed uses DSLs to define some
parts of itself, and it makes a few key extensions to Lisp like the
(meta) macro that are needed for it to work.

The translation of the graphical interface to files and systems is
defined by the I/O spec language, one of Seed's main DSLs. Look at
https://github.com/phantomics/seed/blob/master/demo-sheet/demo-sheet.seed and
you'll see these forms:

1. (put-file (table-specs (get-file :-self)) :-self)
2. (put-file (sheet-content (get-file :main)) :main)

Form 1 is under the (main) branch and Form 2 is under the (cells)
branch. If you watch the demo video, you'll see the "main" and "cells"
branches in the visual display of the spreadsheet interface. The meaning
of Form 1 is "take the input to the main branch, combine it with the
content of the "main.lisp" file using the "table-specs" I/O medium, then
save the resulting data to the "main.lisp" file.

Where does the "main.lisp" filename come from in Form 1? Notice that the
second argument to put-file and the first argument to get-file is
:-self. When the :-self argument is present, the name of the branch
("main" in this case) is string-downcased and has ".lisp" appended to it.

In Form 2, instead of using the name of the branch ("sheet") the keyword
:main is used, which is converted to "main.lisp." If you look at
https://github.com/phantomics/seed/blob/master/demo-sheet/main.lisp,
you'll see that both the data for the spreadsheet cells and the
cell-manipulating forms from the left column are represented there. In
this branch, the "sheet-content" medium is used to convert between the
format for stored spreadsheet data and the format used in the
spreadsheet interface.

So Seed's interface can have any kind of file structure behind it. In
this case, I use two different interface branches to interact with a
single Lisp file. I could also have a dozen different files downstream
from a single interface branch.

One of Seed's core ideas is that programming interface elements should
be "self-actualized" and not tied to arbitrary structures like text
buffers. The interface branches may have relationships with text files,
remote APIs and other things but they are not defined by them. Seed
makes it easy to create "views" of code; for instance, you could have a
display mode where you are shown a function at the beginning of the code
display followed by every other function in the software system that
calls that first function, regardless of what file it's specified in.
You could also create a view for a function and its unit tests.

Implementing things like this would be much harder in Emacs since Emacs
is still tightly coupled to the concept of the text buffer as the main
interactive element. The self-actualized nature of Seed's interface
branches is the reason that they are amenable to graphical programming
and other atypical modes of interaction.

Let me know if this makes sense. By the way, if you'd like to learn more
I've been doing 1-on-1 workshops with developers to show them the basics
of using and extending Seed, either in person or via screen share. The
latter option would probably work best for you if you're interested.
>> The main thing to understand is that it's a dataflow language. Each
>> successive form like (set-time) and (codec) is passed the input data,
>> does something to it and passes it to the next form in the list. So the
>> till macro transforms something like "(set-time) (do-something) (codec)"
>> to "(codec (do-something (set-time original-data)))." With this
>> language, I can implement things like clipboards and undo history in
>> unique ways for different systems.
>>
> Reminds me of my uiop:nest macro. https://fare.livejournal.com/189741.html
> More seriously, congrats, it really looks neat at first glance.
That's cool. In my case I'm reversing the order of expansion as well as
adding the implicit input, so (a) (b) (c) expands to (c (b (a input))).
This makes it more intuitive to specify long series of media. Also, it's
possible to assign two different possible expansions to an I/O medium
depending on if it's taking input or output. So inside the (in) form,
(a) will do something different than it does inside the (out) form since
it's handling input rather than output.

Andrew



More information about the asdf-devel mailing list