scryer-prolog icon indicating copy to clipboard operation
scryer-prolog copied to clipboard

Add absolute_file_name/2

Open aarroyoc opened this issue 4 years ago • 11 comments

Adds the predicate absolute_file_name/2.

It takes a local path and returns an absolute path. Works for both existing and non-existing files. If you pass an absolute path, it returns the same path.

?- use_module(library(os)).
   true.
?- absolute_file_name("README.md", X).
   X = "/home/aarroyoc/dev/ ...".
?- absolute_file_name("README.md", X);true.
   X = "/home/aarroyoc/dev/ ..."
   X = "/home/aarroyoc/dev/scryer-prolog/README.md"
;  ...
?- absolute_file_name("README.m", X);true.
   X = "/home/aarroyoc/dev/ ..."
   X = "/home/aarroyoc/dev/scryer-prolog/README.m"
;  ...
?- absolute_file_name("../README.m", X);true.
   X = "/home/aarroyoc/dev/ ..."
   X = "/home/aarroyoc/dev/scryer-prolog/../README.m"
;  ...
?- absolute_file_name("/home/README.m", X);true.
   X = "/home/README.m"
;  ...

aarroyoc avatar Oct 29 '21 16:10 aarroyoc

This version doesn't expand environment variables. E.g.

?- absolute_file_name("$HOME/logtalk", X), writeq(X), nl.
"/Users/pmoura/scryer-prolog/$HOME/logtalk"
   X = "/Users/pmoura/scrye ...".

Do you think that you could add support for expanding environment variables? Is that something where Rust native libraries can do the actual work? Possibly with a absolute_file_name/3 that would take a list of options, including a boolean option for performing that expansion?

pmoura avatar Oct 29 '21 17:10 pmoura

Intermingling this functionality with expansion of environment variables is not a good idea, please see https://github.com/infradig/trealla/issues/86#issuecomment-721979426 for arising issues.

triska avatar Oct 29 '21 20:10 triska

@aarroyoc: Does path_canonical/2 from library(files) work for you?

https://github.com/mthom/scryer-prolog/blob/ca62e54652ace8374225e9f43f28aac508819255/src/lib/files.pl#L140

triska avatar Oct 29 '21 20:10 triska

Intermingling this functionality with expansion of environment variables is not a good idea, please see infradig/trealla#86 (comment) for arising issues.

In that thread, you only criticize the idea without actually presenting any arguments. What's your suggestion then for expanding paths containing environment variables? The suggestion I made above makes it depending on a boolean option, a solution that's common to several Prolog systems (including Trealla). This solution works well in practice. Currently, for Logtalk, I'm using the ugly workaround listed at https://github.com/mthom/scryer-prolog/discussions/1041#discussioncomment-1483975 But, as I remarked there, this is core functionality that should be available either as a built-in predicate or as core library predicate.

pmoura avatar Oct 29 '21 20:10 pmoura

@triska: for my use case I think path_canonical/2 should work because all the files that are going to use already exist. I didn't look at it because I didn't know that predicate existed TBH and I checked that SICStus, SWI and Trealla have absolute_file_name/2 (which will also work on non-existing files).

aarroyoc avatar Oct 29 '21 20:10 aarroyoc

@triska: for my use case I think path_canonical/2 should work because all the files that are going to use already exist. I didn't look at it because I didn't know that predicate existed TBH and I checked that SICStus, SWI and Trealla have absolute_file_name/2 (which will also work on non-existing files).

That's indeed a key distinction. Applications often need to expand paths for non-existing files. A simple example opening a stream for writing to a new file.

?- use_module(library(files)).
   true.
?- path_canonical("/Users/pmoura/some_new_file", Path).
false.

pmoura avatar Oct 29 '21 20:10 pmoura

I suggest to use the existing functionality if it suffices for your use case. In case you need to create for example "/Users/pmoura/some_new_file", simply specify that path (there is no reason for path_canonical/2 in this example).

In general, predicates relating to files and directories are a good fit for library(files).

triska avatar Oct 29 '21 20:10 triska

In case environment variables are needed, I suggest getenv/2 from library(os), together with path_segments/2 from library(files).

triska avatar Oct 29 '21 20:10 triska

I suggest to use the existing functionality if it suffices for your use case. In case you need to create for example "/Users/pmoura/some_new_file", simply specify that path (there is no reason for path_canonical/2 in this example).

It doesn't suffice in general. That's why I'm using the workaround I linked in my previous reply.

In general, predicates relating to files and directories are a good fit for library(files).

Sure.

pmoura avatar Oct 29 '21 20:10 pmoura

In case environment variables are needed, I suggest getenv/2 from library(os), together with path_segments/2 from library(files).

https://github.com/mthom/scryer-prolog/discussions/1041#discussioncomment-1483975

pmoura avatar Oct 29 '21 20:10 pmoura

Btw, the path_canonical/2 conflates expanding a path with checking if the expanded path exists. This should be separated functionality as these are orthogonal. Adding absolute_file_name/2-3 predicates fixes it as we already have file_exists/1 and directory_exists/1 predicates.

pmoura avatar Oct 29 '21 20:10 pmoura