File Paths in Racket

Here’s the translation of the Go code example to Racket, formatted in Markdown suitable for Hugo:

The filepath module in Racket provides functions to parse and construct file paths in a way that is portable between operating systems. For example, dir/file on Linux vs. dir\file on Windows.

#lang racket

(require racket/path)

(define (main)
  ; `build-path` should be used to construct paths in a
  ; portable way. It takes any number of arguments
  ; and constructs a hierarchical path from them.
  (define p (build-path "dir1" "dir2" "filename"))
  (printf "p: ~a\n" p)

  ; You should always use `build-path` instead of
  ; concatenating `/`s or `\`s manually. In addition
  ; to providing portability, `build-path` will also
  ; normalize paths by removing superfluous separators
  ; and directory changes.
  (printf "~a\n" (build-path "dir1//" "filename"))
  (printf "~a\n" (build-path "dir1/../dir1" "filename"))

  ; `path-dirname` and `path-basename` can be used to split a path to the
  ; directory and the file. Alternatively, `split-path` will
  ; return both in the same call.
  (printf "Dir(p): ~a\n" (path-dirname p))
  (printf "Base(p): ~a\n" (path-basename p))

  ; We can check whether a path is absolute.
  (printf "~a\n" (absolute-path? "dir/file"))
  (printf "~a\n" (absolute-path? "/dir/file"))

  (define filename "config.json")

  ; Some file names have extensions following a dot. We
  ; can split the extension out of such names with `path-get-extension`.
  (define ext (path-get-extension filename))
  (printf "~a\n" ext)

  ; To find the file's name with the extension removed,
  ; use `path-replace-extension`.
  (printf "~a\n" (path-replace-extension filename #""))

  ; `find-relative-path` finds a relative path between a base and a
  ; target. It returns #f if the target cannot
  ; be made relative to base.
  (define rel (find-relative-path "a/b" "a/b/t/file"))
  (when rel (printf "~a\n" rel))

  (set! rel (find-relative-path "a/b" "a/c/t/file"))
  (when rel (printf "~a\n" rel)))

(main)

To run the program, save it as file-paths.rkt and use racket:

$ racket file-paths.rkt
p: dir1/dir2/filename
dir1/filename
dir1/filename
Dir(p): dir1/dir2
Base(p): filename
#f
#t
#".json"
config
t/file
../c/t/file

In Racket, we use the racket/path module which provides similar functionality to Go’s filepath package. The build-path function is used instead of Join, path-dirname and path-basename replace Dir and Base, and find-relative-path is used instead of Rel.

Note that Racket’s path functions often return path objects, which are automatically converted to strings when printed. The behavior of these functions may vary slightly from Go’s equivalents, but they serve similar purposes in handling file paths across different operating systems.