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

What inplace operator should we use for path concatenation? #2

Closed
davidanthoff opened this issue May 17, 2018 · 15 comments
Closed

What inplace operator should we use for path concatenation? #2

davidanthoff opened this issue May 17, 2018 · 15 comments

Comments

@davidanthoff
Copy link
Contributor

davidanthoff commented May 17, 2018

The join function currently is there, and I see no reason to change anything about it.

But it would be nice to also have an inplace operator that does the same trick. I'll list some candidates as separate comments, so that folks can like/dislike them individually. Any reasons, explanations, new suggestions etc. would also be most welcome!

We might also look around what other languages do about this.

@davidanthoff
Copy link
Contributor Author

One option is p1 * p2.

@davidanthoff
Copy link
Contributor Author

Another option is p1 / p2.

@davidanthoff
Copy link
Contributor Author

A third option is p1 || p2.

@davidanthoff
Copy link
Contributor Author

Here is my preference: I like * best, mainly because it also is used for string concatenation, so I think it will be easiest for folks to discover. / to me is too much of a pun. || reminds me of piping, not concatenation.

@oxinabox
Copy link
Contributor

oxinabox commented May 17, 2018

Paths are a Free Monoid, (as are strings).
Conventionally in math the operator for free monoids is that which is normally used for multiplication.
It isn't a great reason, but it has some standing I think.

Another reason is we will get some juxtaposition working,
I don't have FilePaths on this computer so testing with Regex,
It should still hold anyway

✔️ path literal then string literal will work:

julia> r"aas""bbbs" #*1
ERROR: MethodError: no method matching *(::Regex, ::String)

✅ path literal then variable will not work, but could be made to work

But could be made to work with a change to the path macro definition.

julia> b="bbs" 
"bbs"

julia> r"aas"b    #*2
ERROR: ArgumentError: unknown regex flag: b

✅ path literal then path literal will not work, but could be made to work

julia> r"aa"r"bb"
ERROR: ArgumentError: unknown regex flag: r

❌ string variable then path literal can't be made to work

julia> b
"bbs"

julia> br"aa"
ERROR: UndefVarError: @br_str not defined

❌ path variable then string literal can't be made to work

julia> a=r"aas" 
r"aas"

julia> a"bbs"   # *3
ERROR: UndefVarError: @a_str not defined

✔️ String literal then path variable will work

julia> br = r"bbs"
r"bbs"

julia> "aas"br
ERROR: MethodError: no method matching *(::String, ::Regex)

✔️ String literal then path literal will work

julia> "aas"r"bbs"
ERROR: MethodError: no method matching *(::String, ::Regex)

EDIT: A lot of this will not work in 1.0 as juxtraposition has been nerfed.

@rofinn
Copy link
Owner

rofinn commented May 17, 2018

My argument against just reusing * is that joining paths is a fundamentally different operation than string concatenation, so we should use a different operator to avoid confusion. Having used the Path type in my own projects it can be hard to predict what the output of an expression will be when mixing path variables with strings, and using * would just make that worse.

Operators for path join/append in other software:

@iamed2
Copy link
Contributor

iamed2 commented May 17, 2018

One argument against using * for path joining is that you might want to use it to append to the last element.

p"/foo/bar/baz" * ".txt" == p"/foo/bar/baz.exe"

@rofinn
Copy link
Owner

rofinn commented May 17, 2018

I'm also not sure if we want to be consistent with math conventions because different areas of mathematics use different symbols (e.g., cryptography uses (\Vert))

@rofinn
Copy link
Owner

rofinn commented Jan 27, 2019

Alright, I think it's been long enough that we should make a decision. Based on the comments and votes above I'm going to move forward with:

* as string concatentation

The * operator with an AbstractPath should be equivalent to converting to: calling string(p), applying the string * operator, and then reconstructing the path by calling Path(s).

e.g.)

p"/foo/bar/baz" * ".txt" == p"/foo/bar/baz.txt"
p"/foo/bar" * "baz" == p"/foo/barbaz"
p"/foo/bar/" * "baz" == p"/foo/bar/baz"

/ as path concatentation

This operator will be path specific and be equivalent to joinpath, as long as at least 1 argument is already an AbstractPath.

e.g.)

p"/foo/bar/baz" / ".txt" == p"/foo/bar/baz/.txt"
p"/foo/bar" / "baz" == p"/foo/bar/baz"
p"/foo/bar/" / "baz" == p"/foo/bar//baz"

NOTE: This is dependent on dropping AbstractString subtyping (#15, #22)

@iamed2
Copy link
Contributor

iamed2 commented Nov 6, 2019

Another option is // which I am surprised I didn't think about

@rofinn
Copy link
Owner

rofinn commented Nov 6, 2019

Syntactically that seems more confusing and the argument that we aren't doing division still holds because we also aren't creating a rational. I feel like it's fine for the operator to do different things in this context. * can mean concatenation or multiplication depending on the types as well.

@oxinabox
Copy link
Contributor

oxinabox commented Nov 7, 2019

I tried this in a few places and I found it uncomfortable.
Still it is now being used.
and I think even the combo ofg * for string-link concat and / for path-join

@rofinn
Copy link
Owner

rofinn commented Nov 7, 2019

I tried this in a few places and I found it uncomfortable.

Which thing? /? I have to admit that I've grown to like it because of how easy it is to accidentally write join instead of joinpath, so / feels very clear that we're doing joinpath and that we're using an AbstractPaths.

@oxinabox
Copy link
Contributor

oxinabox commented Nov 7, 2019

Yeah, / I might get used to it but it sure feels of with variables right now

Either way though
We should be overloading join though.
It's not even a pun.
It is for me one of the clearest signs that Path should not have been a string -- it is faking dispatch with an extra function

@rofinn
Copy link
Owner

rofinn commented Nov 7, 2019

We do overload join to do the correct thing for paths, but it's often unclear if variables are paths or strings from context. For example, does a third part function return a path when you pass in paths or does it just convert to a string and return the string.

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

No branches or pull requests

4 participants