Hey,

> OK. I see the "referent" concept is broader than I had thought. They are
> not just pointers, but (paraphrasing) expressions awaiting evaluation. The
> "referent pattern" is more or less the type of the expression, i.e. the
> type of whatever the expression evaluates to.

Yes. As I see it.



        Reference = Referent Pattern + Instruction Patterns + Referents
                * Referent Pattern = The most specific description possible of 
the structure of the referents of the reference.
                * Instruction Patterns = The result of streaming the referents 
through the instruction.
                * Referents = The objects pointed to be the reference. 
Accessing them is a dereference (a manifestation).

Why are references more than just pointers to referents? Kuppitz and I are 
realizing that ?all? database optimization can be understood as techniques to 
avoid dereferencing. If the reference can tell the VM what to expect from a 
dereference, then certain instructions can avoid dereferencing the reference. 

Page 17 of the mm-ADT spec has a summary table of the subsequent subsections 
that show how foreign keys, schemas, indices, denormalizations, views, 
pipelines, and aggregations are all just variations on this theme.

Now, what I realized today what that there are two types of “referent patterns."
        * The reference’s referent pattern describes what to expect (locally). 
// read-oriented
        * The database’s type pattern describes what is legal (globally).       
 // write-oriented
I didn’t have the second and I need it. Enter a type system. We need a way to 
extend the mm-ADT’s type system. Enter you.


> For example, in Haskell
> notation:
> 
>  sum [1,2,3] :: Int
> 
> Here, "sum [1,2,3]" is the reference. The referent is something which has
> yet to be determined (the number 6). We know that the referent's type is
> Int, and we can type-check the expression to be verify that it will produce
> an Int. Another example:
> 
>  fmap (\n -> "number " ++ show n) $ filter (> 1) [1,2,3] :: [String]
> 
> Here, "fmap ... [1,2,3]" is the reference, and the referent is a list of
> strings: ["number 2","number 3”].

Bingo. So there are three types of “right hand sides” to an instruction pattern.

[instruction pattern]->result pattern (a description of what too expect)
[instruction pattern]->result object  (the actual result to expect — 
memoization-style)
[instruction pattern]->bytecode       (a different computation that should be 
executed)

…where the first is the second given a specific enough pattern ;). That is, so 
the pattern  is so specific that its an explicit object. And the last is 
something new that I realized this weekend with respects to writing, that might 
not be necessary….


> Instruction patterns seem like additional "referents" to me, with the
> difference that they are applied to objects, and that they are composed of
> concrete instructions.

Yes. Though not “concrete” instructions, but instruction patterns. For 
instance, what is a database hash-index over the name-attribute?

*person{name:@string, age:@int /                          // referent pattern
  [has,name,eq,$x.@string]->*person{name:x, age:@int} }   // instruction pattern

The concrete instruction [has,name,eq,marko] will match the above instruction 
pattern and will return a reference to person objects whose name is now known 
and whose age is still just some integer.

> Instruction patterns seem like additional "referents" to me


I would argue that referent patterns are actually just instruction patterns as:

[value,name]->@string  // instruction pattern

is the same thing as

{name:@string} // referent pattern

…I don’t have an ultra-confident reason why references aren’t just instruction 
patterns, but its related to behavioral differences in reading/writing. More 
exploration is required.


> If a referent is nullary (has some type "a"), an
> instruction pattern seems unary (has some type "a->b", consuming an "a" and
> producing a "b"). But I need to grok more.

Sorta. The semantics of X->Y are:

        “Given a matching X-instruction executed on the reference’s referents, 
the result is Y."

If Y is sufficient to solve the computation, the VM avoided dereferencing… and 
this is database optimization in a nutshell.

Marko.

http://rredux.com




> 
> 
> On Sun, May 26, 2019 at 6:51 PM Marko Rodriguez <okramma...@gmail.com>
> wrote:
> 
>> Hello,
>> 
>>>> [db][get,’people’] // *{name:@string, age:!gt(20)&!lt(33)}
>>>> 
>>>> We have lost information about the “schema.” This is not good as
>>>> compile-time write validation is not possible.
>>>> 
>>> 
>>> So far, I am thinking: yeah, dealing with schema changes can be tricky.
>> 
>> This is not a “schema change” but a greater specification of what the
>> referents are. Again, a reference is defined by its referent pattern (and
>> instruction patterns). The referent pattern is a description of the current
>> instances (referents) while the “schema” is a description of what is legal
>> for all instances (referents). Without “schema,” I lose compile-time
>> validation.
>> 
>>> I then create a people-key on the db map that maintains a
>> person-reference.
>>>> 
>>> 
>>> OK. I think by people-key you mean the primary key for the person type,
>>> i.e. the vertex id. Correct me if I am wrong.
>> 
>> No. db.get(‘people’) is the "people table.” RDBMSs are modeled as a map
>> with the keys being the table names and the values being *{:} references to
>> maps (i.e. rows).
>> 
>>> I see this as a type plus a constraint. And... you won't be surprised to
>>> hear me say this... you express it with a select statement:
>>> 
>>>   youngishPeople := σ_{age <= 20 ∧ age >= 33}(people)
>> 
>> Well, type definitions like this won’t happen at runtime. The VM will just
>> be able to tell you if the range has been restricted. It won’t create new
>> types. But yea, referent patterns are (now) a type plus a constraint.
>> Before, they were just constraints and that is why I lost schema
>> information at runtime.
>> 
>> Take care,
>> Marko.
>> 
>> http://rredux.com
>> 
>> 

Reply via email to