Re: Get and set current directory Lassi Kortela 21 Jul 2019 14:56 UTC
>> (with-current-directory "/some/dir" >> (lambda () ...)) >> >> saves the OS's idea of the current directory, does a chdir() to the desired directory before the thunk and then a chdir() back to the old one afterwards. > I guess I’m missing the use case for this… Are you trying to design something that works only in single-threaded Schemes? In other words you are deliberately ignoring issues with concurrent uses of this construct because there’s no solution? I didn't think of it that way, but your conclusion is right. I'm not even quite sure what the appropriate use of per-thread OS working directories in C/C++ programs is. I guess it can work if one is very careful to be sure of which thread all code runs in (including library code). I haven't worked on many multi-threaded programs, and not any big ones, but what I've done is to have the same OS cwd on each thread and merge pathnames manually. For per-thread cwd's I'd do one of these: 1) The application programmer would have a per-thread variable or parameter containing the thread's base pathname. This variable would not affect the OS interface; the programmer would have to manually merge pathnames to the base path before passing them onto the OS procedures. 2) Have a per-thread file descriptor that has opened that thread's current directory. The file descriptor would be passed to Unix calls like openat() and unlinkat() to help resolve relative paths. Option 2 is nice in that we have support from the kernel, but it's not as portable. I'm not sure whether there's a Windows equivalent. And it would require an optional cwd argument in all the OS procedures (or the per-thread fd would be stored in a standardized parameter as you suggested, and the OS procedures would always get it from there without needing a separate argument). > What is the purpose of this construct? It sets up the current directory of the process (to affect the behavior of external, i.e. C and OS, code)? It implements the concept of “current directory” for Scheme code to use (for example to expand relative filenames)? Only one or both? Both. Most languages' OS APIs don't resolve relative pathnames themselves, they just pass them verbatim to the Unix syscalls so the kernel resolves them. So the with-current-directory construct would affect Unix syscalls, and thereby implicitly affect Scheme code by virtue of the fact that Scheme code would defer to the syscalls. The with-current-directory thing is provided because it's simple and convenient; I haven't met an implementation in any language that tries to do anything fancier than the chdir() and unwind-protect thing. So users know what it does and don't expect anything more. This is the first discussion I've been in where the idea of doing anything more complex has been brought up. I think this kind of thoroughness is a merit to the Scheme community and the Right Thing design approach.