how can a function that has no parameters be defined? from what i can tell from the tutorial, values become functions when either they have parameters, or call other functions. am I misunderstanding something?
It can't. The normal convention is to pass an empty record to the function.
So it still has one argument
interesting
it should be a very rare use case, since Roc functions can't have side effects :big_smile:
Simple example from builtins: https://www.roc-lang.org/builtins/Dict#empty
well, with no side effects, it would basically be useless, but I'm wondering what happens when calling platform functions that do have side effects
maybe something like getting the environment variables
or something simpler, like getting the time
Getting the environment variables or or time actually ends up not hitting this due to needing to await a task. So it would be something like
Task.await Time.now \time -> ...
seems like the reason that function is a task is because of this
I don't follow exactly what you mean.
I don't see any reason for Time.now to return a task on most platforms.
nor why it would receive a callback
Oh, it has to in roc. There is no other option. It is not a pure function. Every I/o primitive in roc has to be wrapped in the effect API.
i see, and the effect API only works with tasks?
can the platform not supply no-argument functions to roc?
Task is built on top of the effect API. It is just used everywhere for convenience of being able to handle errors.
can the platform not supply no-argument functions to roc?
Time.now
would be an example of an effect that takes no arguments. Stdout.line
would be an example of the reverse. 1 input with no result.
ah, i see, i read that code wrong, the function was not an argument to Time.now, but to task.await
Yes, sorry about the confusion.
but, how does Task.await call a function with no arguments?
Effects aren't technically functions. They are more like futures. So Time.now
would actually just be a constant. Eventually, this code will get to builtin effect stuff that the compiler implements internally to connect the platform to the application. I forget the exact function that is call, but it is similar to await and takes an effect and a callback.
This will then call a roc_fx_TimeNow
function that the platform exposes to roc and do what is necessary to wrap that up as an effect.
i see
hmm, are Tags functions? or can they just be called as functions?
A tag name is also a function for generating that tag variant.
Enable you to something like |> List.map Ok
which should wrap all of the elements in a list with the Ok
tag.
i'm guessing |> List.map None
would not work, requiring |> List.map \_ -> None
instead
Correct, if you had a None
variant that takes no args, I think it only gets a constant of the variant rather than a function cause there would be no valid way to generate it with a function.
the convention is that every identifier that starts with an uppercase letter is a tag, right?
Uppercase is a Type in general. So you might see
Result ok err : [Ok ok, Err err]
But you would also see uppercase for a tuple or record:
Tup : (Str, U8)
Person : { height: U32, name: Str }
Oh, I guess uppercase is also used for module names as in List.map
i was a bit confused about this in the repl
» foo = \n -> "hello \(n)"
: Str -> Str
» foo
: Str -> Str
» Bool
Bool : [Bool]
» Bool.true
Bool.true : Bool
you can refer to identifiers with lowercase first letter, but not with uppercase, because they are turned into tags
Yes, all value identifiers are required to start with lower case letters in roc.
except type identifiers
and module identifiers
So, roc will automatically infer types. If you just type an uppercase name into code somewhere, it has to be a variant of a tag.
That is what happens when you just type a capital word into the repl.
yup
is there a way to find the definition of a type?
say you define the following type:
Tup : (Str, U8)
Is it possible to find out what a Tup is, in the repl?
Hmm... I don't think so
fair enough
Good feature idea though
May be hard given we are a fully compiled language and not an interpreter though.
I'm actually working on a simple language myself, and I'm trying to understand how roc works and what tradeoffs have been made. simplicity always comes at a cost, but the cost can most of the time not be an issue
Brendan Hansknecht said:
May be hard given we are a fully compiled language and not an interpreter though.
yes, this would only be a repl feature
Yeah this is one thing I miss from lean. Using #eval
or #check
in the editor and seeing live results in the editor is amazing.
Last updated: Jul 05 2025 at 12:14 UTC