~project-mage/news

Progress Report #5

Details
Message ID
<877cn8zhzr.fsf@arch.mail-host-address-is-not-set>
DKIM signature
missing
Download raw message
Progress Meter:

- [WIP] Knowledge-Representation Improvements
  - [X] Better syntax, cleaner API & refactoring
  - [~] Meta info in slots
  - [ ] Advice
  - [X] Change predicates
  - [ ] Multi-Methods (value-based)
- [WIP] Constraint Management Improvements
  - [X] Better syntax & some refactoring
  - [W] Parameterized pointer variables
  - [X] Advice (for constraints)
  - [X] Store constraints as KR objects
  - [ ] Async execution
- 2D Graphics
  - [ ] Linear Algebra and Geometry additions
  - [ ] 2D API for geometry + Backend (via SDL)
  - [ ] Event objects + Backend (via SDL)
  - [ ] Text API + Backend (via Pango)
- [ ] Cells
- [ ] Configurations
- [ ] Some demo (after everything else)
 
---

August sucked progress-wise and so did most of September. Just like did
all of the summer, really. There were a few reasons for the long break,
but the facts are still the facts: not much progress in those 4.5 months
or so.

In the future, I will try not to raise people's hopes for quick
short-term progress, it will probably be best I only show something once
actually done or right in the works.

In any case, I have been back to working on the project over this past
month, and there's some decent news:

*** Schema creation has been revised to be more straightforward and
    without overhead. ***

Instead of doing

(Ξ (:init-options '(:inheritance :static
                    :ht-args (:test #'equalp)))
   (a 10))

now one would do this instead:

(Ξ (test #'equalp)
   (inheritance :static)
   (a 10))

The new approach manages to do more work at compile time, and is quite
simpler than before, both in implementation and in usage.

*** Ditched the /constraints as schemas/ way. ***

Constraints being schemas worked, but after some thinking, I figured
there won't be that much practical benefit to that approach after all. I
thought that was unavoidable for ergonomics, but I don't think that
anymore. As long as constraints (1) can be schema-like and (2) provide a
way of customization, things should be quite fine. The former is now
accomplished via struct-slot access over the typical schema read/write
operations. The solution to the latter was simply to allow storing a
custom object within a constraint and allow inheritance for it (simply
via a user-supplied function).

What's good about the new approach is that it doesn't incur additional
costs -- those were around 25% both in terms of creation speed and
memory consumption. And while that may be not that much, what the hell,
right? Constraints are used for inheritance, which means there's a
constraint for every slot in an object, so that was implying a certain
tangible cost for every object created with a dynamic inheritance
option. Not an entirely pressing cost, but still.

But the more general motivation behind the initial work was to allow any
struct to derive from `schema', at first only get initialized
minimially, and then, if necessary, upgrade to a full schema status at
runtime.  This yields a kind of object that becomes powerful on demand
(either at creation or at runtime). And while I still feel it's an
interesting idea, it would perhaps make most sense for a rather more
general-purpose object system. And I don't feel like the current
foundations I am using allow for accomplishing that in a good way.

And so I rolled that stuff back, "until further notice".

Oh, well, the new constraints can be named and may be inherited with an
option to redefine the path of any input/output variable.  For example,
the following constraint keeps a history of a given slot value (here in
the 'in slot) by writing to the ring-buffer contained in the 'out slot,
via mutation:

(ζ history# (in out)
   (:= out (rb/add out in) out)) ; rb refers to a ring-buffer

Now, to derive the constraint for a custom slot, one need only redefine
the paths (in, out or both):

(ζ ((in (>> 'x))
    (out (>> 'x-history)))
   (is-a history#))

Partial path redefinition is possible just as well, of course.  And
storing custom information is done via a 'sub slot:

(ζ () (sub (make-some-custom-data ...)) ...)

So, this here probably is as complicated as it needs to be.
 
*** Currently I am working on parameterized pointer variables. ***

I think I have a pretty good idea of what they are going to work out
like in the end.

(ζ (Q (>> * 'q))) 

Here (>> * 'q) is a path, * is a wild card, 'q is a slot of every schema
that matches the wild card in the current object.

One will then be able to define a method that uses Q in one of the
following ways:

(:= Q (+ p 2)) ; define the 'q slot of every matching schema to equal (+ p 2)
(:= p (apply #'+ (all Q))) ; other direction: define p as a function of the Q set
(:= P (+ Q 2)) ; one-to-one match, where both P and Q use wildcards; maybe

The wildcard matching will have a filtering and recursion depth
option. Multiple wild cards will be allowed to appear in a single path.

PS The long break did have some benefits. For one, it let me take a
   fresh look at KR, I guess. But generally I just want to thank people
   who are supporting me for sticking it through with the project over
   the few stale months : )

Yours,

  -- Dmitrii Korobeinikov
Reply to thread Export thread (mbox)