NewerPath... making "/" a generic pathing operator

At one point I wrote up a thought experiment about something called NewPath. Executive summary: I thought it might be more flexible if things like %foo/bar were actually a PATH! with a FILE! in its first slot and a WORD! in its second slot. Then when it was evaluated, it would produce the singular FILE! value %"foo/bar".

This made it seem like you could do interesting path compositions, with GROUP!s and such, and have it look like a file. @rgchris (rightly) complained that this took away some of the simplicity for those dealing in regular FILE!s or URLs.

NewerPath is built on a long-running pet idea of mine to change / from simply meaning "divide" to being expanded to a generic pathing operator. Just as a proof of concept...check this demo out (to actually try it, you have to say set/enfix quote / func ... because /: is not a legal SET-WORD! at the moment)

>> /: enfix func [#left #right] [
    as file! unspaced [left "/" right]

>> subdir: func [x] [
    as file! unspaced ["subdir-" x * 10]

>> (subdir 10) / %foo / (subdir 20) / %myfile.txt
== %subdir-100/foo/subdir-200/myfile.txt

The result is pretty cool. If it's a tight infix operator following the same rules as old dividing /, then you need the parenthesization, else it would be greedy and try "10 / %foo" and such. Though that was part of the Old NewPath proposal too, since you had to parenthesize to get code executed in paths.

But...if we were willing to take a little bit of a hit on pure compatibility with DIVIDE, it could be a left normal, right tight op.

>> /: enfix func [left #right] [
    as file! unspaced [left "/" right]

>> subdir 10 / %foo / subdir 20 / %myfile.txt
== %subdir-100/foo/subdir-200/myfile.txt

The left normality means you can avoid some amount of parenthesization (as long as it's one complete expression). The right tightness stops greedy infixing if it winds up with an opportunity for that while one of its arguments is gathering its arguments. It would change the behavior of / when mixed up with non-infix functions, while leaving pure infix "precedence" the same. Maybe too freaky, the but interesting to point out the parentheses could be avoided.

While it might seem a little weird to say that "picking" one integer out of another integer somehow means to "divide" them, it doesn't seem like the end of the world if 1/2 comes out as 0.5.

The bigger conceptual issue is what happens when people see a / b and can't trust that's mathematical division. Generally speaking the experiment of Rebol has a lot to do with allowing that rug to be pulled out from under you a bit, in order to expand your expressivity. And I do a lot more FILE! or URL! construction from parts than I do math in Rebol.

So I dunno. If your variables have meaningful names and your code is laid out contextually right, it shouldn't be much of a problem. I guess that's why I think it would be good to try it and find out.

I'll mention though, that this capability of FILE! is controversial, because it means that a decision must be made about whether %foo / 1 is #"f" or %foo/1...given that pathing and picking are unified (which I believe strongly has been a great idea).

My view is that it should be consistent across string types, and pick "foo" 1 has to be #"f" pretty much. If you have something that's an integer and you want to path it onto a FILE!, convert it to a file first. %foo / %1

Another relevant thing to think about is the meaning of BLOCK!. It seems very useful to say that the block be unspaced converted:

>> filename: "log"

>> number: 10

>> %some-dir / [filename "-" number %.txt]
== %some-dir/log-10.txt

But again, I think one runs into problems with just how varied the combinatorics get...with every type picking differently out of every other type, with no cohesion across superclasses.

Some thoughts (fuzzier than normal due to a head cold)... and I hope I haven't not completely missed the point.

This is creative and cool expressivity.

Though, the examples show path composition as file concatenation.

Ordinarily, in an expression, people might expect + or & or something as concatenation - can't remember if I've seen / as concatenation. So I'm asking myself, "are there other composition operations other than concatenation that point to / as the best operator?" (other than historical pathing) but my fuzzy head can't get me there straight off.

Of course + has the same issues you point out as /.

Then there is the use of / in file and url paths. Seems natural that the operator be /, but is it confusing? I'm not advocating + but by comparison perhaps it is less confusing visually when concatenating file paths with things.

So I accept that you're looking at a big picture design here but my head has locked on a bit concretely to file concatenation and I'm challenged to work through any other applicative areas.

My gut reaction is unease with this, seems like it will be more symbols to achieve a straight forward result. Also, I know files and urls have their string nature, but I also intuitively can think of them (block nature) where each path element is an atomic representation of something on disk - especially if I've done the work to validate that. In my mind: "is there an alternative, is there a wider enquiry?"

So yes, a block seems most useful to be converted unspaced, but as you point out this may be non-trivial with a mix of types. So I'm wondering if an operation based on pathing is too challenged by the complexity, whether the area is more properly the scope of a dialect and how do these questions relate to future types. That said, I note that even if one has a user function or built-in dialect, the questions stand because pathing may have a 80 for 20 application.

Daydreaming, perhaps invoking a conversion dialect with something enfix and a specified output type might be interesting:

url from [%some-dir/ filename "-" number %.txt]

Ok so evaluator wise maybe that's not so new now. To spice it up maybe pathing could pass through to a from or something else more generically appropriate for pathing for it's 80/20 implementation.

Ok I'm probably delirious - to bed..

1 Like

The advantage is that + doesn't imply adding a slash if needed. The current pathing operator accommodates for double-slashes, as well as adding one if not present. So if I were stuck with a raw concatenation operator, the odds of it trying to have "pathing intelligence" are slim.

(And I'd argue the semiotics of + meaning "concatenation" aren't really very solid... 10 + 20 isn't 1020. At least when you're making a path, the / has -some- semiotics.)

But indeed...merits of the idea do hinge 100% on the idea that we want path composition to concatenate files. Which has come into question. It was just an observation that if we keep that, and if we went with the notion of / as a generic pathing operator, that it would work. But if either of those two ideas are rejected, then it won't work.

It's a more standard idea, but I guess I'm interested in the idea of seeing if it's possible to use infix operations to "riff off" the idea of just seeing a FILE! there and being able to know you want to use infix to shift into a file mode.

But yeah, the competing demands on pathing vs. picking are certainly a little less ideal than it could be with the integers needing conversion... but it looks almost good... if you didn't have to actually say TO-FILE on the ID :-/

 topic: %newerpath-making-a-generic-pathing-operator
 id: 422
 d: read / topic / id

I like the idea that 2/3, 2/3/2018, 2/Mar/2018 are true paths.
But if 2/3 was a decimal 0.6666... then we are lost when writing 2/3/2018 :-/
Then we need a new type FRACTION!
so that fraction/integer gives a DATE!
Same way, we need 2/Mar be valid -- could be = 2/Mar/(current year)

1 Like

As with arbitrary WORD!s I think the idea of data bearing paths is that you would be quoting it... so you'd do '2/3/2008 or having it in dialects where you interpret it, data: [Foo: #bar 2/3/2008]

The concept of paths that don't necessarily have evaluative meaning isn't so different from blocks whose contents can't run under DO...

As another epicycle of the NewPath design saga, here's a more modest (yet still powerful) proposal:

Let MAKE FILE! take a PATH!, then interpret it creatively

>> dir: %home/projects/
>> num: 10

>> make file! '(dir)/subdir/["file-" num ".txt"]
== %home/projects/subdir/file-10.txt

Note how the path-interstitial "/" gets a magic de-duplication, and won't be added if it's already there. So it doesn't wind up being projects//subdir.

The idea of running UNSPACED-style logic when a path segment is a BLOCK! is an idea that has come up before, and seems common enough to be worth it. An added bonus could be that this interpretation could be extended to MAKE FILE! of a plain BLOCK!:

 >> make file! ["file-" num ".txt"]
 == %file-10.txt

And it shaves 7 characters off of as file! unspaced ["file-" num ".txt"]. As a sidenote, make file! (...) would arguably work "consistently" since that would just run an evaluation.

This could mean getting rid of the path picking out of file abnormality. Which would be good.

Coming back to this thread much later: I'll more explicitly agree with your point that being bound by pathing's "step A, step B, etc." chain of operation removes the ability to sort of have a "central mind" about what your transformation is going to be. You become chained to whatever the odd rules are at each step and reverse-engineering what you want, instead of just writing it. (It doesn't help that what a path step does seems to have been semi-random in the first place.)

My second suggestion I think pointed in the better direction, more of a "dialect" in terms of passing a quoted structure to that "central mind":

>> make file! '(dir)/subdir/["file-" num ".txt"]
== %home/projects/subdir/file-10.txt

The new curveball I'm throwing in circa 2019 is % as a generic quoting operator, and killing FILE! altogether.

>> x: %(dir)/subdir/["file-" num ".txt"]
== (dir)/subdir/["file-" num ".txt"]

>> type of x
== path!

>> file-ify x
== "home/projects/subdir/file-10.txt" // not a FILE!, because there is no FILE!

So this FILE-IFY or whatever could be fully userspace. Write and remix your own. Make it a small enough amount of code that if the basic implementation wasn't doing what you wanted for a particular case, you could just hack on it yourself.

A hard part of all this really is coming up with names. Rebol took a lot of the good ones, and here I'm afraid to use TO-FILE. Even if Rebol had never had a FILE! datatype, I might still be wary of it... because it makes it sound like it can't return TEXT! breaks the pattern of the TO-XXX functions. :frowning:

So maybe this is what encourages putting functionality under pathing or MAKE and TO vs. any real desire to leverage any infrastructure they have, because they don't really have that much "infrastructure". Just the name (or in pathing's case, the lack of a name!)