In Racket, how do I get or change my working directory?
Asked Answered
D

2

9

What is Racket's equivalent for viewing and changing the working directory of a process like pwd and cd?

Derail answered 29/7, 2018 at 13:29 Comment(0)
D
12

Use current-directory.

Passing no arguments returns the current working directory. Passing a path changes the working directory to that path.

Here's an example for the REPL that prints the current directory, then changes to the parent directory:

> (current-directory)
#<path:/home/sage/>
> (current-directory (build-path (current-directory) ".."))
; now in /home
Derail answered 29/7, 2018 at 13:29 Comment(0)
D
2

Note that path is a type-object in racket. And because in Racket current-directory does not actually change the environment path but only changes the current-directory path value, if you do this:

> (current-directory "/somepath/thatdoesnt/exist/") ; now in /somepath/thatdoesnt/exist

Racket will not throw an error. You'll only get an error when you try to do something with the path object itself.

such as:

> (directory-list (current-directory)) ; directory-list: could not open directory ; path: /somepath/thatdoesnt/exist/ ; system error: No such file or directory; errno=2 ; [,bt for context]

Doorplate answered 24/7, 2019 at 20:26 Comment(6)
I wouldn't call that "lazy evaluation". In Python I can current_dir = "/bad/path" which doesn't error anything, but when I use it in os.listdir it now errors. Does that mean Python is lazily evaluated as well?Stockholm
the difference is that in Python os.listdir takes a string as it's input. your current_dir is a string. directory-list in Racket requires a path object. Racket's current-directory converts a string to path object... sort of. (path? (current-directory "/badpath")) will not evaluate (current-directory "/badpath") so it is #f. do (string->path "/badpath") to create a valid path object. But a path object will not evaluate to an actual path until it is evaluated in another function, like when directory-list occurs. In Python, os.chdir('/badpath') fails immediately, not lazily.Doorplate
> (current-directory "/badpath") ; now in /badpath does not actually change the environment path. it changes the current-directory path value. The message is misleading. it will only evaluate to an os path when it's used.Doorplate
I just saw the reply, so let me respond. 1) in Racket, there is no real difference in path objects and strings. They can both point to non-existing file. Python, too, has the same behavior. Try from pathlib import Path; p = Path('this-does-not-exist'). It doesn't error. 2) No, directory-list doesn't require only a path object. It also accepts a string. Most path functions in Racket can accept either strings or paths, where strings are effectively converted into paths first.Stockholm
3) (path? (current-directory "/badpath")) doesn't make much sense. (current-directory "/badpath") returns a void? value (it sets the current-directory parameter), so (path? (current...)) will always be #f.Stockholm
4) you are right that there's a difference between Racket and Python. os.chdir is at the OS-level. It issues a system call to change the directory in the system. In contrast, current-directory is at Racket level (so no system call) and is essentially just a variable, where various Racket functions like directory-list consult it to find what the current directory is. I understand why you might view that as "lazy evaluation". The checking is indeed postponed until a system call is actually needed. Still, this is not "lazy evaluation" which is used to describe behavior of function call.Stockholm

© 2022 - 2024 — McMap. All rights reserved.