Stream: show and tell

Topic: Roc ASCII


view this post on Zulip Hannes (May 03 2024 at 02:02):

https://github.com/Hasnep/roc-ascii

Most of the time it's best to support UTF-8, but sometimes you have data that is just ASCII and you can avoid some of the complexity of UTF-8, so I made a quick package with two types: an ASCII string and an ASCII character. See the docs for more info: https://hasnep.github.io/roc-ascii

view this post on Zulip Hannes (Feb 03 2025 at 12:10):

I've just released v0.3.0 of roc-ascii which supports Roc v0.0.0-alpha2 and changes the Ascii type from an opaque type to a plain List Char :)

view this post on Zulip Hannes (Aug 18 2026 at 02:37):

I've just released v0.4.0 v0.4.1 of roc-ascii which supports the new Roc compiler :)

view this post on Zulip Aurélien Geron (Aug 18 2026 at 03:37):

Awesome @Hannes ! I'll add it to the list of libraries available in the Exercism Roc track, since most exercises that manipulate text assume it's ASCII-only. However, it looks like there's currently no release file (.tar.zst)?

view this post on Zulip Hannes (Aug 18 2026 at 04:46):

Just having some technical difficulties with CI, will be ready soon!

view this post on Zulip Hannes (Aug 18 2026 at 06:01):

Okay, v0.4.1 has been released!

view this post on Zulip Aurélien Geron (Aug 18 2026 at 06:30):

@Hannes it looks like something's wrong with the release file, for some reason:

── ✗ package download failed ───────────────────────────────────────────────────────────────────────────────────────────

Failed to download and extract this package:

    https://github.com/Hasnep/roc-ascii/releases/download/v0.4.1/AnawhDawcVySaW3ywcvfUPuhbXfJK7jcwEHaMBAfVv2y.tar.zst

Error: FileNotFound.

── 1 error and 0 warnings ──────────────────────────────────────────────────────────────── bin/download-dependencies.roc

view this post on Zulip Hannes (Aug 18 2026 at 06:32):

Uhoh, I didn't test it :sweat_smile: let me have a look!

view this post on Zulip Aurélien Geron (Aug 18 2026 at 06:32):

Oh it looks like the roc bundle command was launched from the root directory instead of inside the src directory:

% tar xvf AnawhDawcVySaW3ywcvfUPuhbXfJK7jcwEHaMBAfVv2y.tar.zst
x src/main.roc
x src/Char.roc
x src/Utils.roc
x src/Ascii.roc

view this post on Zulip Hannes (Aug 18 2026 at 06:46):

Created an issue for this: https://github.com/roc-lang/roc/issues/10845

view this post on Zulip Luke Boswell (Aug 18 2026 at 06:47):

I think this is by design, you need to explicitly pass the files you want bundled. It doesn't auto find them like the old compiler

view this post on Zulip Luke Boswell (Aug 18 2026 at 06:48):

The design for packages and the targets is a little different. The goal is to give platform/package authors more flexibility and control.

view this post on Zulip Aurélien Geron (Aug 18 2026 at 06:49):

FYI, I just ran roc bundle main.roc inside the src directory, and the bundle contains all *.roc files in this directory (presumably because they're listed in main.roc).

view this post on Zulip Luke Boswell (Aug 18 2026 at 06:53):

Cool, I probably have outdated memory then

view this post on Zulip Richard Feldman (Aug 18 2026 at 12:16):

I do think we should auto-discover dependencies and include those

view this post on Zulip Richard Feldman (Aug 18 2026 at 12:17):

like if you include a .roc file which imports other files, we should bring all those in so your bundle isn't broken :sweat_smile:

view this post on Zulip Hannes (Sep 04 2026 at 15:16):

Just released v0.5.0 which is compatible with the latest Roc nightly and has a functioning release URL you can use. Thanks to @Aurélien Geron for your help!

view this post on Zulip Hannes (Sep 04 2026 at 15:35):

Here's a small example program:

app [main!] {
    cli: platform "https://github.com/roc-lang/basic-cli/releases/download/0.21.0/4rAQg8kUYZ3Vksr4qMQHpaFYNiHSn9GgS7gVxghd1XYV.tar.zst",
    ascii: "https://github.com/Hasnep/roc-ascii/releases/download/v0.5.0/5WxqRf15XVko4HxVq5dW8r84s95CxrtvzrjZYwbg9Z3H.tar.zst",
}

import cli.Stdout
import cli.Stderr
import cli.Stdin
import ascii.Ascii

repeat_input_but_shouting! = || {
    stdin = Stdin.read_to_end!().map_err(|_| "Failed to read from stdin!")?
    msg = Ascii.from_ascii_bytes(stdin).map_err(|_| "Non-ASCII input data!")?
    Stdout.write!(msg.to_uppercase().to_str()).map_err(|_| "Failed to write to stdout!")
}

main! = |_| {
    match repeat_input_but_shouting!() {
        Ok(_) => Ok({})
        Err(err_msg) => {
            _ = Stderr.line!(err_msg)
            Err(Exit(1))
        }
    }
}
❱ echo hi | roc example.roc
HI

view this post on Zulip Steve Howell (Oct 28 2026 at 19:35):

See also https://github.com/showell/roc-webbox/blob/a182bf2/chat/Ascii.roc

Before I realized/remembered that https://github.com/Hasnep/roc-ascii was a thing, I had Claude writing some code, and the same needs came up: is_digit, is_hex_digit, is_alphanumeric, is_whitespace, is_punctuation, is_control, is_letter, to_lowercase, to_uppercase are all in my codebase.

We actually differ on is_whitespace. My version is C's six bytes, which Zig and Go share.

view this post on Zulip Steve Howell (Oct 28 2026 at 19:40):

I think there's an argument to upstream some of these to the Roc standard library. OTOH there's a clear argument that individual developers can knock these out pretty easily. So I'm just giving a data point here.

view this post on Zulip Steve Howell (Oct 28 2026 at 20:49):

There's also a lot of discussion on #ideas > Add an Ascii type to the standard library about ASCII. It's not totally clear to me whether there were any decisions made there.

view this post on Zulip Steve Howell (Oct 29 2026 at 13:37):

I'm now using my ascii library in two different places, which makes me lean more toward wanting them as builtins eventually. It's not a true blocker for me, to be clear. But I'm from the Python school that "batteries included" is a good philosophy, and ascii helpers feel like batteries.

view this post on Zulip Anton (Oct 29 2026 at 14:15):

I'm inclined to agree although I think we probably won't add this before 0.1

view this post on Zulip Richard Feldman (Oct 29 2026 at 16:06):

yeah I want to revisit after 0.1 - I don't really want to add design work projects to 0.1.0's scope unless they're really small and/or urgent :smile:

view this post on Zulip Steve Howell (Oct 29 2026 at 16:46):

FWIW there's much design work to do to move https://github.com/showell/roc-webbox/blob/a182bf2/chat/Ascii.roc into builtins soon after 0.1.0.

It's 227 lines of code, mostly tests. The tests are completely exhaustive. The APIs were all cross-checked against Zig, Rust, C, and Go to try to conform to de facto standards. Every single function is implemented with a one-liner.

I had Claude look into calling directly into zig, but the Roc versions pretty much produce the same code as zig. The zig standard library doesn't do anything exotic like lookup tables that we would want to investigate.

Here's a quick taste:

    ## `a`-`z` to `A`-`Z`; every other byte, 128 to 255 included, unchanged.
    ## Zig `toUpper`, Rust `to_ascii_uppercase`, C `toupper`, and the per-byte
    ## rule of `Str.with_ascii_uppercased`.
    to_uppercase : U8 -> U8
    to_uppercase = |c| if c >= 'a' and c <= 'z' c.bitwise_xor(0x20) else c

Last updated: Nov 04 2026 at 18:54 UTC