Merge pull request #4605 from roc-lang/tutorial-changes

Tutorial and homepage updates
This commit is contained in:
Richard Feldman 2022-11-25 21:25:10 -05:00 committed by GitHub
commit 9ce2f4e1ff
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 36 additions and 49 deletions

View file

@ -177,26 +177,17 @@
<p>The REPL fully supports entering arbitrary expressions, and will evaluate them and print the
results. It remembers recent expressions entered in the current session (if you press the up arrow),
but it can't yet execute effects, and any named variables you define currently exist only for the
next expression it evaluates; they don't yet persist for the remainder of the session. You can try
out the REPL in a browser at <a href="https://roc-lang.org/repl">roc-lang.org/repl</a> - it uses a
WebAssembly build of Roc's compiler, and compiles the code you write to WebAssembly on the fly,
which it then executes in the browser to display the answer.</p>
but it can't yet execute effects. You can try out the REPL in a browser at
<a href="https://roc-lang.org/repl">roc-lang.org/repl</a> - it uses a WebAssembly build of Roc's
compiler, and compiles the code you write to WebAssembly on the fly, which it then executes in
the browser to display the answer.</p>
<p>The compiler works well enough on a basic level to build things with it, but some error messages
could use significant improvement, and it has a lot of known bugs and missing features. You can
currently use it on macOS (either Intel or Apple Silicon), Linux (only x86 machines at the moment),
and Windows (only recently supported; there are definitely still a number of issues to iron out).
Support for other operating systems has not yet been discussed.</p>
<p>In the future, the entire Roc toolset should work completely as a standalone binary, but for now,
application development requires additionally having some combination of
<a href="https://clang.llvm.org">clang</a>,
<a href="https://www.rust-lang.org/">Rust</a>, and
<a href="https://ziglang.org">Zig</a> installed on your machine. These are needed to compile
certain platform dependencies on the fly; in the future, the plan is to have the package manager
include precompiled target-specific binaries for these dependencies, so the only binary you'll need
to have is the one that includes the Roc compiler itself.</p>
currently use it on macOS (either Intel or Apple Silicon), Linux (only x86-64 machines at the moment),
and Windows (only recently supported; debugging and testing features don't work on it yet, and
there are likely bugs we haven't encountered yet due to lack of battle testing). Support for other
operating systems has not yet been discussed.</p>
<p>The compiler doesn't yet support incremental compilation or hot code loading, and build times vary
based on what machine you're building for.</p>
@ -220,12 +211,13 @@ longer to run than generating unoptimized machine code directly.)</p>
ways to go, but improving them can be done by anyone with the patience to read some documentation;
we have issues split up for them, and are happy to help new contributors get up and running!</p>
<p>Builds on x86 Linux also use Roc's surgical linker instead of the system linker, which runs so
fast that linking essentially disappears from the performance profile altogether. The surgical linker
currently only works on x86 Linux. Work has started on the Windows and macOS implementations, but
these have been more challenging in large part because up-to-date public documentation for macOS's
Mach-O file format is hard to find. If you're interested in working on that, please get in touch on
<a href="https://roc.zulipchat.com/">Roc Zulip</a>!</p>
<p>Builds on Linux and Windows also use Roc's surgical linker instead of the system linker, which
runs so fast that linking essentially disappears from the performance profile altogether. The
surgical linker currently only works on Linux and Windows, and it currently supports building
executables but not (yet) dynamic libraries, which is relevant if you're using Roc to create
plugins or want to call Roc functions from existing code bases in other languages. Work has started
on macOS surgical linking, but it isn't usable yet. If you're interested in working on that,
please get in touch on <a href="https://roc.zulipchat.com/">Roc Zulip</a>!</p>
<p>The test runner currently has first-class support for running standard non-effectful tests.
It does not yet have first-class support for effectful tests, property-based tests, snapshot tests,

View file

@ -175,13 +175,17 @@ to use them for more than that.</p>
<p>Let's move out of the REPL and create our first Roc application!</p>
<p>Make a file named <code>main.roc</code> and put this in it:</p>
<samp><span class="kw">app</span> <span class="str">"hello"</span>
<span class="kw">packages</span> <span class="brace">{</span> pf: <span class="str">"https://roc-lang.org/basic-cli/1.0.0/oUkxSOI9zFGtSoIaMB40QPdrXphr1p1780eiui2iO9Mz.rp1"</span> <span class="brace">}</span>
<span class="kw">packages</span> <span class="brace">{</span> pf: <span class="str">"examples/cli/cli-platform/main.roc"</span> <span class="brace">}</span>
<span class="kw">imports</span> <span class="brace">[</span>pf.Stdout<span class="brace">]</span>
<span class="kw">provides</span> <span class="brace">[</span>main<span class="brace">]</span> <span class="kw">to</span> pf
main <span class="kw">=</span>
Stdout.line <span class="str">"I'm a Roc application!"</span>
</samp>
<p>In order to get access to this <code>examples/cli/cli-platform/main.roc</code> file, you'll need
to download the <a href="https://github.com/roc-lang/roc">Roc source code repository</a>, which
contains the <code>examples</code> directory at the beginning of that string. Make sure you <code>cd</code>
into that directory once you've downloaded it!</p>
<p>Try running this with:</p>
<samp>roc dev</samp>
<p>You should see this printed to the terminal:</p>
@ -198,7 +202,6 @@ total <span class="kw">=</span> Num.toStr <span class="paren">(</span>birds <spa
main <span class="kw">=</span>
Stdout.line <span class="str">"There are <span class="str-esc">\(</span><span class="str-interp">total</span><span class="str-esc">)</span> animals."</span>
<span class="kw">|&gt;</span> Program.quick
</samp>
<p>Now if you run <code>roc dev</code>, you should see this:</p>
<samp>There are 5 animals.</samp>
@ -232,7 +235,6 @@ total <span class="kw">=</span> Num.toStr <span class="paren">(</span>birds <spa
main <span class="kw">=</span>
Stdout.line <span class="str">"There are <span class="str-esc">\(</span><span class="str-interp">total</span><span class="str-esc">)</span> animals."</span>
<span class="kw">|&gt;</span> Program.quick</span>
addAndStringify <span class="kw">= \</span>num1<span class="kw">,</span> num2 <span class="kw">-&gt;</span>
Num.toStr <span class="paren">(</span>num1 <span class="op">+</span> num2<span class="paren">)</span>
@ -320,9 +322,9 @@ a concise tag like <code>T</code>:
<samp><span class="kw">dbg</span> T "the value of `count` is:" count</samp>
</section>
<p>Note that <code>dbg</code> is a debugging tool, and is only available when running
your program via <code>roc dev</code>, <code>roc run</code>, or <code>roc test</code>. When you
build a standalone application with <code>roc build</code>, any uses of <code>dbg</code> won't
be included!</p>
your program via a <code>roc</code> subcommand (for example using <code>roc dev</code>,
<code>roc run</code>, or <code>roc test</code>). When you build a standalone application with
<code>roc build</code>, any uses of <code>dbg</code> won't be included!</p>
<section><h2 id="records"><a href="#records">Records</a></h2>
<p>Currently our <code>addAndStringify</code> function takes two arguments. We can instead make
it take one argument like so:</p>
@ -1230,7 +1232,7 @@ Roc compiler. That's why they're called "builtins!"</p>
<p>Let's take a closer look at the part of <code>main.roc</code> above the <code>main</code> def:</p>
<samp><span class="hljs-selector-tag">app</span> "<span class="hljs-selector-tag">hello</span>"
<span class="hljs-selector-tag">packages</span> { <span class="attribute">pf</span>: <span class="str">"examples/cli/cli-platform/main.roc"</span> }
<span class="hljs-selector-tag">imports</span> <span class="hljs-selector-attr">[pf.Stdout, pf.Program]</span>
<span class="hljs-selector-tag">imports</span> <span class="hljs-selector-attr">[pf.Stdout]</span>
<span class="hljs-selector-tag">provides</span> <span class="hljs-selector-tag">main</span> <span class="hljs-selector-tag">to</span> <span class="hljs-selector-tag">pf</span>
</samp>
<p>This is known as a <em>module header</em>. Every <code>.roc</code> file is a <em>module</em>, and there
@ -1243,7 +1245,7 @@ named <code>hello</code> (or <code>hello.exe</code> on Windows) and run it. You
without running it by running <code>roc build</code>.</p>
<p>The remaining lines all involve the <em>platform</em> this application is built on:</p>
<samp><span class="hljs-selector-tag">packages</span> { <span class="attribute">pf</span>: <span class="str">"examples/cli/cli-platform/main.roc"</span> }
<span class="hljs-selector-tag">imports</span> <span class="hljs-selector-attr">[pf.Stdout, pf.Program]</span>
<span class="hljs-selector-tag">imports</span> <span class="hljs-selector-attr">[pf.Stdout]</span>
<span class="hljs-selector-tag">provides</span> <span class="hljs-selector-tag">main</span> <span class="hljs-selector-tag">to</span> <span class="hljs-selector-tag">pf</span>
</samp>
<p>The <code>packages { pf: "examples/cli/cli-platform/main.roc" }</code> part says two things:</p>
@ -1251,19 +1253,17 @@ without running it by running <code>roc build</code>.</p>
<li>We're going to be using a <em>package</em> (that is, a collection of modules) called <code>"examples/cli/cli-platform/main.roc"</code></li>
<li>We're going to name that package <code>pf</code> so we can refer to it more concisely in the future.</li>
</ul>
<p>The <code>imports [pf.Stdout, pf.Program]</code> line says that we want to import the <code>Stdout</code> and <code>Program</code> modules
from the <code>pf</code> package, and make them available in the current module.</p>
<p>The <code>imports [pf.Stdout]</code> line says that we want to import the <code>Stdout</code> module
from the <code>pf</code> package, and make it available in the current module.</p>
<p>This import has a direct interaction with our definition of <code>main</code>. Let's look
at that again:</p>
<samp><span class="attr">main</span> <span class="op">=</span> Stdout.line <span class="str">"I'm a Roc application!"</span> |&gt; Program.quick
<samp><span class="attr">main</span> <span class="op">=</span> Stdout.line <span class="str">"I'm a Roc application!"</span>
</samp>
<p>Here, <code>main</code> is calling a function called <code>Stdout.line</code>. More specifically, it's
calling a function named <code>line</code> which is exposed by a module named
<code>Stdout</code>.
Then the result of that function call is passed to the <code>quick</code> function of the <code>Program</code> module,
which effectively makes it a simple Roc program.</p>
<p>When we write <code>imports [pf.Stdout, pf.Program]</code>, it specifies that the <code>Stdout</code>
and <code>Program</code> modules come from the <code>pf</code> package.</p>
<p>When we write <code>imports [pf.Stdout]</code>, it specifies that the <code>Stdout</code>
module comes from the <code>pf</code> package.</p>
<p>Since <code>pf</code> was the name we chose for the <code>examples/cli/cli-platform/main.roc</code>
package (when we wrote <code>packages { pf: "examples/cli/cli-platform/main.roc" }</code>),
this <code>imports</code> line tells the Roc compiler that when we call <code>Stdout.line</code>, it
@ -1271,7 +1271,7 @@ should look for that <code>line</code> function in the <code>Stdout</code> modul
<code>examples/cli/cli-platform/main.roc</code> package.</p>
<p>If we would like to include other modules in our application, say <code>AdditionalModule.roc</code> and <code>AnotherModule.roc</code>, then they can be imported directly in <code>imports</code> like this: </p>
<samp><span class="hljs-selector-tag">packages</span> { <span class="attribute">pf</span>: <span class="str">"examples/cli/cli-platform/main.roc"</span> }
<span class="hljs-selector-tag">imports</span> <span class="hljs-selector-attr">[pf.Stdout, pf.Program, AdditionalModule, AnotherModule]</span>
<span class="hljs-selector-tag">imports</span> <span class="hljs-selector-attr">[pf.Stdout, AdditionalModule, AnotherModule]</span>
<span class="hljs-selector-tag">provides</span> <span class="hljs-selector-tag">main</span> <span class="hljs-selector-tag">to</span> <span class="hljs-selector-tag">pf</span>
</samp>
<h2 id="comments"><a href="#comments">Comments</a></h2>
@ -1301,12 +1301,11 @@ platforms. Let's use the CLI platform in <code>examples/cli/cli-platform/main.ro
<p>First, let's do a basic "Hello World" using the tutorial app.</p>
<samp><span class="kw">app</span> <span class="str">"cli-tutorial"</span>
packages { pf: <span class="str">"examples/cli/cli-platform/main.roc"</span> }
imports [pf.Stdout, pf.<span class="kw">Program</span>]
imports [pf.Stdout]
provides [main] to pf
main <span class="op">=</span>
Stdout.<span class="kw">line</span> <span class="str">"Hello, World!"</span>
|&gt; <span class="kw">Program</span>.quick
</samp>
<p>The <code>Stdout.line</code> function takes a <code>Str</code> and writes it to <a href="https://en.wikipedia.org/wiki/Standard_streams#Standard_output_(stdout">standard output</a>).
It has this type:</p>
@ -1327,12 +1326,10 @@ when it runs (hence the <code>*</code>).</p>
<p>Let's change <code>main</code> to read a line from <code>stdin</code>, and then print it back out again:</p>
<samp>app <span class="str">"cli-tutorial"</span>
packages { pf: <span class="str">"examples/cli/cli-platform/main.roc"</span> }
imports [pf.Stdout, pf.Stdin, pf.Task, pf.Program]
imports [pf.Stdout, pf.Stdin, pf.Task]
provides [main] to pf
main <span class="op">=</span> Program.quick task
task <span class="op">=</span>
main <span class="op">=</span>
Task.await Stdin.line \text <span class="op">-&gt;</span>
Stdout.line <span class="str">"You just entered: \(text)"</span>
</samp>
@ -1364,12 +1361,10 @@ the program isn't doing anything when we start it up:</p>
<p>This works, but we can make it a little nicer to read. Let's change it to the following:</p>
<samp>app <span class="str">"cli-tutorial"</span>
packages { pf: <span class="str">"examples/cli/cli-platform/main.roc"</span> }
imports [pf.Stdout, pf.Stdin, pf.Task.{ await }, pf.Program]
imports [pf.Stdout, pf.Stdin, pf.Task.{ await }]
provides [main] to pf
main <span class="op">=</span> Program.quick task
task <span class="op">=</span>
main <span class="op">=</span>
await (Stdout.line <span class="str">"Type something press Enter:"</span>) \_ <span class="op">-&gt;</span>
await Stdin.line \text <span class="op">-&gt;</span>
Stdout.line <span class="str">"You just entered: \(text)"</span>