---
title: "Standard Library: Strings, Display, and I/O"
output: arl::arl_html_vignette
pkgdown:
  as_is: true
vignette: >
  %\VignetteIndexEntry{Standard Library: Strings, Display, and I/O}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

<!-- AUTO-GENERATED from inst/arl/ source files. Do not edit manually. -->
<!-- Regenerate with: make lang-docs -->

```{r setup, include = FALSE}
knitr::opts_chunk$set(collapse = TRUE, comment = "#>")
arl::register_knitr_engine()
```

*Examples on this page may reference functions from other stdlib modules
without showing explicit `(import ...)` statements. In the REPL or your
own code, you will need to import non-prelude modules before using their
exports — see [Importing modules](lang-reference.html#importing-modules).*


## String Operations {#section-string-operations}

Core string manipulation functions: joining, splitting, searching,
replacing, and accessing characters. Most search/replace functions
default to fixed (literal) matching; pass `:fixed #f` for regex.

### string-join {#string-join}

Join strings with separator.

**Signature:** `(string-join x [sep ""])`

**Parameters:**
- **`x`** — A list of strings to join.
- **`sep`** — Separator inserted between elements (default "").

**Examples:**
```{arl}
(string-join (list "a" "b" "c") "-")  ; => "a-b-c"
(string-join (list "x" "y" "z"))      ; => "xyz"
(string-join (list "hello" "world") " ")  ; => "hello world"
```

```{arl, include=FALSE}
(assert-equal "a-b-c" (string-join (list "a" "b" "c") "-"))
(assert-equal "xyz" (string-join (list "x" "y" "z")))
(assert-equal "hello world" (string-join (list "hello" "world") " "))
```

**See also:** [string-split](#string-split), [string-format](#string-format)

---

### string-split {#string-split}

Split string on separator.

**Signature:** `(string-split x [sep ""])`

**Parameters:**
- **`x`** — The string to split.
- **`sep`** — Separator to split on (default ""), splitting into characters.

**Examples:**
```{arl}
(string-split "a-b-c" "-")  ; => ("a" "b" "c")
(string-split "hello" "")   ; => ("h" "e" "l" "l" "o")
```

```{arl, include=FALSE}
(assert-equal (list "a" "b" "c") (string-split "a-b-c" "-"))
(assert-equal (list "h" "e" "l" "l" "o") (string-split "hello" ""))
```

**See also:** [string-join](#string-join)

---

### trim {#trim}

Trim leading and trailing whitespace.

**Signature:** `(trim str)`

**Parameters:**
- **`str`** — The string to trim.

**Examples:**
```{arl}
(trim "  hello  ")  ; => "hello"
(trim "no spaces")  ; => "no spaces"
```

```{arl, include=FALSE}
(assert-equal "hello" (trim "  hello  "))
(assert-equal "no spaces" (trim "no spaces"))
```

---

### string-format {#string-format}

Format string with sprintf.

**Signature:** `(string-format fmt args...)`

**Parameters:**
- **`fmt`** — A sprintf-style format string.
- **`args`** — Values to substitute into the format placeholders.

**Examples:**
```{arl}
(string-format "Hello, %s!" "world")   ; => "Hello, world!"
(string-format "%d + %d = %d" 1 2 3)   ; => "1 + 2 = 3"
(string-format "%.2f" 3.14159)          ; => "3.14"
```

```{arl, include=FALSE}
(assert-equal "Hello, world!" (string-format "Hello, %s!" "world"))
(assert-equal "1 + 2 = 3" (string-format "%d + %d = %d" 1 2 3))
(assert-equal "3.14" (string-format "%.2f" 3.14159))
```

**See also:** [string-concat](#string-concat)

---

### string-contains? {#string-contains-p}

Check pattern in string (fixed).

**Signature:** `(string-contains? str pattern [fixed #t])`

**Parameters:**
- **`str`** — The string to search in.
- **`pattern`** — The pattern to search for.
- **`fixed`** — If #t (default), match literally; if #f, treat as regex.

**Examples:**
```{arl}
(string-contains? "hello world" "world")       ; => #t
(string-contains? "hello world" "xyz")          ; => #f
(string-contains? "hello world" "o.*d" :fixed #f)  ; => #t
```

```{arl, include=FALSE}
(assert-true (string-contains? "hello world" "world"))
(assert-false (string-contains? "hello world" "xyz"))
(assert-true (string-contains? "hello world" "o.*d" :fixed #f))
```

**See also:** [string-match?](#string-match-p), [string-find](#string-find)

---

### string-match? {#string-match-p}

Check pattern in string (regex).

**Signature:** `(string-match? str pattern [fixed #f])`

**Parameters:**
- **`str`** — The string to search in.
- **`pattern`** — The pattern to search for.
- **`fixed`** — If #f (default), treat as regex; if #t, match literally.

**Examples:**
```{arl}
(string-match? "hello" "^h.*o$" :fixed #f)  ; => #t
(string-match? "hello" "xyz" :fixed #f)      ; => #f
(string-match? "hello" "hello" :fixed #t)     ; => #t
```

```{arl, include=FALSE}
(assert-true (string-match? "hello" "^h.*o$" :fixed #f))
(assert-false (string-match? "hello" "xyz" :fixed #f))
(assert-true (string-match? "hello" "hello" :fixed #t))
```

**See also:** [string-contains?](#string-contains-p), [string-find](#string-find)

---

### string-find {#string-find}

Find pattern index or #nil.

**Signature:** `(string-find str pattern [fixed #t])`

**Parameters:**
- **`str`** — The string to search in.
- **`pattern`** — The pattern to find.
- **`fixed`** — If #t (default), match literally; if #f, treat as regex.

**Examples:**
```{arl}
(string-find "hello world" "world")  ; => 6
(string-find "hello world" "xyz")    ; => #nil
(string-find "hello" "l")            ; => 2
```

```{arl, include=FALSE}
(assert-equal 6 (string-find "hello world" "world"))
(assert-equal #nil (string-find "hello world" "xyz"))
(assert-equal 2 (string-find "hello" "l"))
```

**See also:** [string-contains?](#string-contains-p), [string-match?](#string-match-p)

---

### string-replace {#string-replace}

Replace first match. Default is literal (fixed); pass :fixed #f for regex.

**Signature:** `(string-replace str pattern replacement [fixed #t])`

**Parameters:**
- **`str`** — The string to modify.
- **`pattern`** — The pattern to match.
- **`replacement`** — The replacement string.
- **`fixed`** — If #t (default), match literally; if #f, treat as regex.

**Examples:**
```{arl}
(string-replace "hello world" "world" "there")    ; => "hello there"
(string-replace "aaa" "a" "b")                     ; => "baa"
```

```{arl, include=FALSE}
(assert-equal "hello there" (string-replace "hello world" "world" "there"))
(assert-equal "baa" (string-replace "aaa" "a" "b"))
```

**See also:** [string-replace-all](#string-replace-all)

---

### string-replace-all {#string-replace-all}

Replace all matches. Default is literal (fixed); pass :fixed #f for regex.

**Signature:** `(string-replace-all str pattern replacement [fixed #t])`

**Parameters:**
- **`str`** — The string to modify.
- **`pattern`** — The pattern to match.
- **`replacement`** — The replacement string.
- **`fixed`** — If #t (default), match literally; if #f, treat as regex.

**Examples:**
```{arl}
(string-replace-all "aaa" "a" "b")   ; => "bbb"
(string-replace-all "hello world world" "world" "there")  ; => "hello there there"
```

```{arl, include=FALSE}
(assert-equal "bbb" (string-replace-all "aaa" "a" "b"))
(assert-equal "hello there there" (string-replace-all "hello world world" "world" "there"))
```

**See also:** [string-replace](#string-replace)

---

### string-append {#string-append}

Concatenate strings together.

**Signature:** `(string-append args...)`

**Parameters:**
- **`args`** — Zero or more strings to concatenate.

**Examples:**
```{arl}
(string-append "hello" " " "world")  ; => "hello world"
(string-append "a" "b" "c")          ; => "abc"
(string-append)                       ; => ""
```

```{arl, include=FALSE}
(assert-equal "hello world" (string-append "hello" " " "world"))
(assert-equal "abc" (string-append "a" "b" "c"))
(assert-equal "" (string-append))
```

**See also:** [string-concat](#string-concat), [string-join](#string-join)

---

### ->string {#to-string}

Convert value to string representation.

**Signature:** `(->string x)`

**Parameters:**
- **`x`** — The value to convert to a string.

**Examples:**
```{arl}
(->string 42)     ; => "42"
(->string #t)     ; => "TRUE"
(->string 3.14)   ; => "3.14"
```

```{arl, include=FALSE}
(assert-equal "42" (->string 42))
(assert-equal "TRUE" (->string #t))
(assert-equal "3.14" (->string 3.14))
```

---

### char-at {#char-at}

Get character at index (0-based).

**Signature:** `(char-at str index)`

**Parameters:**
- **`str`** — The string to index into.
- **`index`** — Zero-based character position.

**Examples:**
```{arl}
(char-at "hello" 0)  ; => "h"
(char-at "hello" 4)  ; => "o"
```

```{arl, include=FALSE}
(assert-equal "h" (char-at "hello" 0))
(assert-equal "o" (char-at "hello" 4))
```

**See also:** [string-ref](#string-ref), [string-slice](#string-slice)

---

### string-ref {#string-ref}

Scheme-style character accessor (alias for char-at).

**Signature:** `(string-ref str index)`

**Parameters:**
- **`str`** — The string to index into.
- **`index`** — Zero-based character position.

**Examples:**
```{arl}
(string-ref "hello" 0)    ; => "h"
(string-ref "hello" 4)    ; => "o"
```

```{arl, include=FALSE}
(assert-equal "h" (string-ref "hello" 0))
(assert-equal "o" (string-ref "hello" 4))
```

**See also:** [char-at](#char-at)

---

### string-slice {#string-slice}

Extract substring from start (inclusive) to end (exclusive), 0-based.

**Signature:** `(string-slice str start end)`

**Parameters:**
- **`str`** — The string to slice.
- **`start`** — Zero-based start index (inclusive).
- **`end`** — Zero-based end index (exclusive).

**Examples:**
```{arl}
(string-slice "hello" 1 4)  ; => "ell"
(string-slice "hello" 0 5)  ; => "hello"
(string-slice "hello" 2 2)  ; => ""
```

```{arl, include=FALSE}
(assert-equal "ell" (string-slice "hello" 1 4))
(assert-equal "hello" (string-slice "hello" 0 5))
(assert-equal "" (string-slice "hello" 2 2))
```

**See also:** [char-at](#char-at)

---

### string-length {#string-length}

Return length of string.

**Signature:** `(string-length str)`

**Parameters:**
- **`str`** — The string to measure.

**Examples:**
```{arl}
(string-length "hello")  ; => 5
(string-length "")       ; => 0
```

```{arl, include=FALSE}
(assert-equal 5 (string-length "hello"))
(assert-equal 0 (string-length ""))
```

---

## String Case {#section-string-case}

Functions for converting string case.

### string-upcase {#string-upcase}

Convert string to uppercase.

**Signature:** `(string-upcase str)`

**Parameters:**
- **`str`** — The string to convert.

**Examples:**
```{arl}
(string-upcase "hello")  ; => "HELLO"
(string-upcase "Hello World")  ; => "HELLO WORLD"
```

```{arl, include=FALSE}
(assert-equal "HELLO" (string-upcase "hello"))
(assert-equal "HELLO WORLD" (string-upcase "Hello World"))
```

**See also:** [string-downcase](#string-downcase), [string-titlecase](#string-titlecase)

---

### string-downcase {#string-downcase}

Convert string to lowercase.

**Signature:** `(string-downcase str)`

**Parameters:**
- **`str`** — The string to convert.

**Examples:**
```{arl}
(string-downcase "HELLO")  ; => "hello"
(string-downcase "Hello World")  ; => "hello world"
```

```{arl, include=FALSE}
(assert-equal "hello" (string-downcase "HELLO"))
(assert-equal "hello world" (string-downcase "Hello World"))
```

**See also:** [string-upcase](#string-upcase), [string-titlecase](#string-titlecase)

---

### string-titlecase {#string-titlecase}

Convert string to title case (capitalize first letter of each word).

**Signature:** `(string-titlecase str)`

**Parameters:**
- **`str`** — The string to convert.

**Examples:**
```{arl}
(string-titlecase "hello world")  ; => "Hello World"
(string-titlecase "HELLO WORLD")  ; => "Hello World"
```

```{arl, include=FALSE}
(assert-equal "Hello World" (string-titlecase "hello world"))
(assert-equal "Hello World" (string-titlecase "HELLO WORLD"))
```

**See also:** [string-upcase](#string-upcase), [string-downcase](#string-downcase)

---

## String Comparison {#section-string-comparison}

Lexicographic comparison functions for strings.

### string<? {#string-lt-p}

Lexicographic less-than comparison.

**Signature:** `(string<? a b)`

**Parameters:**
- **`a`** — First string.
- **`b`** — Second string.

**Examples:**
```{arl}
(string<? "abc" "def")  ; => #t
(string<? "def" "abc")  ; => #f
(string<? "abc" "abc")  ; => #f
```

```{arl, include=FALSE}
(assert-true (string<? "abc" "def"))
(assert-false (string<? "def" "abc"))
(assert-false (string<? "abc" "abc"))
```

---

### string>? {#string-gt-p}

Lexicographic greater-than comparison.

**Signature:** `(string>? a b)`

**Parameters:**
- **`a`** — First string.
- **`b`** — Second string.

**Examples:**
```{arl}
(string>? "def" "abc")  ; => #t
(string>? "abc" "def")  ; => #f
(string>? "abc" "abc")  ; => #f
```

```{arl, include=FALSE}
(assert-true (string>? "def" "abc"))
(assert-false (string>? "abc" "def"))
(assert-false (string>? "abc" "abc"))
```

---

### string=? {#string-eq-p}

String equality comparison.

**Signature:** `(string=? a b)`

**Parameters:**
- **`a`** — First string.
- **`b`** — Second string.

**Examples:**
```{arl}
(string=? "hello" "hello")  ; => #t
(string=? "hello" "world")  ; => #f
```

```{arl, include=FALSE}
(assert-true (string=? "hello" "hello"))
(assert-false (string=? "hello" "world"))
```

---

### string<=? {#string-lte-p}

Lexicographic less-than-or-equal comparison.

**Signature:** `(string<=? a b)`

**Parameters:**
- **`a`** — First string.
- **`b`** — Second string.

**Examples:**
```{arl}
(string<=? "abc" "abc")  ; => #t
(string<=? "abc" "def")  ; => #t
(string<=? "def" "abc")  ; => #f
```

```{arl, include=FALSE}
(assert-true (string<=? "abc" "abc"))
(assert-true (string<=? "abc" "def"))
(assert-false (string<=? "def" "abc"))
```

---

### string>=? {#string-gte-p}

Lexicographic greater-than-or-equal comparison.

**Signature:** `(string>=? a b)`

**Parameters:**
- **`a`** — First string.
- **`b`** — Second string.

**Examples:**
```{arl}
(string>=? "abc" "abc")  ; => #t
(string>=? "def" "abc")  ; => #t
(string>=? "abc" "def")  ; => #f
```

```{arl, include=FALSE}
(assert-true (string>=? "abc" "abc"))
(assert-true (string>=? "def" "abc"))
(assert-false (string>=? "abc" "def"))
```

---

## String/List Conversion {#section-string-list-conversion}

Functions for converting between strings, lists, and numbers.

### string->list {#string-to-list}

Convert string to list of characters.

**Signature:** `(string->list str)`

**Parameters:**
- **`str`** — The string to convert.

**Examples:**
```{arl}
(string->list "hello")  ; => ("h" "e" "l" "l" "o")
(string->list "")       ; => ()
```

```{arl, include=FALSE}
(assert-equal (list "h" "e" "l" "l" "o") (string->list "hello"))
(assert-equal (list) (string->list ""))
```

**See also:** [list->string](#list-to-string)

---

### list->string {#list-to-string}

Convert list of characters to string.

**Signature:** `(list->string lst)`

**Parameters:**
- **`lst`** — A list of single-character strings.

**Examples:**
```{arl}
(list->string (list "h" "e" "l" "l" "o"))  ; => "hello"
(list->string (list))                        ; => ""
```

```{arl, include=FALSE}
(assert-equal "hello" (list->string (list "h" "e" "l" "l" "o")))
(assert-equal "" (list->string (list)))
```

**See also:** [string->list](#string-to-list)

---

### number->string {#number-to-string}

Convert number to string with optional base (2-36).

**Signature:** `(number->string num base-args...)`

**Parameters:**
- **`num`** — The number to convert.
- **`base-args`** — Optional base for conversion (2, 8, 10, or 16; default 10).

**Examples:**
```{arl}
(number->string 42)       ; => "42"
(number->string 255 16)   ; => "ff"
(number->string 10 2)     ; => "1010"
(number->string 8 8)      ; => "10"
```

```{arl, include=FALSE}
(assert-equal "42" (number->string 42))
(assert-equal "ff" (number->string 255 16))
(assert-equal "1010" (number->string 10 2))
(assert-equal "10" (number->string 8 8))
```

**See also:** [string->number](#string-to-number)

---

### string->number {#string-to-number}

Parse string to number with optional base (2-36).

**Signature:** `(string->number str base-args...)`

**Parameters:**
- **`str`** — The string to parse.
- **`base-args`** — Optional base for parsing (2, 8, 10, or 16; default 10).

**Examples:**
```{arl}
(string->number "42")       ; => 42
(string->number "3.14")     ; => 3.14
(string->number "ff" 16)    ; => 255
(string->number "1010" 2)   ; => 10
(string->number "bad")      ; => #f
```

```{arl, include=FALSE}
(assert-equal 42 (string->number "42"))
(assert-equal 3.14 (string->number "3.14"))
(assert-equal 255 (string->number "ff" 16))
(assert-equal 10 (string->number "1010" 2))
(assert-false (string->number "bad"))
```

**See also:** [number->string](#number-to-string)

---

## String Predicates {#section-string-predicates}

Common string predicates for prefix, suffix, and emptiness checks.

### string-prefix? {#string-prefix-p}

Return #t if str starts with prefix.

**Signature:** `(string-prefix? prefix str)`

**Parameters:**
- **`prefix`** — String to check for at the start
- **`str`** — String to check

**Examples:**
```{arl}
(string-prefix? "he" "hello")  ; => #t
(string-prefix? "wo" "hello")  ; => #f
```

```{arl, include=FALSE}
(assert-true (string-prefix? "he" "hello"))
(assert-false (string-prefix? "wo" "hello"))
```

**See also:** [string-suffix?](#string-suffix-p), [string-contains?](#string-contains-p)

---

### string-suffix? {#string-suffix-p}

Return #t if str ends with suffix.

**Signature:** `(string-suffix? suffix str)`

**Parameters:**
- **`suffix`** — String to check for at the end
- **`str`** — String to check

**Examples:**
```{arl}
(string-suffix? "lo" "hello")  ; => #t
(string-suffix? "he" "hello")  ; => #f
```

```{arl, include=FALSE}
(assert-true (string-suffix? "lo" "hello"))
(assert-false (string-suffix? "he" "hello"))
```

**See also:** [string-prefix?](#string-prefix-p), [string-contains?](#string-contains-p)

---

### string-empty? {#string-empty-p}

Return #t if str is the empty string.

**Signature:** `(string-empty? str)`

**Parameters:**
- **`str`** — String to check

**Examples:**
```{arl}
(string-empty? "")   ; => #t
(string-empty? "a")  ; => #f
```

```{arl, include=FALSE}
(assert-true (string-empty? ""))
(assert-false (string-empty? "a"))
```

**See also:** [string-length](#string-length)

---

### string-repeat {#string-repeat}

Repeat string n times.

**Signature:** `(string-repeat str n)`

**Parameters:**
- **`str`** — String to repeat
- **`n`** — Number of repetitions

**Examples:**
```{arl}
(string-repeat "ab" 3)  ; => "ababab"
(string-repeat "x" 0)   ; => ""
```

```{arl, include=FALSE}
(assert-equal "ababab" (string-repeat "ab" 3))
(assert-equal "" (string-repeat "x" 0))
```

**See also:** [string-append](#string-append)

---

## Console I/O {#section-console-i-o}

Functions for reading from standard input and writing to standard output.

### read-line {#read-line}

Read single line from stdin.

**Signature:** `(read-line [prompt ""])`

**Parameters:**
- **`prompt`** — Prompt string to display before reading (default "")

**Examples:**
```{arl}
(read-line)              ; waits for user input, returns string
(read-line "Name? ")     ; prints prompt, then waits for input
```

---

### read-from-string {#read-from-string}

**Signature:** `(read-from-string x)`

**See also:** [read](lang-core.html#read)

---

### write-string {#write-string}

Write string to output (alias for cat).

**Signature:** `(write-string x)`

**Parameters:**
- **`x`** — Value to write to standard output

**Examples:**
```{arl}
(write-string "hello")  ; outputs "hello" with no newline
```

**See also:** [display](#display), [newline](#newline)

---

### newline {#newline}

Output a newline.

**Signature:** `(newline)`

**See also:** [display](#display), [write-string](#write-string)

---

## File I/O {#section-file-i-o}

Functions for reading from and writing to files.

### read-file {#read-file}

Read entire file as string.

**Signature:** `(read-file path [encoding "UTF-8"])`

**Parameters:**
- **`path`** — File path to read
- **`encoding`** — Character encoding to use (default "UTF-8")

**Examples:**
```{arl, eval=FALSE}
(read-file "data.txt")                  ; => file contents as string
(read-file "data.txt" "latin1")         ; read with specific encoding
```

```{arl, include=FALSE}
(define _tmp (r-call "tempfile" (list)))
(r-call "writeLines" (list (r-call "c" (list "line1" "line2")) _tmp))
(assert-equal "line1\nline2" (read-file _tmp))
(r-call "unlink" (list _tmp))
```

---

### read-lines {#read-lines}

Read file into list of lines.

**Signature:** `(read-lines path [encoding "UTF-8"])`

**Parameters:**
- **`path`** — File path to read
- **`encoding`** — Character encoding to use (default "UTF-8")

**Examples:**
```{arl, eval=FALSE}
(read-lines "data.txt")  ; => ("line1" "line2" "line3")
```

```{arl, include=FALSE}
(define _tmp (r-call "tempfile" (list)))
(r-call "writeLines" (list (r-call "c" (list "alpha" "beta" "gamma")) _tmp))
(assert-equal (list "alpha" "beta" "gamma") (read-lines _tmp))
(r-call "unlink" (list _tmp))
```

---

### write-file {#write-file}

Write string or lines to file.

**Signature:** `(write-file path content [sep "\n"])`

**Parameters:**
- **`path`** — File path to write to
- **`content`** — String or list of lines to write
- **`sep`** — Separator used to join lines (default "\n")
- **`encoding`** — Character encoding to use (default "UTF-8")

**Examples:**
```{arl, eval=FALSE}
(write-file "out.txt" "hello world")
(write-file "out.txt" (list "line1" "line2"))
```

```{arl, include=FALSE}
(define _tmp (r-call "tempfile" (list)))
(write-file _tmp "hello world")
(assert-equal "hello world" (read-file _tmp))
(r-call "unlink" (list _tmp))
```

---

### write-lines {#write-lines}

Write list of lines to file.

**Signature:** `(write-lines path lines [encoding "UTF-8"])`

**Parameters:**
- **`path`** — File path to write to
- **`lines`** — List of lines to write
- **`encoding`** — Character encoding to use (default "UTF-8")

**Examples:**
```{arl, eval=FALSE}
(write-lines "out.txt" (list "line1" "line2" "line3"))
```

```{arl, include=FALSE}
(define _tmp (r-call "tempfile" (list)))
(write-lines _tmp (list "one" "two" "three"))
(assert-equal (list "one" "two" "three") (read-lines _tmp))
(r-call "unlink" (list _tmp))
```

---

### append-file {#append-file}

Append content to file.

**Signature:** `(append-file path content [sep "\n"])`

**Parameters:**
- **`path`** — File path to append to
- **`content`** — String or list of lines to append
- **`sep`** — Separator used to join lines (default "\n")
- **`encoding`** — Character encoding to use (default "UTF-8")

**Examples:**
```{arl, eval=FALSE}
(append-file "log.txt" "new entry\n")
```

```{arl, include=FALSE}
(define _tmp (r-call "tempfile" (list)))
(write-file _tmp "first")
(append-file _tmp "second")
(assert-true (string-contains? (read-file _tmp) "first"))
(assert-true (string-contains? (read-file _tmp) "second"))
(r-call "unlink" (list _tmp))
```

---

### file-exists? {#file-exists-p}

Return #t if file exists.

**Signature:** `(file-exists? path)`

**Parameters:**
- **`path`** — File path to check

**Examples:**
```{arl, eval=FALSE}
(file-exists? "data.txt")    ; => #t or #f
(file-exists? "nope.txt")    ; => #f
```

```{arl, include=FALSE}
(define _tmp (r-call "tempfile" (list)))
(r-call "writeLines" (list "" _tmp))
(assert-true (file-exists? _tmp))
(assert-false (file-exists? "/nonexistent/path/to/file.txt"))
(r-call "unlink" (list _tmp))
```

---

### file-size {#file-size}

Return size of file in bytes.

**Signature:** `(file-size path)`

**Parameters:**
- **`path`** — File path to query

**Examples:**
```{arl, eval=FALSE}
(file-size "data.txt")       ; => 1024 (bytes)
```

```{arl, include=FALSE}
(define _tmp (r-call "tempfile" (list)))
(r-call "writeLines" (list "hello" _tmp))
(assert-true (> (file-size _tmp) 0))
(r-call "unlink" (list _tmp))
```

---

### file-modified-time {#file-modified-time}

Return file modification time as numeric timestamp.

**Signature:** `(file-modified-time path)`

**Parameters:**
- **`path`** — File path to query

**Examples:**
```{arl, eval=FALSE}
(file-modified-time "data.txt")  ; => 1700000000 (numeric timestamp)
```

```{arl, include=FALSE}
(define _tmp (r-call "tempfile" (list)))
(r-call "writeLines" (list "" _tmp))
(assert-true (> (file-modified-time _tmp) 0))
(r-call "unlink" (list _tmp))
```

---

### file-delete {#file-delete}

Delete file. Return #t on success.

**Signature:** `(file-delete path)`

**Parameters:**
- **`path`** — File path to delete

**Examples:**
```{arl, eval=FALSE}
(file-delete "temp.txt")     ; => #t
```

```{arl, include=FALSE}
(define _tmp (r-call "tempfile" (list)))
(r-call "writeLines" (list "" _tmp))
(assert-true (file-exists? _tmp))
(assert-true (file-delete _tmp))
(assert-false (file-exists? _tmp))
```

---

## Directory Operations {#section-directory-operations}

Functions for querying and manipulating directories.

### directory-exists? {#directory-exists-p}

Return #t if directory exists.

**Signature:** `(directory-exists? path)`

**Parameters:**
- **`path`** — Directory path to check

**Examples:**
```{arl}
(directory-exists? "/tmp")         ; => #t
(directory-exists? "/nonexistent") ; => #f
```

```{arl, include=FALSE}
(assert-true (directory-exists? (r-call "tempdir" (list))))
(assert-false (directory-exists? "/nonexistent/path/that/does/not/exist"))
```

---

### directory-list {#directory-list}

List directory contents as list of filenames.

**Signature:** `(directory-list path [full.names #f])`

**Parameters:**
- **`path`** — Directory path to list
- **`full.names`** — When #t, return full file paths instead of just names (default #f)

**Examples:**
```{arl, eval=FALSE}
(directory-list ".")               ; => ("file1.txt" "file2.txt")
(directory-list "." #t)            ; => ("./file1.txt" "./file2.txt")
```

```{arl, include=FALSE}
(define _tmpdir (r-call "tempfile" (list "dir")))
(r-call "dir.create" (list _tmpdir))
(r-call "writeLines" (list "" (r-call "file.path" (list _tmpdir "a.txt"))))
(r-call "writeLines" (list "" (r-call "file.path" (list _tmpdir "b.txt"))))
(define _listing (directory-list _tmpdir))
(assert-true (> (length _listing) 0))
(assert-true (r-call "%in%" (list "a.txt" _listing)))
(r-call "unlink" (list _tmpdir :recursive #t))
```

---

### directory-delete {#directory-delete}

Delete directory. Return #t on success.

**Signature:** `(directory-delete path [recursive #t])`

**Parameters:**
- **`path`** — Directory path to delete
- **`recursive`** — When #t, delete contents recursively (default #t)

**Examples:**
```{arl, eval=FALSE}
(directory-delete "/tmp/mydir")    ; => #t
```

```{arl, include=FALSE}
(define _tmpdir (r-call "tempfile" (list "deldir")))
(r-call "dir.create" (list _tmpdir))
(assert-true (directory-exists? _tmpdir))
(assert-true (directory-delete _tmpdir))
(assert-false (directory-exists? _tmpdir))
```

---

## Environment and System {#section-environment-and-system}

Functions for environment variables, shell commands, and process control.

### getenv {#getenv}

Get environment variable value. Return #nil if not set.

**Signature:** `(getenv name)`

**Parameters:**
- **`name`** — Environment variable name

**Examples:**
```{arl}
(getenv "HOME")           ; => "/home/user"
(getenv "UNDEFINED_VAR")  ; => #nil
```

```{arl, include=FALSE}
(assert-true (is.character (getenv "HOME")))
(assert-true (is.null (getenv "ARL_UNDEFINED_TEST_VAR_XYZ")))
```

**See also:** [setenv](#setenv)

---

### setenv {#setenv}

Set environment variable.

**Signature:** `(setenv name value)`

**Parameters:**
- **`name`** — Environment variable name
- **`value`** — Value to assign to the variable

**Examples:**
```{arl}
(setenv "MY_VAR" "hello")  ; => #t
```

```{arl, include=FALSE}
(setenv "ARL_TEST_SETENV_VAR" "test_value_123")
(assert-equal "test_value_123" (getenv "ARL_TEST_SETENV_VAR"))
```

**See also:** [getenv](#getenv)

---

### system-output {#system-output}

Execute shell command and capture output as string.

**Signature:** `(system-output command)`

**Parameters:**
- **`command`** — Shell command string to execute

**Examples:**
```{arl}
(system-output "whoami")   ; => "username"
(system-output "echo hi")  ; => "hi"
```

```{arl, include=FALSE}
(assert-equal "hi" (system-output "echo hi"))
```

---

### exit {#exit}

Exit program with status code.

**Signature:** `(exit status)`

**Parameters:**
- **`status`** — Exit status code (default 0)

---

### format-value {#format-value}

Format value for display.

**Signature:** `(format-value x)`

**Parameters:**
- **`x`** — Value to format as a string

---

## Display and Output {#section-display-and-output}

Functions for formatting and printing values.

### display {#display}

Print value with newline.

**Signature:** `(display x)`

**Parameters:**
- **`x`** — Value to print

**Examples:**
```{arl}
(display 42)             ; prints "42" with newline
(display "hello")        ; prints "hello" with newline
(display (list 1 2 3))   ; prints "(1 2 3)" with newline
```

**See also:** [println](#println), [trace](#trace)

---

### println {#println}

Alias for display.

**Signature:** `(println x)`

**Parameters:**
- **`x`** — Value to print

**Examples:**
```{arl}
(println 42)               ; prints "42\n"
(println (list 1 2 3))     ; prints "(1 2 3)\n"
```

**See also:** [display](#display)

---

### string-concat {#string-concat}

Concatenate values into a string.
Strings are included as-is (unquoted); other values are formatted.

**Signature:** `(string-concat args...)`

**Parameters:**
- **`args`** — Values to concatenate together

**Examples:**
```{arl}
(string-concat "hello" " " "world")  ; => "hello world"
(string-concat 1 "+" 2)              ; => "1+2"
```

```{arl, include=FALSE}
(assert-equal "hello world" (string-concat "hello" " " "world"))
(assert-equal "1+2" (string-concat 1 "+" 2))
```

**See also:** [string-join](#string-join), [string-format](#string-format)

---

### trace {#trace}

Print value and return it.

**Signature:** `(trace x rest...)`

**Parameters:**
- **`x`** — Value to print and return
- **`rest`** — Optional label string to prefix the output

**Examples:**
```{arl}
(trace 42)               ; prints "42", returns 42
(trace 42 "result")      ; prints "result: 42", returns 42
```

**See also:** [warn](lang-core.html#warn), [display](#display)

---

