ChanServ changed the topic of #zig to: zig programming language | | be excellent to each other | channel logs:
schme245 has quit [Remote host closed the connection]
allochi has joined #zig
allochi has quit [Quit: Page closed]
kristate has joined #zig
kristate has quit [Ping timeout: 245 seconds]
qbradley has quit [Ping timeout: 256 seconds]
kristate has joined #zig
companion_cube has joined #zig
kristate has quit [Ping timeout: 268 seconds]
kristate has joined #zig
kristate has quit [Ping timeout: 245 seconds]
kristate has joined #zig
kristate has quit [Ping timeout: 244 seconds]
kristate has joined #zig
kristate has quit [Remote host closed the connection]
kristate has joined #zig
kristate has quit [Remote host closed the connection]
kristate has joined #zig
kristate has quit [Remote host closed the connection]
jevinskie has joined #zig
kristate has joined #zig
kristate has quit [Remote host closed the connection]
darithorn has quit [Remote host closed the connection]
kristate has joined #zig
kristate has quit [Ping timeout: 246 seconds]
schme245 has joined #zig
schme245 has quit [Remote host closed the connection]
schme245 has joined #zig
qazo has quit [Read error: Connection reset by peer]
<schme245> is there something like C++ "pass-by-reference" in Zig or is it C-style "pass-by-value" all the way?
allochi has joined #zig
Hejsil has joined #zig
<Hejsil> schme245, Well passing a pointer is pass-by-ref :)
<schme245> but the pointer is still copied, right?
<Hejsil> Well, yes
<Hejsil> Like in any language
<Hejsil> If you're trying to avoid copying big structs, then I'm happy to inform that zig does some pass-by-ref behind for you when you pass-by-value
<schme245> I'm just trying to figure out the exact semantics, coming from a Java background :)
<schme245> from what I gather, C++ has "reference parameters" that don't involve any copying whatsoever, is that correct?
<Hejsil> Well, assume that the type you passed is copied
<Hejsil> fn a(p: T) void passes T by value
<Hejsil> fn a(p: *T) void passes *T by value
<Hejsil> Well, c++ has void a(T &p)
<Hejsil> This is a pointer behind the scenes
<schme245> the one I'm thinking about is `void a(int& i)`
<Hejsil> Ye, that's the one
<schme245> ahh, ok
<schme245> so, to sum up, assume Zig copies, but sometimes it might decide not to, based on the whim of the compiler?
<Hejsil> Yeah, it's an optimization
<Hejsil> Here is a C pass by pointer vs C++ pass by ref
<Hejsil> I generates the same code (actually c++ has one more instr for some reason)
<schme245> is it correct that "copy elision" is about providing precise semantics for this optimization, so that you can guaranteed under some conditions?
<Hejsil> Oh wait, no it doesn't. My code was wrong
<Hejsil> Yes
<Hejsil> But it is mostly for returning values
<Hejsil> And not passing them
<Hejsil> But then again, we have guaranteed copy elision for parameters already. Pass by pointer
<schme245> hehe yeah, makes sense
<schme245> thank you for the explanations, much appreciated
<Hejsil> np
schme245 has quit [Ping timeout: 240 seconds]
gamester has joined #zig
gamester has left #zig [#zig]
schme245 has joined #zig
belgin has joined #zig
belgin has quit [Client Quit]
kristate has joined #zig
<schme245> is there a good tool on osx to view the assembly generated by the Zig compiler?
<schme245> preferably terminal-based
<Hejsil> Is objdump a thing on osx?
<schme245> yes, but I'm not sure that it works the same as on linux
<Hejsil> Hmm. Well, for small pieces of code, i paste it into
<Hejsil> Not in the terminal though
<schme245> that's a great resource, I didn't think Godbolt could do Zig!
<Hejsil> Some awesome people got it to work. It even has a very current version of zig master branch
Zaab1t has joined #zig
Zaab1t has quit [Client Quit]
kristate has quit [Remote host closed the connection]
kristate has joined #zig
<schme245> yeah, I saw that but I was a bit confused by the wording: "In Zig, structs, unions, and enums with payloads can be passed directly to a function"
<schme245> does "passed directly" mean "not as a pointer"? is that not possible in C?
<schme245> and what about types that are not structs, unions and enums?
<andrewrk> I see, let me try to clarify the wording
<schme245> in some parts of the documentation there's implicit reference/comparisons to C, which totally makes sense, but they can sometimes be hard to understand if you don't have a C background
<andrewrk> I'd like to improve those parts - ideally this document should stand alone
<andrewrk> people who have never used C are very much in the intended audience
Akuli has joined #zig
<Akuli> if i have a function that takes an argument of type []const u8, how do i call it? myFunction("Hello") doesn't work
<andrewrk> how doesn't it work?
<Akuli> error: expected type '[]const u32', found '[5]u8'
<Akuli> hmmmm maybe i should have read that message
<andrewrk> it's ok, sometimes I do the same thing when asking for help in #llvm :)
<andrewrk> schme245, how's this?
<companion_cube> are blocks able to return values, like proper expressions, without the label: break thing?
<andrewrk> companion_cube, you have to use labeled break syntax to take advantage of blocks as expressions
<companion_cube> is there a reason for that choice?
<andrewrk> sounds like you may be interested in
<andrewrk> the reasoning is: we do need labeled break for some things. you can use labeled break for blocks as expressions, so that works today. and then the final decision has not been made yet about whether there is a shorthand for simpler expressions
<companion_cube> I'm not sure I understand why `{foo; x}` can't be the value of `x`
<andrewrk> it used to be that way
<companion_cube> (there seems to be a lot of inspiration from rust in Zig, so that would seem natural)
<andrewrk> one issue was that it lead to inconsistent code for function body blocks
<andrewrk> fn foo() void{ return x; } vs fn foo() void{ x }
<andrewrk> there's probably a closed issue lying around with more reasoning on it
halosghost has joined #zig
<companion_cube> fn food() void { x; }
<companion_cube> (I admit that `void`, as a concept, has always seemed super weird to me, unlike `()`)
<halosghost> companion_cube: what makes `void` weirder than `()` (which I'm presuming you're using to refer to unit)?
<companion_cube> well, void doesn't have values, yet you can return it (?!)
<companion_cube> unit has a single value, so it's easy to tranform `fn foo() unit { x; }` into `fn foo() unit { x; () }` as rust, OCaml, etc. do
<halosghost> that's fair
<halosghost> I guess it has always felt natural to me because I started in C and it just seemed like the type-level version of NULL
<halosghost> I suppose I also really like that unit (depending on the language) can map to the empty tuple
<andrewrk> companion_cube, void is the unit type in zig. fn foo() void { } is secretly translated to fn foo() void { return void{}; };
<andrewrk> (`void{}` being the only value of type `void`)
<companion_cube> ah, so it's unit, ok
<halosghost> simplifies that :)
<companion_cube> (so then you can have a distinction between `x;` and `x`)
<Akuli> halosghost, not a zig question anymore but i'm curious, what do you think about 1-element tuples then? :D if you like 0-element tuples and tuples with >=2 elements
<halosghost> Akuli: 1-element tuples don't bother me. Actually, I find them to be a reasonable approximation/alternative to OOP langauges' boxing
<companion_cube> you can optimize (T,) into T quite easily :)
<halosghost> companion_cube: which is a little like auto-{un,}boxing
<Akuli> hmmm this turned into #proglangdesign
<halosghost> Akuli: above almost everything else, I prize consistency
<halosghost> when languages manage consistency, it makes me very happy
<companion_cube> can you talk about a language at version 0.3 without talking about design? :)
<halosghost> companion_cube: personally, I find it hard to talk about any language without talking about some aspect of design :P
<companion_cube> right.
<Akuli> better ideas?
<Akuli> nevermind, i figured it out
<Akuli> const arr = []u32{ 'P', 0xf6, 0xf6 }; then std.mem.eql(u32, thestuff, arr);
<Akuli> const arr = []u32{ 'P', 0xf6, 0xf6 }; then std.mem.eql(u32, thestuff, arr);
<Akuli> oops
steveno has joined #zig
<schme245> andrewrk: that's much more clear! the one thing that I still find confusing is the test name: "pass aggregate type by non-copy value". the section above mentioned that the thing can be passed either by value or reference, so calling it "non-copy value" muddles that up a bit IMO
<andrewrk> schme245, thanks, I'll change that and then push
<schme245> great, thanks!
forgot-password has joined #zig
Hejsil has quit [Ping timeout: 256 seconds]
<forgot-password> Regarding schme245's pass-by-value discussion: I haven't really figured out when I can just return something from a function and when I have to allocate it on the heap.
<forgot-password> I have a function which returns a struct with two slices. When I pass the result of this function to another function, however, it seems like the data got partially corrupted.
<andrewrk> forgot-password, you have to think about where your bytes are. slices are reference types - the bytes are somewhere else
<forgot-password> I assume that's because I shouldn't be using that memory anymore and something else has written over my intial data.
<andrewrk> if you return a struct with 2 slices, then that raises the question - where are the bytes that the slices are pointing to?
<forgot-password> That makes sense
<andrewrk> one possible answer to that question is: on the heap. And when you're done with the struct, you have to free them
<andrewrk> another possible answer is: global constants. no need to free
<andrewrk> Rust makes you answer this question at compile-time. In Zig you have to answer this question at runtime, with potentially disastrous consequences if you mess it up
<forgot-password> And if they are on the stack the data is basically unusable as soon as the function returns, right?
<andrewrk> correct
<andrewrk> I plan to look into improving debug runtime safety checks to be able to detect dangling references to stack data
<andrewrk> that will be a fun research project
<forgot-password> The thing is, I fully understand what you are telling me, but I feel like it's a whole different beast to actually apply that in your code...
<schme245> forgot-password: what's your language background?
<andrewrk> sounds like you're all set then, just need some practice :)
steveno has quit [Quit: Leaving]
<forgot-password> schme245: 99% gc languages. I do Web-Stuff for work, but in my free time I love to play around with Haskell and Zig :)
<schme245> haha, then we're on the struggle bus together :D
<schme245> I think the way to learn to apply this in the code is to just make all the mistakes
<forgot-password> I figured that from your questions the other day :p
<forgot-password> Yeah, seems like it
<andrewrk> valgrind is a nice tool, don't be afraid to use it (you'll have to use the --no-rosegment workaround for now though)
<schme245> dangling pointer to stack data, overflow the stack, forget to free etc etc... everytime you make a mistake you learn something and you remember it for the future
<Akuli> forgot-password, you could pass a struct as a pointer to the function and have the function modify it
<forgot-password> I'm using lldb, is that any different? Afaik valgrind is for memory-related stuff, right?
<andrewrk> valgrind decompiles your machine code, instruments it, and then JITs it, and detects a lot of mistakes, printing useful stack traces
<andrewrk> it's also instrumental in leak checking
<schme245> speaking of, what do you suggest for profiling Zig code?
<forgot-password> Akuli: Thanks, but I don't think that helps in my current situation
<andrewrk> schme245, valgrind does that too
<Akuli> valgrind does profiling? :D i never knew that
<emekankurumeh[m]> it's sad it only works on unix though
<andrewrk> videos are not for everybody, but I did a couple of streams on some topics relevant to you, schme245 and forgot-password
<andrewrk> Allocators & Memory Management:
<andrewrk> Using Valgrind and GDB to debug memory issues:
<andrewrk> Using valgrind for performance profiling:
<schme245> awesome, I'll check 'em out later tonight!
<forgot-password> andrewrk: Thank you !
jevinskie has quit [Quit: My MacBook has gone to sleep. ZZZzzz…]
schme245 has quit [Remote host closed the connection]
schme245 has joined #zig
darithorn has joined #zig
schme245 has quit [Ping timeout: 246 seconds]
schme245 has joined #zig
schme245 has quit [Remote host closed the connection]
Zaab1t has joined #zig
kristate has quit [Remote host closed the connection]
kristate has joined #zig
kristate has quit [Ping timeout: 245 seconds]
allochi has quit [Ping timeout: 256 seconds]
<Akuli> is there a more elegant way to do this?
<Akuli> hmmm the errdefer is wrong
<Akuli> after the realloc, it would do a double free
<Akuli> i should define buf with var and then buf = allocator.realloc(...) catch unreachable;
<andrewrk> Akuli, I think there's already a function that does that
<Akuli> i think i looked around in std/unicode and couldn't find it :D
<andrewrk> oh, it's for utf-16le, not fully decoded u32 codepoints
<andrewrk> you could use it for inspiration though
<Akuli> / optimistically guess that it will all be ascii.
<Akuli> hmm this is the other way
<Akuli> let me find the correct function
<andrewrk> we have allocator.shrink for your snippet at the end there
<Akuli> oo nice, i'm just used to doing this realloc thing in c
<Akuli> even though in c it's trickier because i need to check whether realloc returns NULL, and the only reliable way to actually free the original pointer then is a temporary variable etc :D
<andrewrk> the errdefer looks correct to me
<Akuli> it isn't
<andrewrk> why not?
<Akuli> there is code after the last line in my paste, think about what happens when that code fails
<andrewrk> I don't see anything that can fail after the alloc
<Akuli> realloc can return a different buffer than what was passed to it, so buf and new_buf aren't necessarily the same
<Akuli> this is only a part of my function :D there's more stuff below it
<andrewrk> I still think the errdefer is correct
<Akuli> if that stuff fails, the defer will free buf, but the buf was passed to realloc which may make it unusable
<Akuli> what the errdefer should do is to free the new buf that came from realloc
<andrewrk> you want: buf = allocator.shrink(u32, buf, i);
<andrewrk> the errdefer is correct
<Akuli> yes i do :D then it is correct
<Akuli> shrink is nice
<andrewrk> the whole point of defer/errdefer is that it can for the most part remain independent of the rest of the body of your function
<andrewrk> you can edit parts of a function without having to change everything
<Akuli> yes, and using the buf= shrink(buf) thing helps with that
<Akuli> if i do this: const x = 'a'; what is the type of x? u8?
<andrewrk> try this: @compileLog(@typeOf(x));
<Akuli> ok :D
<Akuli> hmm comptime_int of course
Zaab1t has quit [Quit: bye bye friends]
Ichorio has joined #zig
<Akuli> is some_string[1..] like some_string+1 in c?
<Akuli> i think it is :D
wootehfoot has joined #zig
marmotini_ has joined #zig
schme245 has joined #zig
schme245 has quit [Remote host closed the connection]
Akuli has quit [Quit: Leaving]
marmotini_ has quit [Ping timeout: 250 seconds]
Sahnvour has joined #zig
<Sahnvour> hi all
<andrewrk> Sahnvour, yes, it tries every PATH directory looking for the executable
<Sahnvour> andrewrk: I see, but I miss something to understand why the return of a !void function (windowsCreateProcess) is used in the `if` where it was previously handled with `catch` ?
<andrewrk> I should break this code up a bit, but look at the "if error union" test
gamester has joined #zig
<Sahnvour> thanks
<gamester> I just tried the newly added Serializer and Deserializer and they're great! Cool improvement over C++ (though C++ may catch up with reflection coming up). The only problem I had was when I tried to use a NullOutStream with it because it's "Error" is simply "error{}" and this doesn't work with the "try" syntax it seems, so you get the following error inside the Serializer:
<gamester> "function with inferred error set must return at least one possible error"
<gamester> Anyway I'm currently tethering my PC to my phone and its not working so great so im going to be offline mostly
<andrewrk> gamester, you can thank MajorLag for those new APIs. There are a few ergonomic issues with error sets, not done with design iterations on those
<andrewrk> you have to be careful serializing errors anyway since the error codes are not stable across different builds
<andrewrk> if the code is trying to auto serialize an error, it should probably do it based on the name
<andrewrk> oh, I see the problem you are describing is not what I am talking about
<andrewrk> sorry
<gamester> yeah the problem is simply when you attach the Serializer to a NullOutStream
schme245 has joined #zig
<gamester> to be more precise, Serializer takes a comptime Error: type and it can't be "error{}"
<gamester> I'm sorry, I mean it can't be NullOutStream.Error, which is error{}
<gamester> andrewrk: yes I've seen on github that error sets are still being worked on / there are known pain points. Anyway, thanks MajorLag for the great library!
<andrewrk> there has got to be a bit twiddly way to "align forward" without remainder division and branching
<andrewrk> addr = alignForward(addr, 8);
<andrewrk> 7 -> 8, 8 -> 8, 9 -> 16, 10 -> 16, ... 15 -> 16, 16 -> 16, 17 -> 24, etc
<gamester> here's what I was talking about:
rohlem has joined #zig
<nbjoerg> andrewrk: (addr + alignment - 1) & (~alignment - 1) ?
wootehfoot has quit [Read error: Connection reset by peer]
<nbjoerg> assuming alignment is power of two
<andrewrk> ahh that's it
<andrewrk> stealing that
<gamester> I have two places where I can use that, nice
<rohlem> nbjoerg, andrewrk: Hmm, I've been using: ((addr - 1) & ~(alignment - 1)) + alignment
<shachaf> Oh, that's ~(alignment - 1), not (~alignment) - 1
<shachaf> That makes more sense
Sahnvour has quit [Ping timeout: 256 seconds]
<rohlem> I can say that my variation has worked in production so far, though I've not stress-tested it since inception...
<nbjoerg> my variation is classic round up, e.g. the equivalient of (addr + alignment - 1) / alignment * alignment
<nbjoerg> your's is not wrong, just a bit stranger to read :)
<rohlem> Okay, whether you add alignment first or later doesn't make a difference with wrapping arithmetic, overflowing in both scenarios.
<nbjoerg> and yeah, should be ~(alignment - 1)
<andrewrk> and in zig syntax, ~(alignment -% 1)
<nbjoerg> but works fine in C at least due to operator order :)
<andrewrk> err, wait that doesn't actually matter, my mistake
<rohlem> andrewrk: Actually, I don't think wrapping it is expected behaviour.
<rohlem> andrewrk: I'd advise leaving the alignment >= 1 check in.
<nbjoerg> wrapping can only happen if you allow alignment of 0
<andrewrk> agreed
<nbjoerg> which is typically a bug
gamester has left #zig ["Konversation terminated!"]
<rohlem> If address space is wrapping then the addition should be made wrapping, but I don't think that's a safe assumption generally.
<rohlem> Actually, is wrapping pointer arithmetic implemented / allowed status-quo?
<andrewrk> status quo, pointer arithmetic is safety-checked undefined behavior if it wraps. I'd have to double check to make sure we have a test covering this
Flaminator has quit [Read error: Connection reset by peer]
Sahnvour has joined #zig
<andrewrk> hmm no test for it. I'll open an issue at least until we have test coverage
<rohlem> So operators +% and -% result in an error?
<andrewrk> yes: error: integer value 1 cannot be implicitly casted to type '[*]u8'
<andrewrk> status quo, if the addition would wrap the address space, then it invokes undefined behavior and there is no safety check for it
halosghost has quit [Quit: WeeChat 2.3]
rohlem has quit [Quit: Page closed]
Flaminator has joined #zig
Ichorio has quit [Ping timeout: 268 seconds]
<MajorLag> gamester: I thought I'd accounted for empty errorsets in serialize, but I guess I missed it. I'll take a look at it when I get home and do a PR to fix. I suppect it will be a 5 character diff.
<MajorLag> ...yeah, I just need to not infer the error in `serializeInt`.
<MajorLag> I got it right in the deserializer, probably because SliceInStream.Error is error{}.
<Sahnvour> what's the idiomatic way to concatenate two strings (one being comptime) ?
<andrewrk> where do you want the resulting bytes to live?
<andrewrk> std.fmt.bufPrint will put them in a slice. std.fmt.allocPrint will give you a slice of heap memory
<andrewrk> if you have a stream you can use the print method
<andrewrk> all of these will let you do "{}{}", a, b
<Sahnvour> I don't really know yet, now that you ask
forgot-password has quit [Quit: leaving]
<Sahnvour> I'm in build.zig, just saw that there's already a fmt utility in there
<Sahnvour> but it seems like it's allocating a lot of strings and never freeing them ?
<andrewrk> yeah, that's going to be fine because it's a build script - you run it once and then everything gets freed when the build exits
<Sahnvour> I see, thanks
Sahnvour has quit [Ping timeout: 256 seconds]
<daurnimator> andrewrk: speaking of valgrind... there's some PRs that need merging :)
<andrewrk> working on it
steveno has joined #zig
SimonNa has quit [Remote host closed the connection]
SimonNa has joined #zig