Last active
June 26, 2024 09:05
-
-
Save giacomocavalieri/192dd30f4fe5c85b79d1bea2238e4055 to your computer and use it in GitHub Desktop.
Lines stream in Gleam
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import gleam/dynamic.{type Dynamic} | |
import gleam/int | |
import gleam/io | |
const file = "./lines.txt" | |
pub fn main() { | |
let assert Ok(stream) = open(file) | |
let assert Ok(lines) = do_count_lines(stream, 0) | |
lines |> int.to_string |> io.println | |
} | |
fn do_count_lines(stream: FileStream, acc: Int) -> Result(Int, FileStreamError) { | |
case read_line(stream) { | |
Error(Other(reason)) -> Error(Other(reason)) | |
Error(Eof) -> Ok(acc) | |
Ok(_) -> do_count_lines(stream, acc + 1) | |
} | |
} | |
type FileStream | |
type FileStreamError { | |
Eof | |
Other(Dynamic) | |
} | |
@external(erlang, "read_line_ffi", "open") | |
fn open(file: String) -> Result(FileStream, Nil) | |
@external(erlang, "read_line_ffi", "read_line") | |
fn read_line(stream: FileStream) -> Result(String, FileStreamError) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-module(read_line_ffi). | |
-export([open/1, read_line/1]). | |
open(File) -> | |
% Here we specify a couple options: | |
% - `raw`: allows for faster access to the file. | |
% - `binary`: reads the contents of the file as binary | |
% which is what Gleam represents Strings as. | |
% - `read_ahead`: this is highly recommended from | |
% Erlang's doc when reading line-by-line a raw file | |
% and allows to squeeze out a bit more performance | |
% reducing the number of system calls. | |
% - `{encoding, utf8}`: Gleam strings are utf8 encoded | |
% so we want to make sure what we read is a valid | |
% string. | |
case file:open(File, [raw, binary, read_ahead, {encoding, utf8}]) of | |
{ok, Stream} -> {ok, Stream}; | |
{error, _} -> {error, nil} | |
end. | |
% Nothing special is going on here, we just have to | |
% massage `file:read_line`'s type into a Gleam result | |
% type. | |
read_line(Stream) -> | |
case file:read_line(Stream) of | |
{ok, Line} -> {ok, Line}; | |
eof -> {error, eof}; | |
{error, Reason} -> {error, {other, Reason}} | |
end. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Jak Gleam MVP