
Reazon – miniKanren for Emacs - geospeck
https://github.com/nickdrozd/reazon
======
nickdrozd
Some background: miniKanren is a logic programming language in the
neighborhood of Prolog (they are similar in the way that Python and Javascript
are similar). The language is described and implemented in the book _The
Reasoned Schemer_ , which is a sequel to the classic _The Little Schemer_. The
major implementations of miniKanren are in Clojure and Racket.

I was reading TRS and wanted to run the code, but I didn't have (and didn't
feel like getting) Clojure or Racket. At the same time, I wanted to try my
hand at some serious Elisp programming. The obvious answer was to put
miniKanren into Emacs, and that's what this is.

------
CamTin
Fun! I highly recommend watching Dan Friedman and William Byrd give their
miniKanren conference talk (they've done it a number of times slightly
differently) e.g. this one at the "Conj" Clojure convention:
[https://www.youtube.com/watch?v=5Q9x16uIsKA](https://www.youtube.com/watch?v=5Q9x16uIsKA)

It's really a fun presentation and does a great job introducing logic
programming and miniKanren to lay programmers.

------
sqrt17
Snarky aside: you can also install a real Prolog (e.g. SWI Prolog) and run
that in an Emacs session, and will be more performant and expressive than
anything you would build on top of Emacs Lisp

~~~
carlob
To be fair I always thought MiniKanren was supposed to be more of a tutorial
than a full fledged prolog. I once tried my hand at 'porting' it to
Mathematica: it's been mostly an exercise in adapting the semantics rather
than the syntax.

------
bjoli
Now, I am all for logic programming, but i have rarely found a place where
such a solution haven't been to much of a mental burden for a project with
more contributors than only myself. I love to find problems where logic
programming is a good fit, and I love the elegance of such solutions, but I
can'tc expect my team to actually grok it.

What are your experience? Any successful uses?

~~~
phaedrus
I tried to integrate a C++ logic programming library (Castor) with Sqlite and
a linear constraint solver to make a dynamically sizing MFC (Windows GUI)
layout library. I thought it would "dog on surfboard with jet pack" awesome,
but it turned out more like "taking Space Shuttle to McDonald's drive-thru."
That is, it made a few hard things simple but also made a lot of easy things
complicated.

I still think logic programming has untapped potential for use in "regular"
programs, but we haven't invented the best way to integrate it yet. In order
to take advantage of bi-directional nature of logic relations (every argument
can be input or output) you really need all the consituent pieces of that
computation to be relational, as well. (To do what William Byrd calls "running
backwards".) But to support this in an imperative language, where some of your
relation is purely logical and some of it is implemented with user-defined
callbacks, requires careful defensive programming in the C++ callback
functions.

Moreover the inherently lazy/on-demand nature of logic programming does not
fit well with the way debuggers for imperative programs work. This is not
specific to logic programming (for example, debugging a regular expression
that is inside a C++ program is a similar case). What is needed is a way to
tell the debugger to display the file, line, and character position where the
regex or logic relation or SQL statement was defined and not the position
inside the engine which is interpreting that data.

I would contrast the "fully integrated, compute on-demand" way I was
attempting to use a logic programming library with the way Sqlite natively
works. With Sqlite, the steps of preparing a statement, looping over the rows,
and finalizing the statement are all distinct steps (as called from C/C++
code). The Sqlite query planner can calculate the entire plan from the SQL
string and the tables it manages internally. When Sqlite computes each next
row as you step the prepared statement object, it is free to use whatever
evaluation order was chosen by the query plan, because it all happens
synchronously in the "step" call and then returns.

Of course the drawbacks of this approach (the famous impedance mismatch) are
well-known to anyone who has used any kind of SQL database API from a C-family
language. So I am not saying it is the best we can do. However I believe this
API interaction strategy is one way (surmised - I haven't tried it yet) that
logic programming could be integrated with an imperative program without it
devolving into an un-traceable mess: treat it like using an SQL engine. Or
like compiling a regex, stepping through, and reading the captures.

I find this answer ultimately disappointing, because I feel that such a
powerful technique ought to transform how you think about and structure your
whole program. And instead of solving the impedance-mismatch problem, it gives
up on it. But having tried things the other way (coroutining logic and
imperative code), if I were to try again, I would try this other way (treating
the logic program like a database or query engine).

~~~
specialist
Heh. I feel ya.

\--

My first real gigs were CAD/CAM based. I really thought both constraint and
parametric programming were the future.

Finally gave up on constraints for UI layout. My alternative was to hand code
the heuristics, esthetics. I created DesignGridLayout (for Java), based on
canonical grids (a graphic design notion). It's now defunct, but if I ever
circle back to UI work, that's where I'll resume.

\--

That impedance mismatch has tripped me up my entire career.

I forfeited in a different way. I inverted the work flow.

I now use working examples to generate the code.

In the case of databases: instead of an ORM to generate SQL, I use SQL to
generate the JDBC/ODBC wrappers.

I can't speak to implementing a query planner (way beyond my intellect), or
your notion of starting with a different mental model, but it's food for
thought.

~~~
phaedrus
For my GUI layout library I decided "snaplines" could be a more fundamental
concept than grids (because a grid can be defined with horizontal and vertical
snaplines). Essentially it's just a linear constraint like "there exists a
variable X_snap1, such that box1.right <= X_snap1 and box2.left >= X_snap1."
The key is that if you re-use the same snapline variable for subsequent rows,
it aligns a column.

Another key idea was that the snaplines are completely independent from the
logical (hierarchical, tree) structure of the "document" (aka form). So like
if you wanted controls above and below something to be horizontally aligned
with each other, but not affect content in the middle, you could do that by
just only associating some controls with those snaplines; the fact that the
snapline cuts across the middle content need not affect it because it's an
abstract "membership" in a group not a physical barrier.

How I came to this design was I had done XAML layouts with WPF on Windows, and
while I preferred to use the Grid tag to solve most layout problems, I was
also frustrated with its limitations: you kind of have to plan ahead, if you
discover you need another alignment line you have to renumber things, or maybe
you need to fuse certain cells, etc. I realized that I was using the grid to
get alignment lines, but didn't (necessarily) want all of the other behaviors
which come with it.

------
jordigh
> namely that of ending the names of test functions with p

I feel like this was a missed opportunity to say "predicate" instead of "test
functions".

------
amirouche
I think nothing can beat minikanren (or microkanren) to query a quad store. It
make recursive queries easy.

~~~
jyriand
Any examples you can share?

~~~
amirouche
Give a use case I will translate it to microkanren query.

I don't have an interesting query to show you. My tests were done on synthetic
data.

------
shawn
Bahaha, 3 of the 30 front page stories are about Lisp. Yessss, rise, Rise! Let
the Lisp dominance commence! Take to the streets and take macros into your
hearts! Demand a formal holiday to celebrate all conses! Tear off those
strongly typed shackles and write a macro system to expand your grocery lists!
[https://github.com/sctb/lumen](https://github.com/sctb/lumen)

Today is a good day.

~~~
patrickg_zill
APL family of languages is next?

I have been seriously looking into a good APL (or deciding between A+ / J /
etc.) for use in scripting. Right now I think AWK to massage the data and
${APL choice} to analyze it might be the right way to go.

~~~
sdegutis
APL seems to require buying another keyboard just to edit it. Maybe an IDE can
help me type SD←((+/((X - AV←(T←+/X)÷⍴X) _2))÷⍴X)_ 0.5 but I'm not really sure
I want it to.

AWK is highly specialized to interpret ad hoc data structures encoded in
strings and spit out new similarly ad hoc strings, like all other unix utils.
Personally I hope that's not the future. In fact I wish for the day our
terminals and coreutils are replaced with utilities that speak JSON or
something.

~~~
Jtsummers
Dyalog and the emacs APL mode both let you use a prefix key for the special
characters. By default it's either . or `. So .. gives you a period, and .r
gives you rho. It's not so bad if you practice with it for a bit each day for
a couple weeks. I became reasonably proficient after about a month of 30
minutes a day of APL practice earlier this year. It would be harder if you
don't touch type yet (I suspect).

