https://www.roc-lang.org/ Roc tutorialinstallexamplescommunitydocsdonate Roc A purple origami bird made of six triangles A fast, friendly, functional language. list = List.map songs \song -> "Artist: \(song.artist)" Fast Roc code is designed to build fast and run fast. It compiles to machine code or WebAssembly. What does fast mean here? Friendly Roc's syntax, semantics, and included toolset all prioritize user-friendliness. What does friendly mean here? Functional Roc has a small number of simple language primitives. It's a single-paradigm functional language. What does functional mean here? 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 = 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 handleReq = \request -> Task.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: string interpolation, pipelines, and backpassing The tutorial introduces these gradually and in more depth, but this gives a brief overview. (*)# Click anything here to see an explanation.Tap anything here to # see an explanation.X Comments in Roc begin with a # and go to the end of the line. ( )main =X 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. ( )Path.fromStr "url.txt"X This converts the string "url.txt" into a Path by passing it to Path.fromStr. Function arguments are separated with whitespace. Parentheses are only needed in nested function calls. ( )|> storeEmailX The pipe operator (|>) is syntax sugar for passing the previous value to the next function in the "pipeline." This line takes the value that Path.fromStr "url.txt" returns and passes it to storeEmail. The next |> continues the pipeline. ( )|> Task.onErr handleErrX If the task returned by the previous step in the pipeline fails, pass its error to handleErr. The pipeline essentially does this: a = Path.fromStr "url.txt" b = storeEmail a Task.onErr b handleErr It creates a Path from a string, stores an email based on that path, and then does error handling. ( )storeEmail = \path ->X This defines a function named storeEmail. It takes one argument, named path. 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 -> is the function's body. ( )url <- File.readUtf8 path |> Task.awaitX This reads the contents of the file (as a UTF-8 string) into url. The <- does backpassing, which is syntax sugar for defining a function. This line desugars to: Task.await (File.readUtf8 path) \url -> The lines after this one form the body of the \url -> callback, which runs if the file read succeeds. ( )user <- Http.get url Json.codec |> Task.awaitX 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 lines ending in |> Task.await, if there's an error, nothing else in storeEmail will be run, and handleErr will end up handling the error. ( )dest = Path.fromStr "\(user.name).txt"X The \(user.name) in this string literal will be replaced with the value in name. This is string interpolation. Note that this line doesn't end with |> Task.await. Earlier lines needed that because they were I/O tasks, but this is a plain old definition, so there's no task to await. ( )_ <- File.writeUtf8 dest user.email |> Task.awaitX This writes user.email to the file, encoded as UTF-8. We won't be using the output of writeUtf8, so we name it _. The special name _ is for when you don't want to use something. You can name as many things as you like _, but you can never reference anything named _. So it's only useful for when you don't want to choose a name. ( )Stdout.line "Wrote email to \(Path.display dest)"X This prints what we did to stdout. Note that this line doesn't end with |> Task.await. That's because, although Stdout.line returns a task, we don't need to await it because nothing happens after it. ( )handleErr = \err ->X Like storeEmail, handleErr 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, storeEmail, and handleErr if you wanted to. ( )when err isX 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 storeEmail. ( )HttpErr url _ -> Stderr.line "Error fetching URL \(url)"X 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 the HttpErr. If we wanted to print more detail about what the error was, we'd name that something other than _ and actually use it. ( )FileReadErr path _ -> Stderr.line "Error reading from \(Path. display path)"X This line will run if the File.readUtf8 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 the FileReadErr. If we wanted to print more detail about what the error was, we'd name that something other than _ and actually use it. ( )FileWriteErr path _ -> Stderr.line "Error writing to \(Path. display path)"X This line will run if the File.writeUtf8 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 the FileWriteErr. 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! Start Tutorial Sponsors We are very grateful for our corporate sponsors Vendr, RWX, and Tweede golf: 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: * Aaron White * Ayaz Hafiz * Christopher Dolan * Ivo Balbaert * James Birtles * Jonas Schell * Lucas Rosa * Nick Gravgaard * Richard Feldman * Shritesh Bhattarai * Zeljko Nesic 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: * GitHub Sponsors * Liberapay 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. powered by Netlify