import unix.*; import libc; tail?(str, tail) { if (size(str) < size(tail)) return false; else return slice(str, size(str) - size(tail)) == tail; } head?(str, head) { if (size(str) < size(head)) return false; else return slice(str, 0, size(head)) == head; } alias pathSeparator = '/'; absolutePath?(path) = head?(path, pathSeparator); all?(seq, predicate) { var res = true; var iter = iterator(seq); while (res and hasNext?(iter)) res = predicate(next(iter)); return res; } any?(seq, predicate) { var res = false; var iter = iterator(seq); while (not res and hasNext?(iter)) res = predicate(next(iter)); return res; } trimHead(seq, predicate) { var n = size(seq); if (n == 0) return slice(seq, 0); var i = 0; while (i < n and predicate(seq[i])) i += 1; return slice(seq, i); } trimTail(seq, predicate) { var n = size(seq); if (n == 0) return slice(seq, 0); while (n > 0 and predicate(seq[n-1])) n -= 1; return slice(seq, 0, n); } trim(seq, predicate) = trimHead(trimTail(seq, predicate), predicate); rootDirectory?(path) = not empty?(path) and all?(path, block (x) { return x == pathSeparator; }); appendPath(path1, ...paths) = appendPath(path1, appendPath(...paths)); overload appendPath(path1, path2) { if (empty?(path2)) return String(path1); else if (absolutePath?(path2)) return String(path2); else if (head?(path2, "." + [pathSeparator])) { var path3 = trimHead(slice(path2, 2), block (x) { return x == pathSeparator; }); return String(appendPath(path1, path3)); } else if (head?(path2, ".." + [pathSeparator])) { var path3 = trimHead(slice(path2, 3), block (x) { return x == pathSeparator; }); return String(appendPath(path1, path3)); } } ====== import io.directories.*; main() { println(appendPath("a","b")); }