ChanServ changed the topic of #zig to: zig programming language | ziglang.org | be excellent to each other | channel logs: https://irclog.whitequark.org/zig/
Topa has joined #zig
Topa has quit [Ping timeout: 240 seconds]
tiehuis has joined #zig
Topa has joined #zig
Topa has quit [Ping timeout: 252 seconds]
Hejsil has joined #zig
Hejsil has quit [Quit: Page closed]
davr0s has joined #zig
davr0s has quit [Quit: My MacBook Pro has gone to sleep. ZZZzzz…]
davr0s has joined #zig
davr0s has quit [Quit: My MacBook Pro has gone to sleep. ZZZzzz…]
tiehuis has quit [Quit: WeeChat 2.0.1]
davr0s has joined #zig
davr0s has quit [Client Quit]
davr0s has joined #zig
davr0s has quit [Quit: My MacBook Pro has gone to sleep. ZZZzzz…]
Hejsil has joined #zig
<Hejsil>
andrewrk, seems .addPackagePath worked perfectly fine
Hejsil has quit [Ping timeout: 260 seconds]
jfo has joined #zig
Hejsil has joined #zig
Topa has joined #zig
davr0s has joined #zig
Topa has quit [Ping timeout: 256 seconds]
Hejsil has quit [Quit: Page closed]
<jfo>
andrewrk are you around?
<jfo>
I am wondering... is there any reason why a comptime function can't return a function? I know this is in the broader context of the discussion around variable capture and closures, but if a compile time function knows everything ahead of time, doesn't that mean it doesn't need to concern itself with that?
<GitHub56>
zig/master ad3e2a5 Andrew Kelley: fix compiler crash on function with invalid return type...
davr0s has quit [Quit: My MacBook Pro has gone to sleep. ZZZzzz…]
Hejsil has joined #zig
noonien has joined #zig
<noonien>
hello!
<noonien>
i've just stumbled upon zig, and i'm enjoying it
<noonien>
i've got up to "comptime" in the docs. from what i understand, comptime calls cannot call external functions, and i was wondering if this rules out reading a file at compile time
<Hejsil>
Yes, because reading files in the std calls out to the os
<Hejsil>
Aka external functions
<noonien>
a use-case for this, that i would find interesting, is parsing protobuf files at compile time, instead of using a code generator
<Hejsil>
True, that would be cool
<Hejsil>
But
<Hejsil>
You have @embedFile
<noonien>
oh, cool. i've not gotten that far yet, will look into it.
<Hejsil>
Ye, just remembered myself
<noonien>
oh, awesome! so you can read a file at compile time, great!
<Hejsil>
Sadly, no way to have UI, i think :)
<Hejsil>
I mean, you would probably have to interface os for that
<noonien>
UI?
<Hejsil>
User interface
<Hejsil>
Well, GUI (Graphical User Interface) is actually what I was refering too
<Hejsil>
Not that I have a usecase for this
<noonien>
well, having the content of the file would be great and pretty much all that's needed as far as I can tell so far
<Hejsil>
Indeed. I don't think drawing on the screen at comptime has much use
<Hejsil>
Unless you intend to do crazy stuff like what you can do in Jai
<noonien>
Nope. I've not got any experience with Jai. I'm only interested in perhaps using zig for embedded projects
<Hejsil>
I think Zig will suit your needs then
jfo has joined #zig
<jfo>
andrewrk: awesome! yeah I thought so... I'm curious about the difference b/t comptime higher order functions and runtime ones, though, the broader discussion around closures doesn't really apply to comptime does it? Because you're basically doing macro expansion on the comptime code? (I realize that's a misleading oversimplification, but it's a useful framing)
<andrewrk>
that's correct
<jfo>
is there any reason you can't next comptime function calls? will a comptime function be able to return a comptime function?
<jfo>
is that a meaningless question?
<andrewrk>
that should work fine
<jfo>
cool! I am _super_ excited about this type of higher order function support
<andrewrk>
I don't know what it means to "next" a function call, but you should be able to return a comptime function from a comptime function
<jfo>
I'd like to try to build a parser combinator when this is available
<jfo>
this looks awesome though I will look through your code ty
<Hejsil>
It's a little bit of a hack at places
<Hejsil>
Because we don't have GC, I kinda needed the user to provide a cleanup function
<Hejsil>
And, local structs are used to create functions and return them
<andrewrk>
Hejsil, one trick to consider, is to have an arena allocator, and so you don't have to worry about freeing individual things, and you can just free the entire AST by freeing the arena at the end
<andrewrk>
I'm going to do this for the self hosted parser
<jfo>
oh I see, that is clever. But certainly it will be better when you can return functions directly I guess?
<Hejsil>
andrewrk, the user can just provide that allocator and then not provide a cleanup function :)
<andrewrk>
I'm going to do this for the self hosted parser
<andrewrk>
oops
<Hejsil>
That makes sense
<MajorLag_>
It appears that a struct declared in a function block has the name of the function block for its type in error output: error: invalid cast from type '&u32' to '&testNestedStructCast()'
<andrewrk>
the suggested workaround for now is to put the struct definition outside the function
<andrewrk>
(still plan to fix it though)
<Hejsil>
Let's assume that a lib allows the user to provide an allocator, but cleans up on error. If the user provides something like an arena, will the empty free calls be a problem?
<Hejsil>
For speed that is
<andrewrk>
I think in practice that is likely not going to be the speed bottleneck of a given program
<Hejsil>
Probably true
<andrewrk>
my plan for the self hosted parser is: create mem.Arena which takes a mem.Allocator, and provides another mem.Allocator which is meant to be used without calling free. Then you can call arena.free() to free everything that you allocated with it
<andrewrk>
so you still pass a normal allocator to the parser
<Hejsil>
Ye, that's what I would expect
<andrewrk>
parser.parse() returns a Tree, and you can do tree.free() to free all of it at once
jfo has quit [Ping timeout: 240 seconds]
<Hejsil>
I guess tree.free() would do the traversal to free. While, if the user provided an arena, they would just call arena.free() instead
<andrewrk>
it wouldn't do the traversal; it would do only self.arena.free()
<andrewrk>
because each parser.parse() creates a new arena for the AST that it returns
<Hejsil>
Aah, ok
<noonien>
it would be cool to have something that automatically formats zig source code with a well defined style guide
<Hejsil>
That'll also help people avoid the "newline" "problem" that new users will face
<noonien>
also, from what i can tell. errors in zig are just ints. is it possible to annotate errors?
<andrewrk>
these tests are what the self hosted parser understands, and also verify that zig fmt outputs the same thing
<andrewrk>
noonien, you can have doc comments for errors, and when we have automatic docgen it will tell you, for every function, the list of possible errors, and the docs for each error
<andrewrk>
and you can even override the doc comment for a given error on a per-function basis
<noonien>
yup. but that's not what i meant.
<noonien>
for example, it would be great to be able to wrap errors
<andrewrk>
I see
<andrewrk>
it's not possible
<andrewrk>
you are welcome to open a github issue and make a proposal
<Hejsil>
Wasn't this discussed before?
<noonien>
hmm, i'm not familiar enough with the language to make a proposal, will think about it
<andrewrk>
Hejsil, probably. I don't remember where
<Hejsil>
And the conclusion was, that that's when you make a tagged union and return that
<andrewrk>
yen
<andrewrk>
*yes
<Hejsil>
I can't remember where I read it
<noonien>
i like go errors for example, errors satisfy an interface that can return a string that describes what happened
<andrewrk>
you can call @errorName(err)
<noonien>
this probably doesn't bode well with how zig works though
<andrewrk>
zig error codes are intended to be understood by the code; it's expected that there is a translation step between an error code and a user friendly error message
<andrewrk>
(for command line programs sometimes you can get away with @errorName)
<noonien>
sure, but you can't really have errors as: `can't parse definition: open file.dsl failed: permission denied`
<Hejsil>
Well, you probably have the file name at call site
<Hejsil>
And then you get error.PermissionDenied back
<andrewrk>
I would argue that correct software design would be bubbling up that in a data structure understandable by code, only rendering the error message at the very end
<andrewrk>
I've seen the anti-pattern of getting a "black box" error string from a low level component at a lot of work environments
<noonien>
Hejsil: yes, but for example, calling "lib.parse" will have the user check for the errors "lib.parse" can return, AND the errors any other function "lib.parse" might call
<andrewrk>
you end up with things like "error: can't parse definition: parsing definition failed: error: permission denied"
<noonien>
Hejsil: in most cases, the user doesn't care why the parsing failed, as long as it's not fixable, but the error message would be more descriptive
<andrewrk>
we actually have a feature that addresses this issue
<andrewrk>
consider if lib.parse catches PermissionDenied and returns ParseError, so now the caller only has to deal with ParseError
<Hejsil>
I totally understand. I'm just saying, that some consideration should be put into having most information available at callsite
<Hejsil>
If possible
<andrewrk>
in zig you can capture an error return trace
<Hejsil>
If not, then custom error union
<andrewrk>
this is kind of like a "stack trace" and it would include the permission denied error, as well as the parse error
<andrewrk>
so in a debugging situtation, you know exactly what happened
<noonien>
andrewrk: yes, but the user wouldn't know why ParserError was returned if I understand correctly
<andrewrk>
it sounds like the requirements of the program dictate that you need a more complicated error reporting mechanism
<andrewrk>
I think that zig's error codes are in harmony with that
<andrewrk>
e.g. in a parser that can get PermissionDenied, that could happen for any number of files
<andrewrk>
you probably also want to note the token range that caused the file to be looked up
<andrewrk>
the error return value seems like the wrong place to handle this to me
<noonien>
i see, so you're suggesting another type, that encompasses the error details, that is populated when an error occurs
<andrewrk>
yes
jfo has joined #zig
<noonien>
this is a nice workaround, however, it basically leaves error handling to the user imho
jfo has quit [Client Quit]
<noonien>
but i can understand why zig might want to make such a decision
<andrewrk>
I think you are overestimating the number of cases that an error code is not sufficient
<andrewrk>
I think that's a fair statement though. zig provides tools and then leaves error handling to the user
<noonien>
perhaps, i'm coming from go, and have learned that having as much info when an error occurs is usually desirable
<noonien>
but having strings as errors, and being able to compose errors will probably mean that each function that can return an error be able to allocate it
<andrewrk>
I see your point
<andrewrk>
if you ever catch one error code and return a different one, it would make sense if there was some kind of hierarchy
<andrewrk>
"ParseError because PermissionDenied"
<andrewrk>
and then associated parameters
<noonien>
yes, this is one of the simple examples. in a bigger program there will probably be even more complex scenarios
<noonien>
like having user-facing errors, that can store their underlying cause hidden. this way the underlying cause can be logged, while the user is shown the user facing error
<andrewrk>
if we want to log the underlying cause, it can log an error return trace, which solves the issue except for parameters such as which file didn't open
<andrewrk>
the error return trace shows all the lines of code where an error code was returned from a function
<andrewrk>
so that would, in our example, include PermissionDenied as well as ParseError
<noonien>
perhaps one such error would be "InvalidForm (can't read file)", while the app knows the entire error trace: "InvalidForm(field1), ParseError, PermissionDenied(file.txt)"
<andrewrk>
that makes sense
<noonien>
for example, go doesn't come with support for error stacks built-in, but because the `error` type is an interface, one can make their own type that wraps errors, there's several libraries that do that actually
<noonien>
ofc, zigs aproach is probablly more in-tune with the language tuned to be as optimal as possible from a memory and speed perspective
<andrewrk>
I think in a situation like this it's pretty reasonable to define structs for return values where you want to return a possible error code and parameters
<andrewrk>
the workflow would be: use zig's error types until you need parameters, then switch to union(enum)
<noonien>
cool, from what i can tell, zig doesn't support multiple return values, right?
<andrewrk>
there have been a few proposals kicking around
<andrewrk>
but nothing accepted yet
<andrewrk>
I think having an error as one of multiple return values would be an anti-pattern
<andrewrk>
you'd want a union(enum) instead
<andrewrk>
e.g. Rust's Result type
<noonien>
that makes sense
<noonien>
are there any docs for the standard library?
davr0s has quit [Quit: My MacBook Pro has gone to sleep. ZZZzzz…]
arBmind has joined #zig
davr0s has joined #zig
davr0s has quit [Quit: My MacBook Pro has gone to sleep. ZZZzzz…]
n_1-c_k_ has joined #zig
davr0s has joined #zig
jfo has joined #zig
<MajorLag_>
andrewk, the problem with union(enum) is that you can't use it with Zig's error handling conveniences like catch, try, etc., if I understand correctly. It would be nice if there was a way to do what noonien was talking about and keep that. Not sure what the solution would look like.
<andrewrk>
fair point
<MajorLag_>
If I were doing it in C, I'd make error a struct with the error's int value, a *void, and a length. But obviously that's pretty inelegant and unsafe for Zig.
<andrewrk>
you could still do that, but yeah maybe there's a better way
<andrewrk>
if you pass in a context struct, you can add error information to it, and then still use an error for the return value
<MajorLag_>
Yeah, that seems a lot simpler, but it does mean adding an extra parameter to everything that can error.