Stream: beginners

Topic: weird loop error


view this post on Zulip Artur Swiderski (Jan 09 2024 at 18:53):

hi, I am getting following weird error

The andMode value depends on itself through the following chain of
definitions:

    ┌─────┐
    │     andMode
    │     ↓
    │     commandsToHandlers
    │     ↓
    │     commandAnalysis
    │     ↓
    │     recoverConfigFromInput
    └─────┘

────────────────────────────────────────────────────────────────────────────────

it is strange because this loop is exactly what I want to achieve (something perfectly feasible in all languages I know of but Roc)

view this post on Zulip Richard Feldman (Jan 09 2024 at 19:00):

this error should be about something that's only supported in lazy language like Haskell

view this post on Zulip Richard Feldman (Jan 09 2024 at 19:02):

for example, of course this can't work:

x = x

because x can't be defined in terms of itself unless x is a function and it's referring to itself in the body

view this post on Zulip Richard Feldman (Jan 09 2024 at 19:02):

similarly, this can't possibly work:

a = b
b = a

view this post on Zulip Richard Feldman (Jan 09 2024 at 19:03):

or this:

a = b
b = c
c = a

view this post on Zulip Richard Feldman (Jan 09 2024 at 19:04):

so this compile error is saying the code has something like one of these, where in order to complete a = ... the compiler has to already know what a is, which isn't possible

view this post on Zulip Richard Feldman (Jan 09 2024 at 19:05):

lazy languages like Haskell can do this because they automatically wrap all definitions in function calls, so they end up in the "a function can refer to itself in the body" situation every time even though it doesn't look like it syntactically

view this post on Zulip Artur Swiderski (Jan 09 2024 at 19:09):

ok I get that, it happens most likely because the function, which is calling indirectly itself, enters the game as value(handler) and its called in similar fashion as "C" handlers frequently are. ok I will find workaround somehow

view this post on Zulip Artur Swiderski (Jan 09 2024 at 19:12):

if this was "normal" function I think I can do f -> h -> f ? I think I have done that in the past, am I correct ?

view this post on Zulip Richard Feldman (Jan 09 2024 at 19:13):

yeah, that should work fine!

view this post on Zulip Artur Swiderski (Jan 09 2024 at 19:23):

btw. is this possible for Roc in the future to recognize that
a = f(.. , c )
b = g(.. , a )
c = h(.. ,b)
a, b and c are in reality functions so it is perfectly ok to have this structure or this will be always limitation ?

view this post on Zulip Richard Feldman (Jan 09 2024 at 19:28):

so f is returning a function here?

view this post on Zulip Artur Swiderski (Jan 09 2024 at 19:35):

yes all functions , I don't know if I have described correctly (in terms of math annotation) but I hope you get the point

view this post on Zulip Artur Swiderski (Jan 09 2024 at 19:39):

I have got over my problem this time but at some point handlers may be the easiest way to solve some other problems. I could try something different but still intuitively expectation is that is should work

view this post on Zulip Richard Feldman (Jan 09 2024 at 19:54):

ah, so if they're all functions, then I think you should be able to make it work by explicitly wrapping them in lambdas, e.g. if the function returned by f takes 2 argument, then:

a = \arg1, arg2 -> (f ...) arg1 arg2

I think that should work

view this post on Zulip Richard Feldman (Jan 09 2024 at 19:55):

if I remember right, there was some detail that led us to decide we should require explicit lambdas in that situation, but I don't remember the reasoning anymore

view this post on Zulip Artur Swiderski (Jan 09 2024 at 20:58):

ok, I will check if this tip works for me, thx

view this post on Zulip Artur Swiderski (Jan 09 2024 at 23:43):

ok in my case things aren't as simple as I initially presented
https://github.com/salarii/peek/blob/main/Commands.roc
275 #|> Dict.insert "dsdsa" andMode

view this post on Zulip Anton (Jan 10 2024 at 10:16):

Interesting... I can try to look at this today

view this post on Zulip Anton (Jan 10 2024 at 19:24):

I won't make it for today, I should be able to take a look on Friday if no one else is available until then.

view this post on Zulip Anton (Jan 12 2024 at 20:15):

Today's tasks took longer then expected, I should have time tomorrow

view this post on Zulip Anton (Jan 13 2024 at 16:09):

So this is the infinite loop:

view this post on Zulip Anton (Jan 13 2024 at 16:09):

This is the simplified version that creates the same error as your code:

app "helloWorld"
    packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.7.1/Icc3xJoIixF3hCcfXrDwLCu4wQHtNdPyoJkEbkgIElA.tar.br" }
    imports [pf.Stdout]
    provides [main] to pf

main =
    Stdout.line "Hello, World!"

andMode : I64 -> List Str
andMode = \num -> recoverConfigFromInput num

recoverConfigFromInput : I64 -> List Str
recoverConfigFromInput = \num -> commandAnalysis num

commandAnalysis : I64 -> List Str
commandAnalysis = \_num ->
    Dict.keys (commandsToHandlers)

commandsToHandlers : Dict Str ( I64 -> List Str )
commandsToHandlers =
    Dict.empty {}
    |> Dict.insert "dsdsa"  andMode

view this post on Zulip Anton (Jan 13 2024 at 16:10):

Further simplified:

andMode : I64 -> List Str
andMode = \num -> commandAnalysis num

commandAnalysis : I64 -> List Str
commandAnalysis = \_num ->
    Dict.keys (commandsToHandlers)

commandsToHandlers : Dict Str ( I64 -> List Str )
commandsToHandlers =
    Dict.empty {}
    |> Dict.insert "dsdsa"  andMode

view this post on Zulip Anton (Jan 13 2024 at 16:10):

Even further:

andMode : I64 -> List Str
andMode = \num -> Dict.keys (commandsToHandlers)

commandsToHandlers : Dict Str ( I64 -> List Str )
commandsToHandlers =
    Dict.empty {}
    |> Dict.insert "dsdsa"  andMode

view this post on Zulip Anton (Jan 13 2024 at 16:14):

But this code can actually be run:

main = Stdout.line (Inspect.toStr (andMode 0))

andMode : I64 -> List Str
andMode = \num -> Dict.keys (commandsToHandlers)

commandsToHandlers : Dict Str ( I64 -> List Str )
commandsToHandlers =
    Dict.empty {}
    |> Dict.insert "dsdsa"  andMode

view this post on Zulip Anton (Jan 13 2024 at 16:15):

That prints ["dsdsa"]

view this post on Zulip Anton (Jan 13 2024 at 16:16):

Building does still yield the error:
Screenshot_20240113_171612.png

view this post on Zulip Anton (Jan 13 2024 at 16:17):

So the code works because it does not rely on any value of the Dict, only on the keys.

view this post on Zulip Anton (Jan 13 2024 at 16:22):

I'm not sure what we should do about this :thinking:

view this post on Zulip David Dunn (Jan 18 2024 at 20:32):

commandsToHandlers never executes andMode. What does "depends on" (from the error message) mean in this context? I thought it meant "executes", which would lead to the mentioned infinite loop.

view this post on Zulip Brendan Hansknecht (Jan 18 2024 at 20:42):

I think depends on means requires a definition of.


Last updated: Jul 06 2025 at 12:14 UTC