Skip to content

Commit

Permalink
Merge pull request #6781 from jeffnm/tutorial
Browse files Browse the repository at this point in the history
update module header syntax in the tutorial
  • Loading branch information
Anton-4 committed Jun 6, 2024
2 parents c75f3cc + dcdac5f commit b3c28eb
Showing 1 changed file with 26 additions and 32 deletions.
58 changes: 26 additions & 32 deletions www/content/tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,10 @@ Let's move out of the REPL and create our first Roc application!
Make a file named `main.roc` and put this in it:

```roc
app "hello"
packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.10.0/vNe6s9hWzoTZtFmNkvEICPErI9ptji_ySjicO6CkucY.tar.br" }
imports [pf.Stdout, pf.Task]
provides [main] to pf
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.10.0/vNe6s9hWzoTZtFmNkvEICPErI9ptji_ySjicO6CkucY.tar.br" }
import pf.Stdout
import pf.Task
main =
Stdout.line! "I'm a Roc application!"
Expand Down Expand Up @@ -1454,61 +1454,54 @@ Besides being built into the compiler, the builtin modules are different from ot
Let's take a closer look at the part of `main.roc` above the `main` def:

```roc
app "hello"
packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.10.0/vNe6s9hWzoTZtFmNkvEICPErI9ptji_ySjicO6CkucY.tar.br" }
imports [pf.Stdout]
provides [main] to pf
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.10.0/vNe6s9hWzoTZtFmNkvEICPErI9ptji_ySjicO6CkucY.tar.br" }
import pf.Stdout
```

This is known as a _module header_. Every `.roc` file is a _module_, and there are different types of modules. We know this particular one is an _application module_ because it begins with the `app` keyword.

The line `app "hello"` shows that this module is a Roc application. The "hello" after the `app` keyword will be removed soon and is no longer used. If the file is named hello.roc, building this application should produce an executable named `hello`. This means when you run `roc dev`, the Roc compiler will build an executable named `hello` (or `hello.exe` on Windows) and run it. You can also build the executable without running it by running `roc build`.

The remaining lines all involve the [platform](https://github.com/roc-lang/roc/wiki/Roc-concepts-explained#platform) this application is built on:
The line `app [main]` shows that this module is a Roc application and which [platform](https://github.com/roc-lang/roc/wiki/Roc-concepts-explained#platform) it is built on.

```roc
packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.10.0/vNe6s9hWzoTZtFmNkvEICPErI9ptji_ySjicO6CkucY.tar.br" }
imports [pf.Stdout]
provides [main] to pf
```

The `packages { pf: "https://...tar.br" }` part says three things:
The `{ pf: platform "https://...tar.br" }` part says three things:

- We're going to be using a _package_ (a collection of modules) that can be downloaded from the URL `"https://...tar.br"`
- That package's [base64](https://en.wikipedia.org/wiki/Base64#URL_applications)\-encoded [BLAKE3](<https://en.wikipedia.org/wiki/BLAKE_(hash_function)#BLAKE3>) cryptographic hash is the long string at the end (before the `.tar.br` file extension). Once the file has been downloaded, its contents will be verified against this hash, and it will only be installed if they match. This way, you can be confident the download was neither corrupted nor changed since it was originally published.
- We're going to name that package `pf` so we can refer to it more concisely in the future.

The `imports [pf.Stdout]` line says that we want to import the `Stdout` module from the `pf` package, and make it available in the current module.
The `import pf.Stdout` line says that we want to import the `Stdout` module from the `pf` package, and make it available in the current module.

This import has a direct interaction with our definition of `main`. Let's look at that again:

```roc
main = Stdout.line "I'm a Roc application!"
main = Stdout.line! "I'm a Roc application!"
```

Here, `main` is calling a function called `Stdout.line`. More specifically, it's calling a function named `line` which is exposed by a module named `Stdout`.

When we write `imports [pf.Stdout]`, it specifies that the `Stdout` module comes from the package we named `pf` in the `packages { pf: ... }` section.
When we write `import pf.Stdout`, it specifies that the `Stdout` module comes from the package we named `pf` in the `packages { pf: ... }` section.

If we would like to include other modules in our application, say `AdditionalModule.roc` and `AnotherModule.roc`, then they can be imported directly in `imports` like this:

```roc
imports [pf.Stdout, AdditionalModule, AnotherModule]
import pf.Stdout
import AdditionalModule
import AnotherModule
```

You can find documentation for the `Stdout.line` function in the [Stdout](https://www.roc-lang.org/packages/basic-cli/Stdout#line) module documentation.

### [Package Modules](#package-modules) {#package-modules}

Package modules enable Roc code to be easily re-used and shared. This is achieved by organizing code into different Interface modules and then including these in the `exposes` field of the package file structure, `package "name" exposes [ MyInterface ] packages {}`. The modules that are listed in the `exposes` field are then available for use in applications, platforms, or other packages. Internal modules that are not listed will be unavailable for use outside of the package.
Package modules enable Roc code to be easily re-used and shared. This is achieved by organizing code into different modules and then including these in the `package` field of the package file structure, `package [ MyInterface ] {}`. The modules that are listed in the `package` field are then available for use in applications, platforms, or other packages. Internal modules that are not listed will be unavailable for use outside of the package.

See [Parser Package](https://github.com/lukewilliamboswell/roc-parser/tree/main/package) for an example.

Package documentation can be generated using the Roc cli with `roc docs /package/*.roc`.

Build a package for distribution with `roc build --bundle .tar.br /package/main.roc`. This will create a single tarball that can then be easily shared online using a URL.

You can import a package that is available either locally, or from a URL into a Roc application or platform. This is achieved by specifying the package in the `packages` section of the application or platform file structure. For example, `packages { .., parser: "<package URL>" }` is an example that imports a parser module from a URL.
You can import a package that is available either locally, or from a URL into a Roc application or platform. This is achieved by specifying the package in the `packages` section of the application or platform file structure. For example, `{ .., parser: "<package URL>" }` is an example that imports a parser module from a URL.

How does the Roc cli import and download a package from a URL?

Expand Down Expand Up @@ -1565,10 +1558,9 @@ We'll use these four operations to learn about tasks.
Let's start with a basic "Hello World" program.

```roc
app "cli-tutorial"
packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.10.0/vNe6s9hWzoTZtFmNkvEICPErI9ptji_ySjicO6CkucY.tar.br" }
imports [pf.Stdout]
provides [main] to pf
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.10.0/vNe6s9hWzoTZtFmNkvEICPErI9ptji_ySjicO6CkucY.tar.br" }
import pf.Stdout
main =
Stdout.line! "Hello, World!"
Expand Down Expand Up @@ -1599,15 +1591,17 @@ Once this task runs, we'll end up with the [tag union](https://www.roc-lang.org/
Let's change `main` to read a line from `stdin`, and then print what we got:

```roc
app "cli-tutorial"
packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.10.0/vNe6s9hWzoTZtFmNkvEICPErI9ptji_ySjicO6CkucY.tar.br" }
imports [pf.Stdout, pf.Stdin, pf.Task]
provides [main] to pf
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.10.0/vNe6s9hWzoTZtFmNkvEICPErI9ptji_ySjicO6CkucY.tar.br" }
import pf.Stdout
import pf.Stdin
import pf.Task
main =
Stdout.line! "Type in something and press Enter:"
input = Stdin.line!
Stdout.line! "Your input was: $(input)"
```

If you run this program, it will print "Type in something and press Enter:" and then pause.
Expand Down

0 comments on commit b3c28eb

Please sign in to comment.