Stream: beginners

Topic: Am I doing something silly?


view this post on Zulip jan kili (Jan 07 2022 at 05:31):

Happy to make an issue for this, but I just want a sanity check - does this make sense to anyone?

view this post on Zulip jan kili (Jan 07 2022 at 05:31):

Module A:

main =
    _ <- await (line "")
    double = \x -> x * 2
    doubleBind = \x -> (\_ -> double x)
    six = (doubleBind 3) {}
    line (Num.toStr six)

Output A:

6

view this post on Zulip jan kili (Jan 07 2022 at 05:32):

Module B:

main =
    _ <- await (line "")
    double = \x -> x * 2
    doubleBind = \x -> (\_ -> double x)
    doubleThree = doubleBind 3
    six = doubleThree {}
    line (Num.toStr six)

Output B:

thread 'main' panicked at 'internal error: entered unreachable code: symbol/layout `8.IdentId(8)` ProcLayout { arguments: [Struct([]), LambdaSet(LambdaSet { set: [(`8.IdentId(8)`, [Builtin(Int(I64))])], representation: Struct([Builtin(Int(I64))]) })], result: Builtin(Int(I64)) } combo must be in DeclarationToIndex', compiler/mono/src/borrow.rs:227:9

view this post on Zulip jan kili (Jan 07 2022 at 05:33):

Changed lines:

six = (doubleBind 3) {}

vs.

doubleThree = doubleBind 3
six = doubleThree {}

(I've removed roc/examples/cli/platform boilerplate for succinctness)

view this post on Zulip jan kili (Jan 07 2022 at 05:34):

Is there an obvious reason that defining doubleThree causes a panic? roc check is clean on both, btw.

view this post on Zulip Brian Carroll (Jan 07 2022 at 06:52):

That looks like a compiler bug. The panic is in a file related to refcount insertion. That phase comes after type checking, so wouldn't show up in roc check.

view this post on Zulip jan kili (Jan 07 2022 at 06:52):

Thanks! I'll report it and temporarily modify my code to use an anonymous binding/closure :)

view this post on Zulip Brian Carroll (Jan 07 2022 at 06:53):

Great!

view this post on Zulip jan kili (Jan 07 2022 at 06:54):

That's a relief - I was worried that I'd messed up some great-grandchild binding in my confusing code... but by the time I boiled it down to the minimal reproduction above I was half-sure that something fishy was going on.

view this post on Zulip jan kili (Jan 07 2022 at 06:58):

https://github.com/rtfeldman/roc/issues/2322

view this post on Zulip David Rojas Camaggi (Jan 10 2022 at 01:52):

HI all, I am trying to set up my m1 mac for development with nix (using rosetta. i.e. platform is still x86_64). I am getting the following error

CMake Error at /nix/store/gxqi9sjvvwmf86qx075alg376x32s0zc-llvm-7.1.0-dev/lib/cmake/llvm/TableGen.cmake:14 (message):
LLVM_TABLEGEN_EXE not set
Call Stack (most recent call first):
include/clang/Driver/CMakeLists.txt:2 (tablegen)

Also tried with UTM and nix-shell also fails on aarch64 (different error), next week I will try another VM on x86 which would be slower but perhaps easier to set up.

I wonder if anyone has experience to share on M1 macs with nix (macos) or nixos.

view this post on Zulip Brendan Hansknecht (Jan 10 2022 at 03:17):

I use an m1 mac with nix. No rosetta

view this post on Zulip Brendan Hansknecht (Jan 10 2022 at 03:17):

Tends to just work

view this post on Zulip Brendan Hansknecht (Jan 10 2022 at 03:17):

Though has some limitations were we don't fully support arm. Not a problem for the main llvm backend.

view this post on Zulip David Rojas Camaggi (Jan 10 2022 at 03:47):

something must be off on my setup, this is what I get with system = aarch64-darwin -> " >...libredirect.dylib' (mach-o file, but is an incompatible architecture (have 'arm64', need 'arm64e'))"

view this post on Zulip Brendan Hansknecht (Jan 10 2022 at 04:29):

I have never seen that, when does it come up?

view this post on Zulip Brendan Hansknecht (Jan 10 2022 at 04:29):

Also, my setup may be leaky (i.e, I also have rust outside of nix and maybe zig), which may fix potential nix issues

view this post on Zulip David Rojas Camaggi (Jan 10 2022 at 05:38):

found it was OpenAL (audio fw specific to macos), not sure why yet but commenting it out allows me to run a shell

view this post on Zulip David Rojas Camaggi (Jan 10 2022 at 05:41):

doing that on x86 system, but that arm64 thing is from when I was trying aarch64-darwin

view this post on Zulip Lucas Rosa (Jan 11 2022 at 16:34):

I use the M1 Max and no nix

view this post on Zulip jan kili (Jan 13 2022 at 06:48):

How can I write a function that accepts a tag argument that could be either an A tag or a B tag? I tried this, but it doesn't work:

» a : [ A Str ]
… a = A "A"
… f : [ A Str, B Str ] -> Str
… f = \x ->
…     when x is
…         A y -> y
…         B y -> y
… f a

── TYPE MISMATCH ───────────────────────────────────────────────────────────────

The 1st argument to f is not what I expect:

11│      f a
           ^

This a value is a:

    [ A Str ]

But f needs the 1st argument to be:

    [ A Str, B Str ]

Tip: Looks like a closed tag union does not have the B tag.

Tip: Closed tag unions can't grow, because that might change the size
in memory. Can you use an open tag union?

view this post on Zulip Brian Carroll (Jan 13 2022 at 06:56):

Yeah I've run into this kind of thing as well. It's because of the language supporting open tag unions. So in theory A Str could be part of any other union besides this one. Longer term I imagine we'll be able to figure it out, I'm not sure. But we don't right now.
I have found a type annotation works in this kind of situation. If you give a name to your union like AorB : [A Str, B Str] and then give a a type annotation like a : AorB

view this post on Zulip Brian Carroll (Jan 13 2022 at 06:58):

Or I suppose you could probably type it out again rather than naming it! But you'll probably want to name it anyway.

view this post on Zulip jan kili (Jan 13 2022 at 06:59):

Interesting, so now I notice that the inferred type for a = A "A" is [ A Str ]*

view this post on Zulip jan kili (Jan 13 2022 at 06:59):

This is confusing to me, because how could a ever accumulate additional tags in its union? It will only ever be that A tag.

view this post on Zulip Brian Carroll (Jan 13 2022 at 07:09):

Yeah I agree and I suspect that it's more of a bug than a feature. But I don't work on that part of the compiler so I'm not 100% sure!

view this post on Zulip jan kili (Jan 13 2022 at 07:10):

Is the real meaning more like "a can be used anywhere a tag union matches this pattern: [ A Str ]*"?

view this post on Zulip jan kili (Jan 13 2022 at 07:12):

I was initially interpreting its inferred type as saying "a is a tag could be A Str or something else"

view this post on Zulip jan kili (Jan 13 2022 at 07:12):

That's what I gathered from this part of the tutorial:

If you have a closed union, that means it has all the tags it ever will, and can't accumulate more.
If you have an open union, that means it can accumulate more tags through conditional branches.

view this post on Zulip Brian Carroll (Jan 13 2022 at 07:12):

Hold on, that's not the type of a! There's no *

view this post on Zulip Brian Carroll (Jan 13 2022 at 07:13):

In your example code

view this post on Zulip jan kili (Jan 13 2022 at 07:13):

True, but in the REPL if I drop my manual annotation, I get this:

  The rockin’ roc repl
────────────────────────

Enter an expression, or :help, or :exit/:q.

» a = A "A"
… a

A "A" : [ A Str ]*

»

view this post on Zulip Brian Carroll (Jan 13 2022 at 07:13):

So it's a closed union that says a can only be A Str and never any other tag. So that's a different type.

view this post on Zulip jan kili (Jan 13 2022 at 07:13):

The "inferred" type

view this post on Zulip Brian Carroll (Jan 13 2022 at 07:13):

yes but your two examples have different types for the same expression

view this post on Zulip Brian Carroll (Jan 13 2022 at 07:15):

The inferred type will have a * but if you annotate it without one you are telling the compiler you explicitly do not want any other tag to be a valid part of the type of a.

view this post on Zulip jan kili (Jan 13 2022 at 07:15):

I see, so basically if a function can handle multiple tags, it's illegal to call it with an input that can't be all of those tags.

view this post on Zulip jan kili (Jan 13 2022 at 07:17):

i.e. if I have an HTTP response that is somehow guaranteed to be a 404, I can't pass that to a function that processes both 200 and 404 responses?

view this post on Zulip Brian Carroll (Jan 13 2022 at 07:17):

That very much depends on the types they have!

view this post on Zulip Brian Carroll (Jan 13 2022 at 07:18):

There are lots of ways to represent HTTP responses in the type system

view this post on Zulip Brian Carroll (Jan 13 2022 at 07:19):

Do you still get this error in the repl case with the inferred type?

view this post on Zulip jan kili (Jan 13 2022 at 07:19):

No, I actually get a panic :laughing:

view this post on Zulip jan kili (Jan 13 2022 at 07:20):

But that's probably irrelevant https://github.com/rtfeldman/roc/issues/2344

view this post on Zulip Brian Carroll (Jan 13 2022 at 07:20):

:laughing:

view this post on Zulip jan kili (Jan 13 2022 at 07:20):

Could you please give me an example of a situation where I would want to manually annotate a def as being a closed tag union instead of an open one?

view this post on Zulip jan kili (Jan 13 2022 at 07:20):

a : [ A Str ]
a = A "A"

vs.

a : [ A Str ]*
a = A "A"

view this post on Zulip jan kili (Jan 13 2022 at 07:21):

The bottom one seems objectively better, if the top one can't be passed to functions that accept other tags.

view this post on Zulip jan kili (Jan 13 2022 at 07:22):

I ask because I'm still confused what the distinction is. I get why functions would accept closed vs. open, but I don't get how a def can BE closed or open.

view this post on Zulip Brian Carroll (Jan 13 2022 at 07:22):

I don't know, I didn't design this feature, I was just trying to help with your specific error but you probably want to talk to someone who was involved in designing it

view this post on Zulip jan kili (Jan 13 2022 at 07:22):

:) Makes sense, thanks!

view this post on Zulip jan kili (Jan 13 2022 at 07:23):

I'll open a new topic for this, since you helped me figure out the silly thing.

view this post on Zulip jan kili (Jan 16 2022 at 08:17):

I modified the example CLI platform to use Rust's print instead of println, and now I'm successfully writing a lot of Rust-based prints to stdout (with a \r between each, so that the line overwrites itself)! However, after ~47,000 consecutive (very fast) writes to stdout, I'm getting a Segmentation fault: 11. Since these writes are generated by recursive _ <- await ... calls, is this an expected "stack overflow"-type problem with having too many callbacks? Is there a better way to do a lot of I/O tasks without causing such a segfault? My instinct is to replace the recursion with a while loop, but that doesn't exist in Roc.

view this post on Zulip jan kili (Jan 16 2022 at 08:25):

The only way I can think to get more writes out of this program would be to wrap the Roc main function in a Rust while loop at the platform level (and make the Roc main function responsible for only one write), but I don't know enough about platforms to know if that would somehow break the platform/application contract.

view this post on Zulip jan kili (Jan 16 2022 at 08:31):

The context for this I/O use case is that I'm experimenting with how one might use Roc to do ASCII animation for things like CLI loading spinners or simple CLI games (Snake? Space Invaders?) :smile:

view this post on Zulip Brian Carroll (Jan 16 2022 at 11:25):

I can help with one piece of this: Getting the compiler to generate while loops.
Any function that is tail-recursive will be automatically transformed into a while loop. If you're not familiar with that concept, here's an article that explains it: https://www.geeksforgeeks.org/tail-recursion/. Normally you need to refactor your code so that any value that's preserved from one iteration to the next becomes an argument of the recursive call. Those extra arguments usually make the function ugly to use from the outside world, so you end up wrapping it in another function to make it nicer.

view this post on Zulip jan kili (Jan 16 2022 at 12:44):

Ah, that's super useful! Does that only apply to functions provided to the platform, or all of them?

view this post on Zulip jan kili (Jan 16 2022 at 13:33):

@Brian Carroll Would this module get the while loop optimization? It seems like it might, as it is still running and hasn't crashed yet :smiley:

#!/usr/bin/env roc

app "example"
    packages { pf: "./roc/examples/cli/platform" }
    imports [ pf.Stdout.{ line }, pf.Task.{ await } ]
    provides [ main ] to pf

main =
    _ <- await (line "")
    tick 1000000000000

tick = \count ->
    if count == 0 then
        line "Done!"
    else
        # _ <- await (line (Num.toStr count))
        tick (count - 1)

view this post on Zulip Brian Carroll (Jan 16 2022 at 13:42):

Nope, it's any function that calls itself and immediately returns the result. This is an optimisation that is implemented in pretty much every functional language. It's the standard trick for doing loops without mutation. I think it was figured out in the 70s, like everything else! It's called tail-call optimisation or tail-call elimination.

view this post on Zulip Brian Carroll (Jan 16 2022 at 13:43):

I had lots of fun learning to use this when I discovered it!

view this post on Zulip Folkert de Vries (Jan 16 2022 at 13:52):

eh, in the above case tick will be TCO'd

view this post on Zulip jan kili (Jan 16 2022 at 14:15):

Would uncommenting the await change that?

view this post on Zulip Folkert de Vries (Jan 16 2022 at 14:18):

today, probably yes

view this post on Zulip Folkert de Vries (Jan 16 2022 at 14:18):

but LLVM may be able to turn the recursion back into a loop after some inlining

view this post on Zulip jan kili (Jan 16 2022 at 14:50):

I see! Thanks. So then... is it impossible today to avoid a stack overflow when infinitely-repeating an I/O cycle?

view this post on Zulip jan kili (Jan 16 2022 at 14:57):

(I'm glad there's a path to clean TCO for I/O, though!)

view this post on Zulip Folkert de Vries (Jan 16 2022 at 20:30):

This is actually an interesting question. So say we start with something of this form

tick = \count ->
    if count == 0 then
        Effect.putLine "done"

    else
        Effect.await (Effect.putLine "step") \{} -> tick (count - 1)

Where Effect a : [ @Effect (World -> { a, world: World } ) ] and

Effect.await : Effect a, (a -> Effect b) -> Effect b 
Effect.await = \@Effect thunk, toEffect -> 
    @Effect \world1 ->
        { a, world: world2 } = thunk world1

        @Effect thunk2 = toEffect a

        thunk2 world2

Inlining gives

tick = \count ->
    if count == 0 then
        Effect.putLine "done"

    else
        @Effect thunk = Effect.putLine "step" 
        toEffect = \{} -> tick (count - 1)

        @Effect \world1 ->
            { a, world: world2 } = thunk world1

            @Effect thunk2 = toEffect a

            thunk2 world2

The @Effect wrapper melts away

tick = \count ->
    if count == 0 then
        Effect.putLine "done"

    else
        thunk = Effect.putLine "step" 
        toEffect = \{} -> tick (count - 1)

        \world1 ->
            { a, world: world2 } = thunk world1

            thunk2 = toEffect a

            thunk2 world2

We can clean this up slightly

tick = \count ->
    if count == 0 then
        Effect.putLine "done"

    else
        thunk = Effect.putLine "step" 
        toEffect = \{} -> tick (count - 1)

        \world1 ->
            { a, world: world2 } = thunk world1

            (toEffect a) world2

In this case we can inline toEffect, because the data dependency on world2 ensures correct evaluation order
Also we can move thunk into the closure and inline it (this does not happen today, but it's semantically valid)

tick : I64 -> (World -> { a: {}, world : World })
tick = \count ->
    if count == 0 then
        Effect.putLine "done"

    else
        \world1 ->
            { a: _, world: world2 } = (Effect.putLine "step") world1

            (tick (count - 1)) world2

now we lift functions to the toplevel, and run into issues with closures

helper \world1, { count } ->
    { a: _, world: world2 } = (Effect.putLine "step") world1

    (tick (count - 1)) world2

tick : I64 -> (World -> { a: {}, world : World })
tick = \count ->
    if count == 0 then
        Effect.putLine "done"

    else
        helper ??? { count }

we need to complete the closure conversion

helper : World, { count : I64 } -> { a: {}, world : World }
helper \world1, { count } ->
    { a: _, world: world2 } = (Effect.putLine "step") world1

    when tick (count - 1) is    
        C1 { msg } -> (Effect.putLine msg) world2
        C2 { count } -> helper world2 { count }

tick : I64 -> [ C1 Effect.putLine { msg: Str }, C2 helper { count: I64 } ]
tick = \count ->
    if count == 0 then
        C1 { msg: "done" }

    else
        C2 { count }

and now helper can be TCO'd.

view this post on Zulip Folkert de Vries (Jan 16 2022 at 20:31):

given that we can do this with some simple rewriting, it seems plausible that LLVM could already figure this out today

view this post on Zulip Folkert de Vries (Jan 16 2022 at 20:34):

indeed, for this example the LLVM gets there

  %call1.i.i = tail call fastcc %str.RocStr @"#UserApp_tick_6cc39a125db7a4f2ba7ee17ffefa9ff1fe97baed9c849631614587aef96caa15"(i64 %operation_result.i.i.i)
  ret %str.RocStr %call1.i.i

view this post on Zulip jan kili (Jan 16 2022 at 21:18):

🤯

view this post on Zulip jan kili (Jan 16 2022 at 21:19):

:bow:

view this post on Zulip jan kili (Jan 16 2022 at 21:28):

How does tick not need to call helper?
How is its annotation (tick : I64 -> [ C1 Effect.putLine { msg: Str }, C2 helper { count: I64 } ]) legal if Effect.putLine and helper are functions?
Are the functions called implicitly or something?

view this post on Zulip Folkert de Vries (Jan 16 2022 at 21:38):

trying to figure out how to explain this, but that's kind of the idea yes

view this post on Zulip Folkert de Vries (Jan 16 2022 at 21:45):

We're missing main here

main : Effect {}
main = tick 5

Based on the return type for tick, this should be

main : [ C1 Effect.putLine { msg: Str }, C2 helper { count: I64 } ]
main = tick 5

This is the main function we expose. What it returns is really a suspended computation, or a recipe for a computation. We also expose an evaluator for this recipe. Intuitively

cheatyActualMain : Effect a -> a 
cheatyActualMain = \effect -> 
    @Effect thunk = effect

    thunk world

The closure transform turns that into (we're pretending here that cheatyActualMain main is called:

cheatyActualMain : [ C1 Effect.putLine { msg: Str }, C2 helper { count: I64 } ] -> {}
cheatyActualMain = \closure -> 
    when closure is
        C1 { msg } -> (Effect.putLine msg) world
        C2 { count } -> helper world { count }

view this post on Zulip jan kili (Jan 16 2022 at 21:47):

Where is World defined? (I've never heard of "worlds" in Roc before.)

view this post on Zulip Folkert de Vries (Jan 16 2022 at 21:49):

it's something I stole from haskell real quick to make sure the ordering of operations is fixed

view this post on Zulip Folkert de Vries (Jan 16 2022 at 21:49):

you could say World : {}

view this post on Zulip Folkert de Vries (Jan 16 2022 at 21:49):

haskell's IO monad is defined in this way

view this post on Zulip jan kili (Jan 16 2022 at 21:50):

How does Effect a unify with [ C1 Effect.putLine { msg: Str }, C2 helper { count: I64 } ]? (I may be using the world "unify" incorrectly here, but I don't see how cheatyActualMain can accept main as its argument.

view this post on Zulip Folkert de Vries (Jan 16 2022 at 21:50):

where IO a : (RealWorld -> (a, RealWorld)

view this post on Zulip Folkert de Vries (Jan 16 2022 at 21:51):

right, so they don't unify but they are related in this case

view this post on Zulip Folkert de Vries (Jan 16 2022 at 21:51):

in e.g. elm we think of function types as just a -> b

view this post on Zulip Folkert de Vries (Jan 16 2022 at 21:52):

but, we extend that with an extra piece of information: what values (and with which types) are captured by the function

view this post on Zulip Folkert de Vries (Jan 16 2022 at 21:53):

So given

identity = \x -> x

where elm would say

identity : a -> a

we under the hood say

identity : a [ C identity {} ] -> a

view this post on Zulip jan kili (Jan 16 2022 at 21:54):

Whoa! So is [ C1 Effect.putLine { msg: Str }, C2 helper { count: I64 } ] an annotation for only under-the-hood or is it also legal above-the-hood?

view this post on Zulip Folkert de Vries (Jan 16 2022 at 21:54):

and more interestingly

f = \x -> Str.concat x y

(note, y is not bound within f, it is a free variable, and captured by this closure)

f : Str [ C f { y : Str } ] -> Str

view this post on Zulip Folkert de Vries (Jan 16 2022 at 21:54):

the closure part is under-the-hood entirely

view this post on Zulip jan kili (Jan 16 2022 at 21:54):

I'm wondering whether I can stitch these code snippets into a module and run it on ./roc/examples/cli/platform

view this post on Zulip Folkert de Vries (Jan 16 2022 at 21:56):

in any case, to bring this together, we eliminate function values, and replace them by their captured environment. So main : Effect a really has a function type main : World [ some things ] -> { a, World }, and that function value we represent by the closure tag union

view this post on Zulip Folkert de Vries (Jan 16 2022 at 21:58):

and then by doing some bookkeeping we can later know how to evaluate a closure value: simply match on all possible functions that it could be and pass along the arguments

view this post on Zulip jan kili (Jan 16 2022 at 22:09):

Are these tricks possible in a simple application outside of its platform? Above the platform/application boundary?

view this post on Zulip jan kili (Jan 16 2022 at 22:10):

For example, using the examples/cli/platform as-is?

view this post on Zulip Folkert de Vries (Jan 16 2022 at 22:10):

not in user code, because Effect is made with a private tag

view this post on Zulip Folkert de Vries (Jan 16 2022 at 22:10):

so you cannot unpack it or manually make an Effect from a function

view this post on Zulip jan kili (Jan 16 2022 at 22:16):

Ah, I see. Does that mean that today there's no platform-agnostic way to avoid a stack overflow when infinitely-repeating an I/O cycle?

view this post on Zulip Folkert de Vries (Jan 16 2022 at 22:17):

there is no guaranteed way

view this post on Zulip jan kili (Jan 16 2022 at 22:17):

Platforms have to explicitly support any infinite loops required for servers / games / long-running processes?

view this post on Zulip Folkert de Vries (Jan 16 2022 at 22:17):

but with --optimize tail optimization already happens

view this post on Zulip Folkert de Vries (Jan 16 2022 at 22:18):

in these cases

view this post on Zulip Folkert de Vries (Jan 16 2022 at 22:19):

I'd like to add Effect.forever : Effect a -> Effect b for that

view this post on Zulip jan kili (Jan 16 2022 at 22:22):

Thank you for all this info!

view this post on Zulip jan kili (Jan 16 2022 at 22:23):

I'm disappointed that my pure-Roc CLI-based ASCII game hopes must be put on hold, but I'm hopeful it'll get support in the future :)

view this post on Zulip Folkert de Vries (Jan 16 2022 at 22:23):

did you run into stack issues?

view this post on Zulip jan kili (Jan 16 2022 at 22:23):

Yeah, I got a segfault after 47k frames

view this post on Zulip Folkert de Vries (Jan 16 2022 at 22:23):

ah, ok

view this post on Zulip Folkert de Vries (Jan 16 2022 at 22:23):

you did use --optimize?

view this post on Zulip jan kili (Jan 16 2022 at 22:24):

I didn't! What command is that a flag for?

view this post on Zulip Folkert de Vries (Jan 16 2022 at 22:24):

you can do cargo run -- --optimize foo/bar/Baz.roc

view this post on Zulip jan kili (Jan 16 2022 at 22:24):

Ooh, I'll try

view this post on Zulip jan kili (Jan 16 2022 at 22:25):

And that might work with a mid-tick _ <- await?

view this post on Zulip Folkert de Vries (Jan 16 2022 at 22:25):

certainly worth a try

view this post on Zulip jan kili (Jan 16 2022 at 22:48):

gogogo.gif

view this post on Zulip Folkert de Vries (Jan 16 2022 at 22:49):

nice!

view this post on Zulip Folkert de Vries (Jan 16 2022 at 22:49):

so yeah we should figure out how to also make this work in non-optimized modes

view this post on Zulip jan kili (Jan 16 2022 at 22:50):

Am I doing something silly? Yes, I'm running unoptimized code!

view this post on Zulip jan kili (Jan 16 2022 at 22:50):

Space Invaders, here I come.

view this post on Zulip jan kili (Jan 16 2022 at 22:56):

Thank you!

view this post on Zulip jan kili (Jan 16 2022 at 22:58):

(Side note, my mac went to sleep twice during the one minute I was running that infinite sleepless loop :joy:)

view this post on Zulip jan kili (Jan 16 2022 at 22:59):

(I think I might need to add a sleep function to the platform's API)

view this post on Zulip Folkert de Vries (Jan 16 2022 at 23:00):

really, it can go to sleep during busy-waiting loops?

view this post on Zulip Pit Capitain (Jan 17 2022 at 07:17):

Thank you both for this really interesting discussion :smile:

view this post on Zulip Brian Carroll (Jan 17 2022 at 10:24):

Yeah, interesting stuff!

view this post on Zulip Brian Carroll (Jan 17 2022 at 10:25):

Great we can do this as well. Having a main loop with I/O inside it will be useful in all sorts of places!

view this post on Zulip Richard Feldman (Jan 17 2022 at 17:28):

I wonder if https://github.com/rtfeldman/roc/issues/1778 would still be reproducible with --optimize :thinking:

view this post on Zulip Folkert de Vries (Jan 17 2022 at 18:05):

I think the inliner is not able to make the same thing happen there. We definitely tried it with --optimize

view this post on Zulip Folkert de Vries (Jan 19 2022 at 16:23):

define internal fastcc {} @Effect_forever_inner_fb5e512425fc9449316ec95969ebe71e2d576dbab833d61e2a5b9330fd70ee2({} %"5", { { %str.RocStr } } %"#arg_closure") {
entry:
  br label %tailrecurse

tailrecurse:                                      ; preds = %tailrecurse, %entry
  %"5.tr" = phi {} [ %"5", %entry ], [ zeroinitializer, %tailrecurse ]
  %"#arg_closure.tr" = phi { { %str.RocStr } } [ %"#arg_closure", %entry ], [ %call1, %tailrecurse ]
  %struct_field_access_record_0 = extractvalue { { %str.RocStr } } %"#arg_closure.tr", 0
  tail call fastcc void @"#Attr_#inc_2"({ %str.RocStr } %struct_field_access_record_0, i64 1)
  tail call fastcc void @"#Attr_#dec_3"({ { %str.RocStr } } %"#arg_closure.tr")
  tail call fastcc void @"#Attr_#inc_2"({ %str.RocStr } %struct_field_access_record_0, i64 1)
  %call = tail call fastcc {} @Effect_effect_closure_putLine_9d9f29527a6be626a8f5985b26e19b237b44872b03631811df4416fc1713178({} zeroinitializer, { %str.RocStr } %struct_field_access_record_0)
  %call1 = tail call fastcc { { %str.RocStr } } @Effect_forever_67abdd721024f0ff4eb3f4c2fc13bc5bad42db7851d456d88d203d15aaa450({ %str.RocStr } %struct_field_access_record_0)
  br label %tailrecurse
}

it's beautiful

view this post on Zulip Folkert de Vries (Jan 19 2022 at 16:24):

This is an Effect.forever (used as e.g. Effect.forever (Effect.putLine "hello world") to print that line forever) and llvm turns it into a loop

view this post on Zulip Folkert de Vries (Jan 19 2022 at 16:26):

still needs some cleanup, and then maybe some variations that could iterate while some condition is true

view this post on Zulip jan kili (Jan 19 2022 at 16:28):

Nice! Is this for use in appcode or platformcode?

view this post on Zulip Folkert de Vries (Jan 19 2022 at 16:30):

a platform author could now expose Task.forever building upon this function

view this post on Zulip Folkert de Vries (Jan 19 2022 at 16:30):

so, both kinda

view this post on Zulip jan kili (Jan 19 2022 at 16:31):

That's super useful.

view this post on Zulip Richard Feldman (Jan 19 2022 at 17:28):

wow, fantastic!!! :heart_eyes:

this may end up becoming one of the most commonly used functions among all Roc programs!

view this post on Zulip Lucas Rosa (Jan 19 2022 at 19:53):

omg! I wanted this for an event loop when I was trying to wrap SDL in a platform

view this post on Zulip Lucas Rosa (Jan 19 2022 at 19:53):

this is very cool!

view this post on Zulip Folkert de Vries (Jan 19 2022 at 21:51):

This now also works

main : Task.Task {} []
main =
    Task.loop 0 looper

looper = \n ->
    if n < 10 then
        s = Num.toStr n

        {} <- Task.after (Task.putLine "Iteration: \(s)")

        Task.succeed (Step (n + 1))

    else
        Task.succeed (Done {})

view this post on Zulip Folkert de Vries (Jan 19 2022 at 22:00):

plus we get

forever : Task val err -> Task * err
forever = \task ->
    helper = \{} ->
        task
            |> Effect.map \res ->
                when res is
                    Ok _ -> Step {}
                    Err e -> Done (Err e)

    Effect.loop {} helper

i.e. a forever on tasks that terminates when a task fails

view this post on Zulip jan kili (Jan 19 2022 at 22:41):

Yesss

view this post on Zulip jan kili (Jan 19 2022 at 22:42):

Are you planning to add any of these examples to examples/?

view this post on Zulip jan kili (Jan 19 2022 at 22:43):

This feature is invaluable to web servers, games, etc! Thank you :D

view this post on Zulip Folkert de Vries (Jan 19 2022 at 22:43):

the loop and forever task functions are added to the benchmarks and cli platforms in my PRs

view this post on Zulip Folkert de Vries (Jan 19 2022 at 22:44):

no usage examples yet though

view this post on Zulip jan kili (Jan 19 2022 at 22:45):

I might add some usage examples (unless you want to)

view this post on Zulip jan kili (Jan 19 2022 at 22:46):

to give examples/cli/Echo.roc some friends

view this post on Zulip Lucas Rosa (Jan 19 2022 at 23:44):

this does make building a REPL in roc possible now

view this post on Zulip Lucas Rosa (Jan 19 2022 at 23:44):

well I should say easier*

view this post on Zulip jan kili (Feb 13 2022 at 06:46):

Should this cause an Eldritch horror to be unleashed on my REPL? :scared:

x : F32
x = 1.5
x * Num.toFloat 4

view this post on Zulip jan kili (Feb 13 2022 at 06:54):

I'm thinking no: https://github.com/rtfeldman/roc/issues/2476 :laughing:

view this post on Zulip jan kili (Mar 12 2022 at 11:24):

I'm back with more tag union panics! :laughing:

» x : [ Y U8 ]*
… x = Y 3
… x
thread '<unnamed>' panicked at 'invalid content in tag union variable: (114, RigidVar(SubsIndex<roc_module::ident::Lowercase>(0)))', compiler/mono/src/layout.rs:2002:23
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
^C

Am I doing something silly?

view this post on Zulip jan kili (Mar 12 2022 at 11:24):

(a closed tag union works fine here)

» x : [ Y U8 ]
… x = Y 3
… x

Y 3 : [ Y U8 ]

view this post on Zulip jan kili (Mar 12 2022 at 11:54):

I've got a second one! The silliness continues?

» wrap = \value -> Tag value
… wrap

<function> : a -> [ Tag a ]*

» wrap = \value -> Tag value
… wrapIt = wrap
… wrapIt

<function> : a -> [ Tag a ]*

» wrap = \value -> Tag value
… wrap 42

Tag 42 : [ Tag (Num *) ]*

» wrap = \value -> Tag value
… wrapIt = wrap
… wrapIt 42
thread 'main' panicked at 'Roc failed with message: "UnresolvedTypeVar compiler/mono/src/ir.rs line 6842"', repl_cli/src/lib.rs:137:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

view this post on Zulip Ayaz Hafiz (Mar 12 2022 at 13:40):

Could you file bugs for these? The second one is known I think but would be good to have a record of both!

view this post on Zulip jan kili (Jul 03 2022 at 04:43):

Silliness detected? https://github.com/rtfeldman/roc/issues/3377

view this post on Zulip jan kili (Jul 03 2022 at 04:53):

(I'm causing a segfault by substituting [0, 1, 2] with List.range 0 3)

view this post on Zulip jan kili (Jul 03 2022 at 05:22):

I've encountered a second problem! Am I missing something about this syntax, because this seems like a reasonable recursion pattern to me:

» a = \b ->
…     c = \d ->
…         if d >= 10 then d else c (d+b)
…     c 0
… a 6
thread 'main' panicked at 'internal error: entered unreachable code: symbol/layout `#UserApp.c` ProcLayout { arguments: [Builtin(Int(I64))], result: Builtin(Int(I64)) } combo must be in DeclarationToIndex', crates/compiler/mono/src/borrow.rs:165:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
[jan@framey roc]$

view this post on Zulip jan kili (Jul 03 2022 at 05:23):

(btw, that inner function is fine by itself)

» c = \d ->
…     if d >= 10 then d else c (d+3)
… c 0

12 : Num *

»

view this post on Zulip jan kili (Jul 03 2022 at 05:25):

I'll go ahead and report that second "internal error" problem as an issue, too.

view this post on Zulip jan kili (Jul 03 2022 at 05:26):

I expect that I'm exhibiting minimal silliness here today. Sorry for being boring!

view this post on Zulip jan kili (Jul 03 2022 at 05:31):

https://github.com/rtfeldman/roc/issues/3378

view this post on Zulip jan kili (Jul 11 2022 at 16:41):

Ummm what am I missing here?

main =
    deck = myDeck
    {card} = dealMe deck
    rank =
        when card.rank is
            Ace -> "Ace"
            King -> "King"
            Queen -> "Queen"
            Jack -> "Jack"
    suit =
        when card.suit is
            Club -> "Clubs"
            Diamond -> "Diamonds"
            Heart -> "Hearts"
            Spade -> "Spades"
    "My card is the \(card.rank) of \(card.suit)!\n"
── MISSING EXPRESSION ─ ..._roc/domain-modeling-in-roc/step_2__card_game_A.roc ─

I am partway through parsing a definition, but I got stuck here:

 4│      provides [main] to pf
...
23│  main =
24│      deck = myDeck
25│      {card} = dealMe deck
26│      rank =
27│          when card.rank is
                              ^

I was expecting to see an expression like 42 or "hello".

:thinking:

view this post on Zulip Brendan Hansknecht (Jul 11 2022 at 16:44):

Whitespace bug? That is definitely what it looks like to me.

view this post on Zulip jan kili (Jul 11 2022 at 16:45):

Ooh, I'll check for that

view this post on Zulip Brendan Hansknecht (Jul 11 2022 at 16:46):

Might be worth running roc format and seeing the diff? might fix it?

view this post on Zulip jan kili (Jul 11 2022 at 16:47):

Success!

view this post on Zulip jan kili (Jul 11 2022 at 16:47):

I didn't try the formatter, but I think it was a funky newline.

view this post on Zulip jan kili (Jul 11 2022 at 16:47):

Thank you :)

view this post on Zulip Brendan Hansknecht (Jul 11 2022 at 16:48):

If it seems worth tracking/filing an issue, maybe we can make a better error message or fix the parsing around this.

view this post on Zulip jan kili (Jul 11 2022 at 16:50):

While I have you here, any tips for this?

[jan@framey roc]$ export RUST_BACKTRACE=full
[jan@framey roc]$ cargo run ../domain-modeling-in-roc/step_2__card_game_A.roc
    Finished dev [unoptimized + debuginfo] target(s) in 0.44s
     Running `target/debug/roc ../domain-modeling-in-roc/step_2__card_game_A.roc`
thread '<unnamed>' panicked at 'not yet implemented', crates/compiler/mono/src/ir.rs:2382:23
stack backtrace:
   0:     0x5635ba31fb9d - std::backtrace_rs::backtrace::libunwind::trace::hee598835bc88d35b
                               at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c/library/std/src/../../backtrace/src/backtrace/libunwind.rs:93:5
   1:     0x5635ba31fb9d - std::backtrace_rs::backtrace::trace_unsynchronized::h9cdc730ba5cf5d72
                               at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5
   2:     0x5635ba31fb9d - std::sys_common::backtrace::_print_fmt::h75aeaf7ed30e43fa
                               at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c/library/std/src/sys_common/backtrace.rs:66:5
   3:     0x5635ba31fb9d - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h606862f787600875
                               at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c/library/std/src/sys_common/backtrace.rs:45:22
   4:     0x5635ba34aadc - core::fmt::write::he803f0f418caf762
                               at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c/library/core/src/fmt/mod.rs:1190:17
   5:     0x5635ba319d28 - std::io::Write::write_fmt::h70bc45872f37e7bb
                               at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c/library/std/src/io/mod.rs:1657:15
   6:     0x5635ba321dd7 - std::sys_common::backtrace::_print::h64d038cf8ac3e13e
                               at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c/library/std/src/sys_common/backtrace.rs:48:5
   7:     0x5635ba321dd7 - std::sys_common::backtrace::print::h359300b4a7fccf65
                               at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c/library/std/src/sys_common/backtrace.rs:35:9
   8:     0x5635ba321dd7 - std::panicking::default_hook::{{closure}}::hf51be35e2f510149
                               at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c/library/std/src/panicking.rs:295:22
   9:     0x5635ba321aa0 - std::panicking::default_hook::h03ca0f22e1d2d25e
                               at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c/library/std/src/panicking.rs:314:9
  10:     0x5635ba322529 - std::panicking::rust_panic_with_hook::h3b7380e99b825b63
                               at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c/library/std/src/panicking.rs:698:17
  11:     0x5635ba3221d9 - std::panicking::begin_panic_handler::{{closure}}::h8e849d0710154ce0
                               at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c/library/std/src/panicking.rs:586:13
  12:     0x5635ba320064 - std::sys_common::backtrace::__rust_end_short_backtrace::hedcdaddbd4c46cc5
                               at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c/library/std/src/sys_common/backtrace.rs:138:18
  13:     0x5635ba321f29 - rust_begin_unwind
                               at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c/library/std/src/panicking.rs:584:5
  14:     0x5635b5b4ae83 - core::panicking::panic_fmt::he1bbc7336d49a357
                               at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c/library/core/src/panicking.rs:143:14
  15:     0x5635b5b4ad4d - core::panicking::panic::h4241c5ccea17faca
                               at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c/library/core/src/panicking.rs:48:5
  16:     0x5635b99cc490 - roc_mono::ir::from_can_let::he631a1fd2e7f1db7
                               at /home/jan/_code/_roc/roc/crates/compiler/mono/src/ir.rs:2382:23
  17:     0x5635b9a09970 - roc_mono::ir::from_can::h6c53f19073fb59f4
                               at /home/jan/_code/_roc/roc/crates/compiler/mono/src/ir.rs:5932:33
  18:     0x5635b996e417 - roc_mono::ir::from_can_let::{{closure}}::hb169aff3d0732e09
                               at /home/jan/_code/_roc/roc/crates/compiler/mono/src/ir.rs:2206:25
  19:     0x5635b99769d7 - roc_mono::ir::handle_variable_aliasing::h457631afa9a49d05
                               at /home/jan/_code/_roc/roc/crates/compiler/mono/src/ir.rs:7025:16
  20:     0x5635b99d0e75 - roc_mono::ir::from_can_let::he631a1fd2e7f1db7
                               at /home/jan/_code/_roc/roc/crates/compiler/mono/src/ir.rs:2209:24
  21:     0x5635b9a09970 - roc_mono::ir::from_can::h6c53f19073fb59f4
                               at /home/jan/_code/_roc/roc/crates/compiler/mono/src/ir.rs:5932:33
  22:     0x5635b99d6413 - roc_mono::ir::specialize_external::h014c8ba65786d364
                               at /home/jan/_code/_roc/roc/crates/compiler/mono/src/ir.rs:2988:32
  23:     0x5635b996ebf8 - roc_mono::ir::specialize_variable_help::hc0e86a21717b3946
                               at /home/jan/_code/_roc/roc/crates/compiler/mono/src/ir.rs:3465:23
  24:     0x5635b99dbbf3 - roc_mono::ir::specialize_variable::h0634205863a1b1ec
                               at /home/jan/_code/_roc/roc/crates/compiler/mono/src/ir.rs:3414:5
  25:     0x5635b99d4cb4 - roc_mono::ir::specialize_external_help::he85ecfa478515205
                               at /home/jan/_code/_roc/roc/crates/compiler/mono/src/ir.rs:2767:33
  26:     0x5635b99d4aa2 - roc_mono::ir::specialize_external_specializations::h03afe44495a518a6
                               at /home/jan/_code/_roc/roc/crates/compiler/mono/src/ir.rs:2740:13
  27:     0x5635b99d400e - roc_mono::ir::specialize_all::h38efe702f28bba33
                               at /home/jan/_code/_roc/roc/crates/compiler/mono/src/ir.rs:2673:9
  28:     0x5635b7436e4e - roc_load_internal::file::make_specializations::h624990574ec76565
                               at /home/jan/_code/_roc/roc/crates/compiler/load_internal/src/file.rs:4519:13
  29:     0x5635b743c47b - roc_load_internal::file::run_task::h6036f07fd619b017
                               at /home/jan/_code/_roc/roc/crates/compiler/load_internal/src/file.rs:4996:17
  30:     0x5635b741559a - roc_load_internal::file::worker_task::hebe41c651db0920e
                               at /home/jan/_code/_roc/roc/crates/compiler/load_internal/src/file.rs:1817:34
  31:     0x5635b7440e1a - roc_load_internal::file::load_multi_threaded::{{closure}}::{{closure}}::h16d5eba0a83616fc
                               at /home/jan/_code/_roc/roc/crates/compiler/load_internal/src/file.rs:1659:25
  32:     0x5635b744caf7 - crossbeam_utils::thread::ScopedThreadBuilder::spawn::{{closure}}::ha411c1ac2e878ff5
                               at /home/jan/.cargo/registry/src/github.com-1ecc6299db9ec823/crossbeam-utils-0.8.10/src/thread.rs:438:31
  33:     0x5635b73d3fef - core::ops::function::FnOnce::call_once{{vtable.shim}}::h182bc693cee28e90
                               at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c/library/core/src/ops/function.rs:227:5
  34:     0x5635b740505d - <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once::hee34075471a3830c
                               at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c/library/alloc/src/boxed.rs:1853:9
  35:     0x5635b74eed84 - std::sys_common::backtrace::__rust_begin_short_backtrace::h74784c32857fa8b7
                               at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c/library/std/src/sys_common/backtrace.rs:122:18
  36:     0x5635b74dd8d4 - std::thread::Builder::spawn_unchecked_::{{closure}}::{{closure}}::h54bd13ac090e0e91
                               at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c/library/std/src/thread/mod.rs:498:17
  37:     0x5635b74efaa4 - <core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once::he1cf1df6def34f88
                               at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c/library/core/src/panic/unwind_safe.rs:271:9
  38:     0x5635b74ef26d - std::panicking::try::do_call::h48b63b9234108830
                               at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c/library/std/src/panicking.rs:492:40
  39:     0x5635b74ef49b - __rust_try
  40:     0x5635b74ef1bd - std::panicking::try::hb3ba778589fab460
                               at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c/library/std/src/panicking.rs:456:19
  41:     0x5635b74ec7d4 - std::panic::catch_unwind::h7c5138398b54d137
                               at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c/library/std/src/panic.rs:137:14
  42:     0x5635b74dd6f3 - std::thread::Builder::spawn_unchecked_::{{closure}}::hd3349d142c8673c4
                               at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c/library/std/src/thread/mod.rs:497:30
  43:     0x5635b73d3f0f - core::ops::function::FnOnce::call_once{{vtable.shim}}::h14f5d8c93db30fba
                               at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c/library/core/src/ops/function.rs:227:5
  44:     0x5635ba329d03 - <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once::hf70ac038171e3e1a
                               at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c/library/alloc/src/boxed.rs:1853:9
  45:     0x5635ba329d03 - <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once::he6690128792365ad
                               at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c/library/alloc/src/boxed.rs:1853:9
  46:     0x5635ba329d03 - std::sys::unix::thread::Thread::new::thread_start::ha07928d93d5a5ec9
                               at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c/library/std/src/sys/unix/thread.rs:108:17
  47:     0x7f8513f29d40 - start_thread
  48:     0x7f8513a8703f - __GI___clone
  49:                0x0 - <unknown>
^C
[jan@framey roc]$

view this post on Zulip Brendan Hansknecht (Jul 11 2022 at 16:51):

does it pass roc check?

view this post on Zulip Brendan Hansknecht (Jul 11 2022 at 16:51):

That catches a lot that might crash the compiler.

view this post on Zulip jan kili (Jul 11 2022 at 16:51):

GAH I always forget to go back to checking

view this post on Zulip jan kili (Jul 11 2022 at 16:52):

I do check check check check, then the first time it passes I go straight to run run run run while editing :facepalm:

view this post on Zulip jan kili (Jul 11 2022 at 16:52):

Thanks again, check has my answers :)

view this post on Zulip Richard Feldman (Jul 11 2022 at 16:53):

that's surprising actually - cargo run should do the "check and then only run if there are no errors reported" flow :thinking:

view this post on Zulip Richard Feldman (Jul 11 2022 at 16:53):

so I'm surprised that cargo run ../domain-modeling-in-roc/step_2__card_game_A.roc would report no compile-time errors but cargo run check would!

view this post on Zulip Brendan Hansknecht (Jul 11 2022 at 16:59):

really? I thought cargo run <script> and roc <script> did not run check. That would definitely be useful.

view this post on Zulip Richard Feldman (Jul 11 2022 at 16:59):

so roc foo.roc does this, but roc run foo.roc just runs and doesn't check

view this post on Zulip Brendan Hansknecht (Jul 11 2022 at 16:59):

hmm. Yeah, I don't think that is working

view this post on Zulip Richard Feldman (Jul 11 2022 at 16:59):

so it's the difference between cargo run run and cargo run :big_smile:

view this post on Zulip Brendan Hansknecht (Jul 11 2022 at 17:00):

Or maybe it does part of the check but not all of it...not sure

view this post on Zulip Brendan Hansknecht (Jul 11 2022 at 17:00):

I definitely need to use check still.

view this post on Zulip Richard Feldman (Jul 11 2022 at 17:00):

hm, if you can reproduce an example of it not working right, maybe it's an easy fix!

view this post on Zulip jan kili (Jul 25 2022 at 01:24):

Hello, it's me again, Dr. Help I. M. Crashing :laughing:

view this post on Zulip jan kili (Jul 25 2022 at 01:24):

This behavior seems like it shouldn't be possible, unless there's a bug in the release build process:

[jan@framey ~]$ cd ~/_code/_roc/roc
[jan@framey roc]$
[jan@framey roc]$ nix develop
[jan@framey roc]$
[jan@framey roc]$ cargo run ../project-euler-in-roc/2.roc
    Finished dev [unoptimized + debuginfo] target(s) in 0.46s
     Running `target/debug/roc ../project-euler-in-roc/2.roc`
🔨 Rebuilding host...
4613732
[jan@framey roc]$
[jan@framey roc]$ cargo build --release
    Finished release [optimized] target(s) in 0.48s
[jan@framey roc]$
[jan@framey roc]$ exit
exit
[jan@framey roc]$
[jan@framey roc]$ cd ~/_code/_roc/project-euler-in-roc/
[jan@framey project-euler-in-roc]$
[jan@framey project-euler-in-roc]$ ../roc/target/release/roc 2.roc
🔨 Rebuilding host...
thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 2, kind: NotFound, message: "No such file or directory" }', crates/compiler/build/src/link.rs:360:22
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Any { .. }', crates/cli/src/build.rs:283:46
[jan@framey project-euler-in-roc]$
[jan@framey project-euler-in-roc]$ ../roc/target/release/roc check 2.roc
0 errors and 0 warnings found in 20 ms.
[jan@framey project-euler-in-roc]$
[jan@framey project-euler-in-roc]$ ???

view this post on Zulip jan kili (Jul 25 2022 at 01:25):

It seems to not matter which app I run, the same "yes inside nix develop, no outside it" happens

view this post on Zulip jan kili (Jul 25 2022 at 01:26):

Did I miss a step? (I remembered to check this time! haha)

view this post on Zulip jan kili (Jul 25 2022 at 01:28):

(on Linux, Fedora 36)

view this post on Zulip jan kili (Jul 25 2022 at 01:56):

Oh, and I guess this is additional info + a more concise repro:

[jan@framey roc]$ ./target/release/roc ../project-euler-in-roc/2.roc
🔨 Rebuilding host...
4613732
[jan@framey roc]$
[jan@framey roc]$ exit
exit
[jan@framey roc]$
[jan@framey roc]$ cd ../project-euler-in-roc/
[jan@framey project-euler-in-roc]$
[jan@framey project-euler-in-roc]$ ../roc/target/release/roc 2.roc
🔨 Rebuilding host...
thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 2, kind: NotFound, message: "No such file or directory" }', crates/compiler/build/src/link.rs:360:22
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Any { .. }', crates/cli/src/build.rs:283:46
[jan@framey project-euler-in-roc]$

view this post on Zulip jan kili (Jul 25 2022 at 01:58):

Summary:

view this post on Zulip jan kili (Jul 25 2022 at 01:59):

I thought builds were self-contained, but are they not?

view this post on Zulip Brendan Hansknecht (Jul 25 2022 at 02:45):

Your missing zig on your machine?

view this post on Zulip Brendan Hansknecht (Jul 25 2022 at 02:45):

*line 360 not 310, so clang

view this post on Zulip Brendan Hansknecht (Jul 25 2022 at 02:45):

You can't build the platform

view this post on Zulip Brendan Hansknecht (Jul 25 2022 at 02:46):

If you were to build in nix and then build outside of nix with --precompiled-host=true, it should work.

view this post on Zulip Brendan Hansknecht (Jul 25 2022 at 02:48):

We should improve those error messages

view this post on Zulip jan kili (Jul 25 2022 at 02:50):

:check: Wow, that was fast.

[jan@framey project-euler-in-roc]$ ../roc/target/release/roc 2.roc --precompiled-host=true
4613732
[jan@framey project-euler-in-roc]$

view this post on Zulip jan kili (Jul 25 2022 at 02:51):

I didn't know about that flag, and I assumed a Roc build could compile platforms/hosts without any system dependencies!

view this post on Zulip Brendan Hansknecht (Jul 25 2022 at 02:52):

The host is still in another language, so that has all the dependencies that other language brings in. Long term, you should be able to just download the package as a precompiled host. Once that is the norm, all the host building shouldn't matter to anyone except platform authors.

view this post on Zulip jan kili (Jul 25 2022 at 02:55):

Nice! So right now, the --precompiled-host=true tells the Roc executable to look in the platform dir for a platform executable?

view this post on Zulip jan kili (Jul 25 2022 at 02:56):

Should the word "host" be replaced with "platform" in all app-developer-facing messaging?

view this post on Zulip Brendan Hansknecht (Jul 25 2022 at 02:57):

It basically says, trust me, the platform was already compiled and has not changed. Don't spawn the thread that compiles the platform. We will use the existing executable file.

view this post on Zulip Brendan Hansknecht (Jul 25 2022 at 03:00):

And probably to the host vs platform question. It is a terminology thing that has turned into them essentially being used interchangeably (though there is technically a difference). Platform is definitely the term I would expect an app author to see and use.

view this post on Zulip jan kili (Jul 25 2022 at 03:00):

Great! Thank you very much for these great explanations :)

view this post on Zulip jan kili (Jul 25 2022 at 03:02):

This will definitely become part of my workflow:

[jan@framey project-euler-in-roc]$ alias roc='../roc/target/release/roc --precompiled-ho
st=true'
[jan@framey project-euler-in-roc]$ roc 2.roc
4613732
[jan@framey project-euler-in-roc]$

view this post on Zulip jan kili (Jul 25 2022 at 03:08):

Regarding host vs. platform: https://github.com/rtfeldman/roc/issues/3630

view this post on Zulip jan kili (Jul 25 2022 at 03:12):

Regarding panic/error messaging: https://github.com/rtfeldman/roc/issues/3631

view this post on Zulip Brian Carroll (Jul 25 2022 at 04:01):

On terminology: The platform consists of a non-Roc "host" and a Roc API to interface to it.

view this post on Zulip Brian Carroll (Jul 25 2022 at 04:05):

So the message is referring to technically the right thing, but using a term that isn't explained anywhere in the docs yet.

view this post on Zulip Brendan Hansknecht (Jul 25 2022 at 04:10):

Sure, but to a roc app author, they will only ever interact with platforms as a unit, never the host directly. So flags and error messages should generally be catered to that?

view this post on Zulip Brendan Hansknecht (Jul 25 2022 at 04:10):

At least that is my thought

view this post on Zulip Brian Carroll (Jul 25 2022 at 04:13):

I wasn't disagreeing, just explaining to anyone following who didn't know.

view this post on Zulip jan kili (Jul 25 2022 at 04:14):

Nice, does that API include only .roc files?

view this post on Zulip Brian Carroll (Jul 25 2022 at 04:19):

Yes

view this post on Zulip jan kili (Oct 05 2022 at 02:59):

How do I bool?

        |> List.map (\sum ->
            when sum * 2 > rowCount is
                Bool.true -> 1
                _ -> 0)
── SYNTAX PROBLEM ──────────────────────────────────────── day_3_solutions.roc ─

This pattern is malformed:

37│                  Bool.true -> 1
                     ^^^^^^^^^

view this post on Zulip jan kili (Oct 05 2022 at 03:06):

It works as an if ... then ... else ... expression but not a when ... is ... expression

view this post on Zulip jan kili (Oct 05 2022 at 03:06):

I'll just switch it to if/else

view this post on Zulip jan kili (Oct 05 2022 at 03:07):

Dang functional programming... making me forget about good old-fashioned if/else... :angry_cat: :laughing:

view this post on Zulip Richard Feldman (Oct 05 2022 at 03:17):

oh yeah, this is supposed to work exactly the way you tried to write it - it just hasn't been implemened yet :sweat_smile:

view this post on Zulip Richard Feldman (Oct 05 2022 at 03:18):

Foo.bar -> ... should desugar to essentially x if x == Foo.bar -> ...

view this post on Zulip Richard Feldman (Oct 05 2022 at 03:19):

which you can always write by hand, but yes - in the case of booleans specifically, might as well use if! :big_smile:

view this post on Zulip jan kili (Oct 05 2022 at 03:19):

Any hope for [a, b, c] -> ...? :fingers_crossed: :present: :santa:

view this post on Zulip jan kili (Oct 05 2022 at 03:20):

Maybe tuples will alleviate that need

view this post on Zulip Richard Feldman (Oct 05 2022 at 03:23):

yeah there was some discussion on Zulip about that awhile back

view this post on Zulip Richard Feldman (Oct 05 2022 at 03:24):

I think some form of it will turn out to be a good idea!

view this post on Zulip Chris Duncan (Oct 09 2022 at 21:27):

@JanCVanB: In this topic, they show how to pattern match in the way you were looking for.


Last updated: Jul 06 2025 at 12:14 UTC