I noticed that in my new Dogelog Player the absolute_file_name/2
predicate might either return one of the two:
/* WSL */
?- absolute_file_name('baz.p', X).
X = '/mnt/c/foo/bar/baz.p'
/* Windows 10 */
?- absolute_file_name('baz.p', X).
X = 'C:\\foo\\bar\\baz.p'
So what to do? Normalize it and always use '/' and eliminate '\\' ?
This is what I did for formerly Jekejeke Prolog.
How do everything 100% in Prolog?
Here is a use case for last_sub_atom/5. Its useful to make an OS polyglott Prolog system, at least polyglott among Unix, Windows and Mac. You
can get rid of Logtalks internal_os_path/2, which I think is a little
design flaw in my old Prolog system, which my new Prolog system tries
to avoid. One can do the following like here, maybe there are also other agorithms based on last_sub_atom/5, but this is easiest to understand:
sys_file_parent(Path, Dir) :-
(last_sub_atom(Path, Pos1, _, _, '/') -> true; Pos1 = -1),
(last_sub_atom(Path, Pos2, _, _, '\\') -> true; Pos2 = -1),
Pos is max(Pos1, Pos2), Pos \== -1, !,
Pos3 is Pos+1,
sub_atom(Path, 0, Pos3, _, Dir).
sys_file_parent(_, '').
sys_file_name(Path, Name) :-
(last_sub_atom(Path, Pos1, _, _, '/') -> true; Pos1 = -1),
(last_sub_atom(Path, Pos2, _, _, '\\') -> true; Pos2 = -1),
Pos is max(Pos1, Pos2), Pos \== -1, !,
Pos3 is Pos+1,
atom_length(Path, Len),
Len2 is Len-Pos3,
sub_atom(Path, Pos3, Len2, _, Name).
sys_file_name(Path, Path).
Maybe regex could do the same. But can regex search backwards?
You would need a kind of greedy regex pattern, that nevertheless
has an alternative in it. And a regex library is more heavier, than some
last_sub_atom/5 which is still relative lightweight to provide, only
a variant of sub_atom/5.
Here comes last_sub_atom/5 to the rescue. The proposal is simple.
sub_atom/5 search forward, last_sub_atom/5 searches backward:
Here from ISO core standard:
?- sub_atom('baaab', X, Y, Z, 'aa').
X = 1, Y = 2, Z = 2;
X = 2, Y = 2, Z = 1;
fail.
?- sub_atom('abracadabra', X, Y, Z, 'abra').
X = 0, Y = 4, Z = 7;
X = 7, Y = 4, Z = 0.
And here the analogue searching backward:
?- last_sub_atom('baaab', X, Y, Z, 'aa').
X = 2, Y = 2, Z = 1;
X = 1, Y = 2, Z = 2;
fail.
?- last_sub_atom('abracadabra', X, Y, Z, 'abra').
X = 7, Y = 4, Z = 0;
X = 0, Y = 4, Z = 7.
I introduced this some years ago in formerly Jekejeke Prolog.
And since this week its also available in Dogelog Player.
Mostowski Collapse schrieb am Dienstag, 24. Mai 2022 um 12:19:25 UTC+2:
I noticed that in my new Dogelog Player the absolute_file_name/2
predicate might either return one of the two:
/* WSL */
?- absolute_file_name('baz.p', X).
X = '/mnt/c/foo/bar/baz.p'
/* Windows 10 */
?- absolute_file_name('baz.p', X).
X = 'C:\\foo\\bar\\baz.p'
So what to do? Normalize it and always use '/' and eliminate '\\' ?
This is what I did for formerly Jekejeke Prolog.
How do everything 100% in Prolog?
Here are some example runs:
?- sys_file_parent('/mnt/c/foo/bar/baz.p', X).
X = '/mnt/c/foo/bar/'.
?- sys_file_name('C:/foo/bar/baz.p', X).
X = 'baz.p'.
?- sys_file_parent('C:\\foo\\bar\\baz.p', X).
X = 'C:\\foo\\bar\\'.
?- sys_file_name('C:\\foo\\bar\\baz.p', X).
X = 'baz.p'.
Its not the same as decompose_file_name/3 from Logtalk,
which is possibly also not OS polyglott. Its not the same
since it leaves the directory delemiter, either '/' or '\\'
at the end of the parent intact. So the reverse function
of this decomposition is simply atom_concat/3:
?- atom_concat('/mnt/c/foo/bar/', 'baz.p', X).
X = '/mnt/c/foo/bar/baz.p'.
?- atom_concat('C:\\foo\\bar\\', 'baz.p', X).
X = 'C:\\foo\\bar\\baz.p'.
Mostowski Collapse schrieb:
Here is a use case for last_sub_atom/5. Its useful to make an OS
polyglott
Prolog system, at least polyglott among Unix, Windows and Mac. You
can get rid of Logtalks internal_os_path/2, which I think is a little
design flaw in my old Prolog system, which my new Prolog system tries
to avoid. One can do the following like here, maybe there are also other
agorithms based on last_sub_atom/5, but this is easiest to understand:
sys_file_parent(Path, Dir) :-
(last_sub_atom(Path, Pos1, _, _, '/') -> true; Pos1 = -1),
(last_sub_atom(Path, Pos2, _, _, '\\') -> true; Pos2 = -1),
Pos is max(Pos1, Pos2), Pos \== -1, !,
Pos3 is Pos+1,
sub_atom(Path, 0, Pos3, _, Dir).
sys_file_parent(_, '').
sys_file_name(Path, Name) :-
(last_sub_atom(Path, Pos1, _, _, '/') -> true; Pos1 = -1),
(last_sub_atom(Path, Pos2, _, _, '\\') -> true; Pos2 = -1),
Pos is max(Pos1, Pos2), Pos \== -1, !,
Pos3 is Pos+1,
atom_length(Path, Len),
Len2 is Len-Pos3,
sub_atom(Path, Pos3, Len2, _, Name).
sys_file_name(Path, Path).
Maybe regex could do the same. But can regex search backwards?
You would need a kind of greedy regex pattern, that nevertheless
has an alternative in it. And a regex library is more heavier, than some
last_sub_atom/5 which is still relative lightweight to provide, only
a variant of sub_atom/5.
Hello,
Why you didn't decide to use more classic dirname and basename? Meaning would've been immediately obvious for any experienced programmer.
Best Regards,
Alex
On 5/24/22 12:43, Mostowski Collapse wrote:
Here are some example runs:
?- sys_file_parent('/mnt/c/foo/bar/baz.p', X).
X = '/mnt/c/foo/bar/'.
?- sys_file_name('C:/foo/bar/baz.p', X).
X = 'baz.p'.
?- sys_file_parent('C:\\foo\\bar\\baz.p', X).
X = 'C:\\foo\\bar\\'.
?- sys_file_name('C:\\foo\\bar\\baz.p', X).
X = 'baz.p'.
Its not the same as decompose_file_name/3 from Logtalk,
which is possibly also not OS polyglott. Its not the same
since it leaves the directory delemiter, either '/' or '\\'
at the end of the parent intact. So the reverse function
of this decomposition is simply atom_concat/3:
?- atom_concat('/mnt/c/foo/bar/', 'baz.p', X).
X = '/mnt/c/foo/bar/baz.p'.
?- atom_concat('C:\\foo\\bar\\', 'baz.p', X).
X = 'C:\\foo\\bar\\baz.p'.
Mostowski Collapse schrieb:
Here is a use case for last_sub_atom/5. Its useful to make an OS
polyglott
Prolog system, at least polyglott among Unix, Windows and Mac. You
can get rid of Logtalks internal_os_path/2, which I think is a little
design flaw in my old Prolog system, which my new Prolog system tries
to avoid. One can do the following like here, maybe there are also other >>> agorithms based on last_sub_atom/5, but this is easiest to understand:
sys_file_parent(Path, Dir) :-
(last_sub_atom(Path, Pos1, _, _, '/') -> true; Pos1 = -1),
(last_sub_atom(Path, Pos2, _, _, '\\') -> true; Pos2 = -1),
Pos is max(Pos1, Pos2), Pos \== -1, !,
Pos3 is Pos+1,
sub_atom(Path, 0, Pos3, _, Dir).
sys_file_parent(_, '').
sys_file_name(Path, Name) :-
(last_sub_atom(Path, Pos1, _, _, '/') -> true; Pos1 = -1),
(last_sub_atom(Path, Pos2, _, _, '\\') -> true; Pos2 = -1),
Pos is max(Pos1, Pos2), Pos \== -1, !,
Pos3 is Pos+1,
atom_length(Path, Len),
Len2 is Len-Pos3,
sub_atom(Path, Pos3, Len2, _, Name).
sys_file_name(Path, Path).
Maybe regex could do the same. But can regex search backwards?
You would need a kind of greedy regex pattern, that nevertheless
has an alternative in it. And a regex library is more heavier, than some >>>
last_sub_atom/5 which is still relative lightweight to provide, only
a variant of sub_atom/5.
Look-ahead might not be a bad idea?
Question of the day:
Look-ahead might not be a bad idea?
Rather an pretty bad idea without any benefit, since
the intended use case of non-det last_sub_atom/5, is
det lastIndexOf(_), namely like here, slightly optimized
version now with only one clause:
sys_file_name(Path, Name) :-
atom_length(Path, Len),
(last_sub_atom(Path, _, _, Pos1, '/') -> true; Pos1 = Len),
(last_sub_atom(Path, _, _, Pos2, '\\') -> true; Pos2 = Len),
Pos is min(Pos1, Pos2),
sub_atom(Path, _, Pos, 0, Name).
So there is a (->)/2, which cuts away last_sub_atom/5. So if
you do some extra work in last_sub_atom/5, you will:
- Not eliminate the choice point. For example if the file
name is "foo/bar/baz.p", the look ahead will find another
“/”, and you will get a choice point.
- Only generate overhead. Since you will internally search
the first “/” from left, and then the second “/” from left.
The only thing that removes the choice point is the
local cut in (->)/2. And one way to avoid some extra work
is to not have look-ahead.
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 491 |
Nodes: | 16 (3 / 13) |
Uptime: | 147:32:58 |
Calls: | 9,695 |
Calls today: | 5 |
Files: | 13,732 |
Messages: | 6,178,671 |