Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Immutable Paths, of minimum length 2 #906

Closed
wants to merge 2 commits into from
Closed

Immutable Paths, of minimum length 2 #906

wants to merge 2 commits into from

Conversation

hostilefork
Copy link
Member

@hostilefork hostilefork commented Jan 6, 2019

This changes PATH! to no longer be an ANY-SERIES! type. This means it
cannot be operated on with series operations like APPEND, and it can't
be traversed to give new positions into paths with things like NEXT
or SKIP. However, other operations like LENGTH OF, PICK, and FOR-EACH
continue to work.

Besides no series modifiers, ANY-PATH! can't be mutated with POKE-ing.
This means that a path can be checked at the time of its creation for
properties which cannot be violated by future mutations.

The new rules are:

  • Paths must contain at least 2 elements. The minimum path is /,
    which is the path form of [_ _]...two blanks.

  • Paths may not directly contain other paths. This prevents various
    ambiguity problems like [a/b c] and [a b/c] both being possible
    interpretations of a/b/c. Indirect inclusion of other paths is
    legal, such as a/(b/c)/d

It is believed that this change eliminates harmful degrees of freedom,
without really sacrificing any behaviors people found that interesting.
Additionally, being able to promise paths are immutable open doors to
being able to create optimized representations of things like / or
/a, which could be packed into a single cell with no array node.

If one wishes to do surgery on path content, the way to do that is to
convert it to a BLOCK! or GROUP! and use series operations on that,
and then change it back to a PATH!.

(Note: Any series embedded in a path, e.g. the GROUP! in a/(b c d)/e,
is not subject to the immutability rule...and is subject to whatever
mutability state it had when it was inserted.)

This changes PATH! to no longer be an ANY-SERIES! type.  This means it
cannot be operated on with series operations like APPEND, and it can't
be traversed to give new positions into paths with things like NEXT
or SKIP.  However, other operations like LENGTH OF, PICK, and FOR-EACH
continue to work.

Because there's no way to change them, ANY-PATH! is also immutable.
This means that a path can be checked at the time of its creation for
properties which cannot be violated by future mutations.

The new rules are:

* Paths must contain at least 2 elements.  The minimum path is `/`,
  which is the path form of [_ _]...two blanks.

* Paths may not directly contain other paths.  This prevents various
  ambiguity problems like [a/b c] and [a b/c] both being possible
  interpretations of a/b/c.  Indirect inclusion of other paths is
  legal, such as `a/(b/c)/d`

It is believed that this change eliminates harmful degrees of freedom,
without really sacrificing any behaviors people found that interesting.
Additionally, being able to promise paths are immutable open doors to
being able to create optimized representations of things like `/` or
`/a`, which could be packed into a single cell with no array node.

If one wishes to do surgery on path content, the way to do that is to
convert it to a BLOCK! or GROUP! and use series operations on that,
and then change it back to a PATH!.

(Note: Any series embedded in a path, e.g. the GROUP! in `a/(b c d)/e`,
is not subject to the immutability rule...and is subject to whatever
mutability state it had when it was inserted.)
This commit does a rethinking of the definition of a REFINMENT! such
that /word is the parallel to what would be [_ word] as a block.  This
opens up the possibilities for greater expressions of paths in the
pattern `/foo/bar/...`

Similar to how the QUOTED! change generalized what were previously
dedicated types, this adds REFINEMENT! as a parse rule and some
compatibility checks.  Unlike LIT-WORD? and LIT-PATH? however, the
matching of the pattern for REFINEMENT? and the term may be worth
keeping to idiomatically identify this path subclass.

As a first take, this is more inefficient than a refinement, as it
actually does allocate 2-element arrays for each usage (which can't
fit in 2 cell spaces, as it must account for an end as well, so it
requires a full 4 cell-sized array allocation, in addition to a
series node).  This makes a refinement cost roughly the overhead of
6 additional value cells to the one cell it occupied previously.

Next step will be to adapt the "in-situ" escaping technique (which was
made to put higher quoting levels into cells directly) such that it
can represent this form of 2-element path at nearly no added cost,
while still appearing to be a PATH!.
@hostilefork
Copy link
Member Author

Merged with fixes:

fa6cd53

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant