Roc
A fast, friendly, functional language.
credits = List.map(songs, |song| "Performed by ${song.artist}"
)
Try Roc
You can try Roc using this read-eval-print loop (REPL), which is running in your browser in WebAssembly.
Shift-Enter
adds a newline.
Try entering 0.1 + 0.2
Enter an expression to evaluate, or a definition (like x = 1) to use later.
Examples
Roc is a young language. It doesn't even have a numbered release yet, just nightly builds!
However, it can already be used for several things if you're up for being an early adopter—
with all the bugs and missing features which come with that territory.
Here are some examples of how it can be used today.
Command-Line Interfaces
main! = |args| Stdout.line!("Hello!")
You can use Roc to create scripts and command-line interfaces (CLIs). The compiler produces binary executables, so Roc programs can run on devices that don't have Roc itself installed.
As an example, the HTML for this website is generated using a simple Roc script. You can see the code for it in the main Roc code repository.
If you’re looking for a starting point for building a command-line program in Roc, basic-cli is a popular platform to check out.
Web Servers
handle_req! = |request| Ok({ body: … })
You can also build web servers in Roc. basic-webserver is a platform with
a simple interface: you write a function which takes a Request
, does some I/O, and returns a Response
.
Behind the scenes, it uses Rust's high-performance hyper and tokio libraries to execute your Roc function on incoming requests.
For database access, roc-pg lets you access a PostgreSQL database—with your Roc types checked against the types in your database's schema.
Embedding
fn = require("foo.roc"); log(`Roc says ${fn()}`);
You can call Roc functions from other languages. There are several basic examples of how to call Roc functions from Python, Node.js, Swift, WebAssembly, and JVM languages.
Any language that supports C interop can call Roc functions, using similar techniques to the ones found in these examples.
Most of those are minimal proofs of concept, but roc-esbuild is a work in progress that's used at Vendr to call Roc functions from Node.js.
Other Examples
You can find more use cases and examples on the examples page!
Code Sample with Explanations
Here's a code sample that shows a few different aspects of Roc:
- File I/O and HTTP requests
- Pattern matching for error handling
- JSON deserialization via type inference
- Common syntax sugar: the
?
infix and postfix operators and string interpolation
The tutorial introduces these gradually and in more depth, but this gives a brief overview.
Comments in Roc begin with
#
and go to the end of the line.This defines
main!
, which is where our program will begin.In Roc, all definitions are constant, so writing
main! =
again in the same scope would give an error.This converts the string
"url.txt"
into aPath
by passing it toPath.from_str
.It then sends that result to
store_email!
. The!
sigil at the end tells you that this function is effectual, meaning it will either do I/O, talk to the network, or can otherwise return a different result each time it's called. Functions that do not end in!
will always return the same result given the same arguments.Function arguments are surrounded with parenthesis and separated by commas.
The
?
infix operator here will return the result if successful, otherwise it will callhandle_err!
with the error if it fails.This defines a function named
store_email!
. It takes one argument, namedpath
.In Roc, functions are ordinary values, so we assign names to them using
=
like with any other value.The
|arg1, arg2|
syntax begins a function, and the part after the final|
is the function's body.This passes
path
to theFile.read_utf8
function, which reads the contents of the file (as a UTF-8 string) intourl
.The
!
sigil at the end tells you that this function is effectual, meaning it will either do I/O, talk to the network, or can otherwise return a different result each time it's called. Functions that do not end in!
will always return the same result given the same arguments.The
?
is an operator that means, if the file read fails (maybe becausepath
refers to a missing file), the rest of this function will be skipped, and thehandle_err
function will take over.This fetches the contents of the URL and decodes them as JSON.
If the shape of the JSON isn't compatible with the type of
user
(based on type inference), this will give a decoding error immediately.As with all the other function calls that end with the
?
postfix operator, if there's an error, nothing else instore_email!
will be run, andhandle_err!
will run.The
$(user.name)
in this string literal will be replaced with the value stored in theuser
record'sname
field. This is string interpolation.Note that this function call doesn't involve the
?
operator. That's becausePath.from_str
isn't an effectual function and can't fail, so there's no need to use?
to handle it's result.This writes
user.email
to the file, encoded as UTF-8.Since
File.write_utf8!
doesn't produce any information on success, we don't bother using=
like we did on the other lines.This prints what we did to stdout.
Notice that this does a function call inside the string interpolation. Any valid Roc expression is allowed inside string interpolation, as long as it doesn't contain any newlines.
Like
store_email!
,handle_err!
is also a function.Although type annotations are optional everywhere in Roc—because the language has 100% type inference—you could add type annotations to
main!
,store_email!
, andhandle_err!
if you wanted to.This will run one of the following lines depending on what value the
err
argument has.Each line does a pattern match on the shape of the error to decide whether to run, or to move on and try the next line's pattern.
Roc will do compile-time exhaustiveness checking and tell you if you forgot to handle any error cases here that could have occurred, based on the tasks that were run in
store_email
.This line will run if the
Http.get
request from earlier encountered an HTTP error.It handles the error by printing an error message to stderr.
The
_
is where more information about the error is stored in theHttpErr
. If we wanted to print more detail about what the error was, we'd name that something other than_
and actually use it.This line will run if the
File.read_utf8!
from earlier encountered a file I/O error.It handles the error by printing an error message to stderr.
The
_
is where more information about the error is stored in theFileReadErr
. If we wanted to print more detail about what the error was, we'd name that something other than_
and actually use it.This line will run if the
File.write_utf8!
from earlier encountered a file I/O error.It handles the error by printing an error message to stderr.
The
_
is where more information about the error is stored in theFileWriteErr
. If we wanted to print more detail about what the error was, we'd name that something other than_
and actually use it.
To get started with the language, try the tutorial!
Sponsors
We are very grateful for our corporate sponsors! They are: Tweede golf, ohne-makler, and Decem.
If you would like your organization to become an official sponsor of Roc's development, please DM Richard Feldman on Zulip!
We'd also like to express our gratitude to our generous individual sponsors! A special thanks to those sponsoring $25/month or more:
- Anthony Bullard
- Peter Marreck
- Barry Moore
- Eric Andresen
- Jackson Lucky
- Agus Zubiaga
- Angelo Ceccato
- Niclas Overby
- Krzysztof G.
- Sam Mohr
- Steven Chen
- Drew Lazzeri
- Alex Binaei
- Jono Mallanyk
- Chris Packett
- James Birtles
- Ivo Balbaert
- Lucas Rosa
- Jonas Schell
- Christopher Dolan
- Nick Gravgaard
- Zeljko Nesic
- Shritesh Bhattarai
- Richard Feldman
- Ayaz Hafiz
Thank you all for your contributions! Roc would not be what it is without your generosity. 💜
We are currently trying to raise $4,000 USD/month in donations to fund one longtime Roc contributor to continue his work on Roc full-time. We are a small group trying to do big things, and every donation helps! You can donate using:
All donations go through the Roc Programming Language Foundation, a registered US 501(c)(3) nonprofit organization, which means these donations are tax-exempt in the US.