ChanServ changed the topic of #zig to: zig programming language | ziglang.org | be excellent to each other | channel logs: https://irclog.whitequark.org/zig/
hoppetosse has quit [Ping timeout: 260 seconds]
<benzrf>
andrewrk: wtf is the "var" type
hopppetosse has quit [Ping timeout: 248 seconds]
<zesterer>
Why does Zig not accept tabs?
<benzrf>
zesterer: tabs are evil
<zesterer>
They're not. They're used in cases where whitespace alignment isn't required to be a specific width.
hopppetosse has joined #zig
<benzrf>
well, i'm not andrewrk, so ignore me :)
<zesterer>
To enforce that at a compiler level is pretty damn obnoxious. Just saying.
<benzrf>
i feel like ive heard of something else that rejects tabs
<benzrf>
maybe it was Go or Rust?
<benzrf>
(not saying this as justification, just seeing if anybody else remembers what that wouldve been)
<zesterer>
Go and Rust both accept tabs.
<benzrf>
hmm
<benzrf>
maybe i was just thinking of giving warnings on tabs? shrug
<benzrf>
obviously you should properly write a formal spec in coq ;)
davr0s has joined #zig
<zesterer>
As an additional point, I have a developer friend that is partially sighted. He has to use very large font sizes when working, and it infuriates him no end when developers use soft-tabs, since it means he ends up scrolling code a lot since he can't tell his editor to display tabs as a single character's width.
<andrewrk>
zesterer, I don't want that point to get lost, can you add it to your case on the issue?
<zesterer>
andrewrk: Sure
<zesterer>
[Not talking to anybody in particular] Apart from anything else, spaces are not indentation. They're padding. The two are totally distinct, and spaces were never intended to act as identation. If you're using them as such, you're such them incorrectly.
<andrewrk>
this is a discussion that has the potential to get repeated many times; I request that we can have it on the issue so that, however it gets resolved, people questioning the decision can read the full discussion
<benzrf>
man
<benzrf>
the compile time stuff seems like it'd be really hard to properly spec
<benzrf>
just implement a true type system...... you know you want to ;)
<benzrf>
well, that would also be very hard to spec, i guess
cenomla has quit [Quit: cenomla]
jfo has joined #zig
davr0s has quit [Quit: My MacBook Pro has gone to sleep. ZZZzzz…]
jfo has quit [Ping timeout: 240 seconds]
zesterer has quit [Quit: zesterer]
<MajorLag_>
the more I play with comptime the more difficult I find it to reason about. that might change over time.
<hopppetosse>
turns out the full pkg does encoding too
<hopppetosse>
still no deps =)
<andrewrk>
hopppetosse, it would be a roundabout way to do it, but you could try improving translate-c enough to do this port automatically
<hopppetosse>
That would actually be pretty sweet
<hopppetosse>
I haven't looked at the translate-c code yet
<MajorLag_>
I found translate-c really helpful in getting an SDL2 binding going. Only had to correct a few things (like SDL_RWclose)
<MajorLag_>
But I imagine macro-heavy code would cause more issues
<MajorLag_>
andrewrk, do you know if Zig can even link properly with Mingw libs? Last time I tried it ended badly.
<andrewrk>
I think it used to, but then I neglected that code for the msvc linking code
<zesterer_>
Out of interest, what's the thinking behind disallowing passing structs / enums / unions by value? I can understand it makes the compiler internals a little simpler, but does it have value?
<andrewrk>
but yes, to avoid implicit copying, and to have there be one canonical way to do things
<andrewrk>
I don't think it actually makes compiler internals less complicated
<andrewrk>
I'll file the issue
<zesterer_>
andrewrk: Okay. A pattern I very often use is to have a function that constructs a type and returns it. Something like create_x_from_y(y). I'd assume this would break any such syntax?
<hopppetosse>
I had issues building generic containers because of this - I had have to use &const T instead of T for the same code to work on user defined structs and primitive types
<zesterer_>
andrewrk: Cheers for answering that
<zesterer_>
andrewrk: I actually mapped out a plan for a language I was going to write a few months ago, and it looks surprisingly similar to Zig.
<andrewrk>
I hope I can fulfill your use case
<zesterer_>
andrewrk: If you're interested, here are a few example programs I drew up. I think the only major difference is that my language would have had support for anonymous structs. https://pastebin.com/QaKnKd7q
<hopppetosse>
zesterer: all structs in zig are anonymous =9
<zesterer_>
hopppetosse: By that, I mean that they can be generated inline. One could do: function(<a, b>, c)
<andrewrk>
what does that do?
<andrewrk>
{0} and {1} in fmt specifiers is a good idea
<andrewrk>
a, b = b, a; how do you make this work?
<andrewrk>
implicit heap allocation is a major departure from zig
<zesterer_>
As I say, this wasn't a plan: there are some elements of the syntax that are contradictory or ambiguous. I was just brainstorming.
<andrewrk>
ah
<hopppetosse>
"{0} and {1} in fmt specifiers is a good idea" -> Agreed
<zesterer_>
So much so that I implemented that syntax in C++ in a previous kernel's utility code using variadic templates. It was typesafe, but had a tendency to produce way too much code and had some runtime overhead if aggressive optimisations weren't enabled
<zesterer_>
I like how methods in Zig as little more than namespaced functions. Makes a lot more sense to me than implicitly declaring an identifier like "this" to deal with self-referencing.
<andrewrk>
in zig you can likely copy-paste a block of code from one place to another and have it work verbatim
<andrewrk>
that's one reason for that
<zesterer_>
Sensible decision
<zesterer_>
I also like how you've included a bunch of built-in utility functions for querying types at compile-time. It struck me as madness at how C++ relied on the <type_traits> header to provide features like that, yet wasn't properly available in a freestanding environment.
<MajorLag_>
andrewrk, is there reasoning behind the inconsistent capitalization of builtin functions or was it just an oversight? @TagType/@tagName.
<andrewrk>
I'm not 100% happy with how that turned out, but it's following the style guide
<andrewrk>
which says that functions are capitalized if they return a type
<andrewrk>
kind of annoying to have @sizeOf and @TypeOf
<andrewrk>
but to be consistent it should be @TypeOf
<andrewrk>
I'm open to style guide modification proposals
<andrewrk>
(I believe @typeOf existed before the style guide and I haven't updated it yet)
<MajorLag_>
I'm trying to avoid bikeshedding the hell out of all these proposals
cenomla has joined #zig
<MajorLag_>
is there a way to get the active field (value of the active field ideally) of a union?
<zesterer_>
andrewrk: If you're going to enforce anything, you should be enforcing camelCase and TitleCase on public functions and structs, not preventing people using tabs in their code. At least then you're making sure that the interface between libraries is consistent.
<MajorLag_>
On the one hand, I kinda agree. Whitespace should either be significant or not. On the other hand, it's hard to think of something that matters less.
<andrewrk>
MajorLag_, if it's a union with a provided (or auto) enum tag, then yes
<zesterer_>
Whitespace is purely cosmetic. It doesn't alter the interface between bits of code (like identifier case does), it doesn't lead to spaghetti code, it can be automatically corrected by any half-decent editor. If there's anything that should be permissible, it's whitespace styles.
<zesterer_>
andrewrk: So does "defer" work even on early function returns? If so, that's a bloody neat feature.
<andrewrk>
one thing that's planned is passing --fmt, which would apply zig fmt to the files during the compilation (and overwrite the file contents with the reformatted code). this would allow tabs (and convert them to spaces)
<andrewrk>
zesterer_, yes, defer runs on scope exit. note that this is different than in go, where it runs at the end of the current function, which requires a heap allocation per defer
<andrewrk>
sorry not per defer, but in general, requires hidden heap allocation
<MajorLag_>
Go does a lot of that
<zesterer_>
It's one of the things that really put me off Go
<zesterer_>
I'm definitely warming to Zig far more than I am most languages, so congrats on building something so decent
<andrewrk>
errdefer runs at scope exit if and only if you returned from the function with an error from inside the scope
<MajorLag_>
The GC, the ASI, the lack of a union type... overall, I didn't hate Go, but it has some things I'd rather not deal with.
<andrewrk>
thanks zesterer_
<MajorLag_>
Yeah, after I got to using Zig I'm finding I really like it for the most part. And the parts I don't may just be because they feel a little too different from C.
<zesterer_>
andrewrk: Side note: I see that Zig has a neat monadic error syntax. Are there plans to extend that to all types in a similar manner to Rust's type-safe payload enums? Or is that not within the scope of the language?
<andrewrk>
which parts are those MajorLag_
<andrewrk>
comptime?
<andrewrk>
zesterer_, can you elaborate? extend what exactly to all types?
<zesterer_>
andrewrk: enum MyEnum { Foo { foo: u32 }, Bar { bar: f32 } }
<zesterer_>
Tagged unions that don't break the type system, like in Rust
<MajorLag_>
The things I bring up. They're mostly little things and generally I've found your reasoning to be pretty solid, or that part of the language is still in flux.
<andrewrk>
summary: union { } is a C-like union, but it has runtime safety via a secret field (which you do not have access to)
<zesterer_>
andrewrk: As it should be :)
<andrewrk>
union(enum) { } is a tagged union. in this case the tag type is auto generated, but you can pass an enum type in place of `enum`, and then you can do rust-style semantics on it
<zesterer_>
andrewrk: I assume it's impossible to check a tagged union field without first asserting that the tagged union is of the type you think it is?
<andrewrk>
it doesn't block you from doing that. but you are encouraged to switch on the value (equivalent of rust's match) to destructure it
<zesterer_>
Would be nice if it gave something like the internal type or an error
<andrewrk>
here's code that does that: switch (value) {Enum.Item => |x| x, else => error.WrongField}
<zesterer_>
Okay. So not forcing type system honesty at a language level like Rust does then. That's fine too
<andrewrk>
right. In the same way that you should avoid @ptrCast if you can, you should avoid accessing a union(enum) via a field directly if you can
jfo has joined #zig
<zesterer_>
Okay. Not sure how I feel about that. ptrCast() is different in that it's not the sort of thing that you use as a shortcut. But if you're prototyping code, it's quite possible you decide to skip the union(enum) check because you're *pretty sure* it's fine, but then that code somehow ends up in production code a few years down the line and nobody's fixed it
<andrewrk>
one note is that if that production code is running in ReleaseSafe mode, it would at least crash if the wrong field was ever accessed
<zesterer_>
Reasonable I guess, but doesn't really fit with the "Compile errors are better than runtime crashes." from the Zen.
<andrewrk>
fair point
<MajorLag_>
On the other hand, it means that if I need speed and don't care so much about safety (probably because I developed in release-safe and have a reasonable assurance that it's ok), I'll appreciate knowing there's no invisible costs.
<MajorLag_>
Oh, nevermind, you were complaining about the crash vs compile error
<zesterer_>
I think it would make a lot of sense to return a %Type. That way, the developer is forced to consider the possibility of problems
<MajorLag_>
which is a legit point
jfo has quit [Ping timeout: 240 seconds]
<zesterer_>
Like it doesn't make sense to have a %void returned on something like printing text to the console incase stdout fails, yet no error on something like accessing a union(enum) which is way more likely to go horribly wrong
<andrewrk>
this is similar to the ?? prefix operator on nullables. it asserts that the item is not null, and returns the payload
<zesterer_>
andrewrk: Yes, effectively
<zesterer_>
You could argue that there's the runtime overhead of checking the tag, but that's kind of irrelevant: If they're using a union(enum) and not checking the tag, they shouldn't be using the union(enum) in the first place since they clearly don't care that the union(enum) can take more than one type value. Might as well just use a straight type.
<MajorLag_>
that's fair I think
<MajorLag_>
unless I want it tagged elsewhere, but I have some tight loop that needs to not check them. Seems like kind of an edge case.
<zesterer_>
MajorLag_: In which case, you should probably just take a reference to the union(enum)'s internal value rather than checking the entire enum(value) every time in the loop
<zesterer_>
Or better yet, just unpack the thing. I'm sure the optimiser can get rid of that later anyway.
<MajorLag_>
I'm probably iterating over a large number of unions in this case
<MajorLag_>
though in all honesty I can't think of a reason I'd be doing that and not wanting a tag.
<zesterer_>
MajorLag_: In that case, why are you using a lot of union(enum)s if they're all clearly of the same type?
<zesterer_>
Might as well just use a single tag rather than an identical tag for literally all of the things you're iterating.
<MajorLag_>
first thing that comes to mind: a bunch of different Entity structs that have unions of their subtypes. Of course that's a bad example since I'd want a tag.
<zesterer_>
My point is that the ONLY places you should be using an union(enum) is somewhere where there's genuine runtime ambiguity about the type contained within it. If that's the case, then checking the tag before using it is ALWAYS essential to avoid horrible problems
<zesterer_>
*uncertainty, not ambiguity
<MajorLag_>
and if I knew they were all of the same type (perhaps I pre-sorted them) and really needed to do this, I can abuse @offsetOf and @intToPtr/@ptrToInt
<zesterer_>
MajorLag_: If you really want to, although that's a horrible thing to do :D
<MajorLag_>
Maybe, but I derive particular joy from abusing @intToPtr/@ptrToInt.
* zesterer_
screams
<andrewrk>
MajorLag_, did you also find @fieldParentPtr ?
<MajorLag_>
I know of it, I haven't had to use it yet.
<zesterer_>
Hearing about the oddities that old CPU architectures have with address / integer incompatibility make me deeply fear code like that
<zesterer_>
andrewrk: I saw that. Not 100% sure that purpose it would have though?
<andrewrk>
look for its use in the standard library
<zesterer_>
andrewrk: The same could be achieved with just a simple subtraction? Or is it just syntax sugar?
<andrewrk>
it's slightly safer than @ptrCast + @offsetOf
<andrewrk>
useful for OOP-like things
<zesterer_>
Fair enough
<hopppetosse>
@fieldParentPtr is very similar to the container_of macro in linux
<andrewrk>
yeah I was thinking of renaming it to @containerOf
<zesterer_>
Or just parentOf()?
<hopppetosse>
built-in functions should keep the @
<zesterer_>
Although tbh "parent" doesn't make so much sense since it's usually used in terms of data reference relationships so I see your point
<zesterer_>
hopppetosse: '@' was intended to be implicit ;)
<hopppetosse>
someone suggested removing the @'s from built in funcs recently, and I think I got overly sensitive =P
<hopppetosse>
they already got rid of my sweet sweet sigils and '->' in the name of 'readability'... please, no more!
<hopppetosse>
On a more serious note, I'm quite liking the new sigil-less error handling, so thanks =)
<andrewrk>
:)
<hopppetosse>
Not sure how I feel about the -> removal
<andrewrk>
hopppetosse, have you experienced error return traces yet?
<andrewrk>
there's a syntax problem with return types
<hopppetosse>
yeah, I saw the discussion
<andrewrk>
we can potentially add back in -> if everybody loves it
<hopppetosse>
it does make the code look cleaner though, I just thought that -> was a good visual anchor
<andrewrk>
but I want to solve the syntax issue at the same time, so that this can be the last breaking change to return types
<hopppetosse>
I'm not sure what you mean by error return traces
<andrewrk>
I need to make a blog post about these
<zesterer_>
andrewrk: What's "->"?
<andrewrk>
it's something I invented
<MajorLag_>
I'm ok either way, but -> seems redundant.
<andrewrk>
zesterer_, function prototypes used to look like your language with ->, until last weekx
<zesterer_>
I'm on team "->".
<andrewrk>
noted
<hopppetosse>
yeah, it's redundant, but visually useful
<hopppetosse>
just like the enforced indentation and curly braces
<hopppetosse>
one makes it good for machines, the other for humans
<zesterer_>
Minimalism at the cost of clarity if not a good idea
<zesterer_>
Even the UNIX philosophy has its limits
<MajorLag_>
As long as you don't go to the length of enforcing style I'll be ok.
<andrewrk>
style won't be enforced, but we will provide `zig fmt` if one wants to opt-in to the canonical style
<hopppetosse>
I'm pretty sure I'm on team -> but please not any time soon.... I just spent far too much time removing ->'s from tick
<hopppetosse>
though the annoying thing was putting in the explicit void return type
<andrewrk>
sorry hopppetosse
<andrewrk>
I know that was annoying, I did it for the zig std lib
<hopppetosse>
it was kinda my fault, I assumed my regex-fu was sufficient to get it done automatically
<zesterer_>
Does Zig have anything akin to rustfmt? It would be trivial to write a script that goes around adding "->" back into everything
<hopppetosse>
I've just finished my uni semester, I should have more free time over the next month
<hopppetosse>
I was actually going through the self-hosted code the other day
<hopppetosse>
that's a nice looking parser
<andrewrk>
non-recursive too!
<zesterer_>
Is Zig's syntax deterministic? Can it be read by a recursive decent parser without ambiguity?
<andrewrk>
yes. the c++ parser is recursive descent. the self hosted parser is equivalent to recursive descent, but uses an explicit stack instead of recursion
<zesterer_>
Nice. Apologies if I'm not using the right terms. When it comes to compiler design, I'm largely self-taught.
<zesterer_>
If I get a spare day or two, I'll give building a parser a go. That way, we can easily build up a syntax tree to spit out some nice formatted Zig for any revision of Zig
<andrewrk>
zesterer_, a new parser?
<andrewrk>
why not contribute to the official hosted parser?
<andrewrk>
*official self hosted parser
<zesterer_>
andrewrk: Perhaps a forking of the original into a separate repository is more suitable? That way it can be reused by community tools pretty easily
<zesterer_>
andrewrk: We can have nice IDE tools
<andrewrk>
I mean, we could just make the official parser part of the standard library
<andrewrk>
there's no reason not to
<zesterer_>
That makes a lot of sense
<zesterer_>
You'll have to excuse me with all these questions.
<zesterer_>
Is there documentation for the contents of the standard library? I couldn't seem to find any.
<andrewrk>
no. I'm banking on the automatic doc gen for that (inspired by rust doc)
<andrewrk>
and that's only going to be implemented in the self hosted compiler
<zesterer_>
Okay. I'll just look through the source and take educated guesses. I assume there are distinct freestanding and hosted components of it?
<andrewrk>
zesterer_, it relies on lazy top level declaration analysis. so the line between freestanding and os-dependent is blurry
<andrewrk>
any function which does not depend on OS specific code works
<andrewrk>
and if you accidentally depend on an OS in freestanding mode, you'll get a compile error
<zesterer_>
Right. Maybe in future separating freestanding into something similar to Rust's core module is a good idea?
<andrewrk>
to what end?
<andrewrk>
I mean, what for?
<MajorLag_>
this comptime struct reflection is starting to look pretty decent. I can definitely make use of this for debugging.
<zesterer_>
andrewrk: The more the standard library grows, the more dependent on hosted stuff any freestanding implementation becomes. The compiler still has to parse available functions to determine whether we're allowed to use them presumably?
<andrewrk>
nope
<andrewrk>
it's fully lazy. if you have a compile error in a function you never call, you don't see the compile error
<andrewrk>
if you don't use a function from foo.zig, foo.zig is not even loaded from disk
<andrewrk>
in other words, what you already have to do for generics, we do for every function
<zesterer_>
ooh you have elfy stuff in the standard library? That's cool. Very cool.
<andrewrk>
zesterer_, try this code: test "aoeu" { unreachable; }
<andrewrk>
zig test test.zig
<MajorLag_>
I can attest to not seeing errors in unused code
<andrewrk>
you can see the elf/dwarf code in action
<andrewrk>
MajorLag_, this has a downside too, I acknowledge. I have plans to make this better
<zesterer_>
andrewrk: I can guess at what that does. Unless it's something weird and unexpected?
<andrewrk>
just prints a stack trace
<hopppetosse>
speaking of the unused code thing, how would you feel about including a compile flag to enable unused functions checks?
<andrewrk>
hopppetosse, I need to make an issue for this too. I'm still writing up the other one
<zesterer_>
Also... I invented an allocator for my kernel that's pretty fast and incredibly simple to implement and has support for free() too. I've not seen the design used anywhere else, which I thought a little weird. Fancy me writing it up for Zig's standard library some time?
<andrewrk>
zesterer_, definitely. there's std.heap which will end up having a variety of allocators to choose from
<MajorLag_>
I could use some more function reflect, so I can print out the while function signature, and preferably it's name or something. Very much on the "it'd be nice to have" list though.
<MajorLag_>
s/while/whole/g
<andrewrk>
MajorLag_, it's definitely planned. feel free to make an issue, maybe I'll have some inspiration on the airplane tomorrow :)
<MajorLag_>
and access to the hidden union tag would let me print the value of those too. right now I just print the union and it's member types.
<zesterer_>
MajorLag_: Can you not just print @TagType(my_union)?
<andrewrk>
I think I figured out how we can have runtime noalias safety
<andrewrk>
which makes me want to turn noalias on by default for all pointer parameters (you'd be able to disable it per function)
<MajorLag_>
generally speaking I'm all for safety as long as I can disable it.
<andrewrk>
that would destroy the only thing rust has going for it in terms of performance vs zig
<andrewrk>
MajorLag_, ahhh I see why you wanted access to the secret field
<MajorLag_>
Except for unions, I can basically print out an entire struct as it would appear in source, plus the values of each field. Which is great.
<andrewrk>
would you expect the printing code to work in --release-fast mode?
<MajorLag_>
Yeah, I can see how that'd be an issue for secret field
<MajorLag_>
It could be special cased to say "sorry bro, we're in release mode" and fall back to what it does now.
<andrewrk>
MajorLag_, in gdb if you print a union, it prints every possible value
<andrewrk>
e.g. here's what it would look like if it were A, here's what it would look like if it were B
<MajorLag_>
I feel like I may go down the rabbit hole of adding netcode to this toy raycaster just to experiment with comptime encoder/decoder generation.
<andrewrk>
if you do I'll try to fix the comptime bugs we found
<MajorLag_>
andrewrk, won't that get dangerous if any of them are pointers? I suppose I don't have to try and follow pointers that are in a union though.
<andrewrk>
I mean try to fix them in time for you to do your thing
<andrewrk>
yeah, gdb doesn't follow pointers
<MajorLag_>
Currently I do follow pointers. I like that I have so much information I can tag my outputs with ? or & or even ?&&&&&[]u8 or whatever if that's how it's accessed.
<MajorLag_>
I think before I do any netcode though I should see about adding some version of this to fmt. fmt is a little limited right now.
tjpalmer has joined #zig
<tjpalmer>
I didn't follow why pointer sigil needs to change, but is * also off the books? Using * like C might have its downsides, but it's familiar to people. And you also show using * to capture pointers, like |*whatever| {...}, in the docs, though I haven't tried that use case yet.
<tjpalmer>
I wasn't sure why it was * there and & elsewhere.
<GitHub14>
[zig] zesterer opened pull request #734: Made Zig support tabs (master...master) https://git.io/vNbSn
<zesterer_>
tjpalmer: Personally, I think '@' after the expression should be used for dereferencing. It gets rid of what I all "chain ambiguities" in C.
<zesterer_>
For example, the expression "*a.b.c" leaves it ambiguous as to which result the dereference applies to. We know it applies to the last one, but then that leaves ugly syntax like this: "(*a.b).c"
<zesterer_>
A better alternative is this to place the reference after the pointer, leading to nice syntax like this: "a.b.c@" or "a.b@.c"
<zesterer_>
*dereference
<zesterer_>
andrewrk: Thoughts about the above? ^
<benzrf>
lol @ "*dereference"
<zesterer_>
benzrf: Oh God I didn't notice that :D
<benzrf>
i thought the issue was just with the take-a-reference operator
<benzrf>
since it overlaps with the reference-type operator
<zesterer_>
Oh? I admit, I didn't read the whole conversation
<MajorLag_>
andrewrk: so @offsetOf doesn't work for unions, which makes sense, except that unions have that secret field (and probably do some alignment stuff), so I can't just ptrCast to get at the values.
<benzrf>
if i write "&foo" there's an ambiguity of whether i mean the type of pointers to the type foo, or whether i mean a pointer to the variable foo
<benzrf>
strictly speaking
<benzrf>
im not sure it's actually that much of a problem
<benzrf>
er, i /assume/ this is what the issue is about anyway >.>
<zesterer_>
benzrf: Urgh yeah, that's not nice.
<benzrf>
the issue arises since type expressions are value expressions
<zesterer_>
'~' is way better for that
<benzrf>
is that a c++ ism
<benzrf>
22:00 <zesterer_> Tagged unions that don't break the type system, like in Rust
<benzrf>
what do you mean by that :p
<benzrf>
er, :o
<zesterer_>
benzrf: In Rust, it's impossible to circumvent the type system without 'unsafe'. The syntax forces you to consider that a tagged union may not be of the type you think it is.
<benzrf>
wait
<zesterer_>
i.e: The compiler will get upset if your match expression doesn't account for edge cases
<benzrf>
oh, you mean "(tagged unions that don't...), like in rust"
<benzrf>
and not "tagged unions that don't (break, like in rust)"
<zesterer_>
Yes :D
<benzrf>
ah
<zesterer_>
Damn the English language and its syntax ambiguities
<benzrf>
well, i guess the comma technically disambiguates
<zesterer_>
I think there's technically still ambiguity even with the comma :\
<benzrf>
comma associates less tightly than space
<benzrf>
22:58 <andrewrk> which makes me want to turn noalias on by default for all pointer parameters (you'd be able to disable it per function) 22:59 <andrewrk> that would destroy the only thing rust has going for it in terms of performance vs zig
<benzrf>
this is still wrong
<benzrf>
noalias only accounts for stuff that happens within a lexical scope
<benzrf>
rust has *global* aliasing guarantees
<benzrf>
oh wait actually let me double check what noalias does exactly before doublign down
<tjpalmer>
I was refering to point type sigil because I through andrewrk said he had to change it. While postfix dereference has its virtues, I'm concerned about any churn that's not vital. (I really want to see 1.0, though I have to admit coroutines rock.)
<tjpalmer>
Pointer type, I meant.
<benzrf>
andrewrk: yeah - unless im misunderstanding, doing "*foo = 3; some_func(foo); return *foo" is not safe to turn "return *foo" into "return 3"
<benzrf>
but in rust, global guarantees and distinguishing between mutable and immutable pointer types means you can safely do stuff like that
<tjpalmer>
On breaking change (in std) recommendations, while I've never used a custom allocator in C++, I'm concerned that C++ folks will complain about function-pointer-based allocators, since my understanding is that allocator template parameters in c++ wouldn't need function pointers.
<MajorLag_>
I wonder if the better way to go about it wouldn't be to just add some kind of builtin instead. var foo = @type(i32); var bar = &foo; var baz = @type(&foo); or something like that.
<benzrf>
that doesnt make snse to me MajorLag_
<benzrf>
first: are you proposing a new syntax that goes inside @type?
<benzrf>
distinct from expression syntax i mean
<tjpalmer>
Maybe standard cost of allocation far outweighs that, but if it came back to bite, it could require std reworking. Again, I've never used custom allocators before, so I have no experience. But I'm off the other conversation topic. Just wanted to get it out there.
<benzrf>
actually hmm i guess that could work
<benzrf>
capture variables in the scope but dont otherwise allow expression syntax?
<benzrf>
although id definitely think itd be a good idea to use a unique construct instead of a pseudo-function-call
tjpalmer has quit [Quit: Page closed]
<benzrf>
given that it'd be parsed differently
<zesterer_>
tjpalmer: With regards to what you say about "churn": it's better to make changes now while the language has fewer adopters and less dependent code. Make as many breaking changes as possible now such that the resultant language is sensible and stable by the time the user base grows
hopppetosse has quit [Ping timeout: 264 seconds]
<MajorLag_>
benzrf, basically the idea is that no matter what happens inside @type(), it will return a type, and anything that happens outside it or it's builtin bretheren (@typeOf, @MemberType, etc) isn't.
<zesterer_>
MajorLag_: That seems like it major breaks the idea of consistent syntax
<zesterer_>
*majorly
<MajorLag_>
maybe, I'm just not wild about a new sigil
<zesterer_>
What else is the sigil used for?
<MajorLag_>
it's the pointer sigil, it's just ambiguous in certain cases if you want a pointer type or a pointer to a variable of type type.
<benzrf>
yeah those cases arent terribly common
<MajorLag_>
well I'll keep thinking. maybe I'll have a better idea.
<MajorLag_>
I'm unclear on this: does type type exist at all in runtime?
<zesterer_>
In my language-that-was-not-to-be, I used prefix '@' for referencing and postfix '@' for dereferencing. AFAIK, there aren't any syntax ambiguities (although I might have missed something)
<MajorLag_>
Odin does that with ^
jfo has joined #zig
<MajorLag_>
Ok, so a quick test says no. type type only exists at runtime. Given that, I don't think having to wrap type assignments in @Type is that bad, because they're already special.
jfo has quit [Ping timeout: 256 seconds]
<zesterer_>
It seems like a lot of syntactic cruft and breaking of the parser just to avoid using '~'.
<zesterer_>
It means Zig can no longer be parsed by a recursive decent parser, which adds a load of complication to the compiler
<MajorLag_>
s/runtime/comptime/
<zesterer_>
Or rather it can, but you have to make a special case for the @type() function in the parser code rather than later on in compilation
<zesterer_>
Which is weird and annoying and also breaks the intuition humans have for how the language works too
<MajorLag_>
Not being a compiler writer, I'll take your word for it about parsing. It just seems strange to me to have & for normal values and ^ for type values.
<MajorLag_>
Though admittedly, on reflection, it does make sense that "this is a pointer to a thing" and "give me the address of a thing" are separate.
<zesterer_>
Trust me, not having context-free ambiguity is awesome in a language. It means you don't have to make the parser way more complex by keeping track of what identifiers are as you parse (or otherwise bake functions like @type() into the parser itself). That means faster compilation, easier to write formatting and syntax tools, and generally just a lot of extra good stuff
<MajorLag_>
In some other languages that do this sort of thing, type isn't a special type so much as just a const pointer to a struct with information about a type. Which does seem easier to reason about.
<MajorLag_>
but they have different ways of doing generics, so they don't need to do (@typeOf(x))(y) or anything like that.
<MajorLag_>
I guess I'll just see how it shakes out.
jfo has joined #zig
jfo has quit [Ping timeout: 276 seconds]
davr0s has joined #zig
jfo has joined #zig
jfo has quit [Ping timeout: 240 seconds]
jfo has joined #zig
jfo has quit [Ping timeout: 240 seconds]
Hejsil has joined #zig
jfo has joined #zig
tiehuis has joined #zig
davr0s has quit [Quit: My MacBook Pro has gone to sleep. ZZZzzz…]
davr0s has joined #zig
davr0s has quit [Client Quit]
cenomla has quit [Quit: cenomla]
dd3 has joined #zig
<zesterer_>
Does an ordinary type implicitly caste to a tagged union if the tagged union contains that type?
<zesterer_>
i.e: Can I do this? "fn f(val: TaggedTypeContainingI32) void {} { f(0); }"
<zesterer_>
tiehuis: Although not including it is understandable due to ambiguity between similar variants
<tiehuis>
yeah, it would only really have a use case on specific variants which would be a bit inconsistent
<tiehuis>
plus it also means you don't know what tag is being assigned at the initialization site without referring back to the declaration
<tiehuis>
which is a point against readability/explicitness
<zesterer_>
In that case, I have one more question: is 'var' what I think it is? Does it allow you to infer both the type and the data of a value without having to explicitly pass both to a function?
<tiehuis>
yes, it pretty much allows you to pass anything to a function
<zesterer_>
Perfect
<tiehuis>
it's useful at the moment for duck-typing and getting some pseudo polymorphism i find, and for some simple wrapper functions which may have slightly different actions based on the type
<zesterer_>
Zig doesn't support overloading, does it?
<tiehuis>
no
<zesterer_>
In which case, var becomes useful for that.
<zesterer_>
In some cases
<tiehuis>
yeah, for simple cases where it changes only based on type. the math functions use var extensively for f32 and f64 on the same functions
<tiehuis>
pretty much _Generic in c, but a bit more powerful
<zesterer_>
Actually, full overloading is probably possible with variadics. They'd be evaluated at compile-time after all.
zesterer_ has quit [Remote host closed the connection]
jfo has quit [Ping timeout: 276 seconds]
jfo1 has joined #zig
jfo1 has quit [Ping timeout: 240 seconds]
tiehuis has quit [Quit: WeeChat 2.0.1]
hoppetosse has joined #zig
jfo1 has joined #zig
jfo1 has quit [Ping timeout: 240 seconds]
tjpalmer has joined #zig
tjpalmer has quit [Client Quit]
davr0s has joined #zig
zesterer has joined #zig
jfo1 has joined #zig
davr0s has quit [Quit: My MacBook Pro has gone to sleep. ZZZzzz…]
Tobba has quit [Read error: Connection reset by peer]
jfo1 has quit [Quit: WeeChat 1.9.1]
Tobba has joined #zig
Hejsil has quit [Ping timeout: 260 seconds]
hoppetosse has quit [Ping timeout: 248 seconds]
hoppetosse has joined #zig
<andrewrk>
zesterer, I'm also considering removing var args functions and adding tuples
<zesterer>
andrewrk: As in variable-length tuples?
<andrewrk>
yes
<andrewrk>
std.debug.warn("a = {0}, b = {1}", [a, b]);
<andrewrk>
not sure what the tuple syntax would be, but there's one idea
<andrewrk>
a tuple has comptime known length and types, and runtime known values
<zesterer>
I assume it'd be created inline?
<andrewrk>
what do you mean?
<zesterer>
Doesn't matter. I misread something earlier
<zesterer>
Would it support destructuring? Destructuring is cool. Really intuitive syntax sugar.
<andrewrk>
yes
<andrewrk>
var a, const b = [x, y]
<andrewrk>
most useful to initialize multiple variables from a block
<zesterer>
Nice. That sounds like it could create some very pretty, very clean code
<zesterer>
Also (I'm sure you know this already) it would be nice if there was a more idiomatic way to print to stdout than doing "var stdout_file = try io.getStdOut(); var stdout_file_stream = io.FileOutStream.init(&stdout_file); const stdout = &stdout_file_stream.stream; stdout.print("Hello, World!\n");"
<zesterer>
:D
<andrewrk>
are you looking for std.debug.warn?
<andrewrk>
if you are actually trying to print to stdout, don't you care about whether the pipe fails?
<zesterer>
I do, but they should probably be accumulated into a single error that is returned by a std.print() function. Something generic like PipeFailedError.
<zesterer>
In 99% of cases, you don't need to know or care *why* the printing failed: only that it did
<zesterer>
For those 1% of cases there is the current syntax
<andrewrk>
getStdOut can fail on windows
<zesterer>
I understand that. All of those errors (errors when getting the stdout file handle, errors when writing to the pipe, etc.) could be combined into a single PipeFailure error which makes syntax simpler.
<andrewrk>
that API is less powerful
<andrewrk>
handling errors is easy, just do it
<MajorLag_>
andrewrk: not sure how I can get the possible values for a union in reflection. @ptrToInt/@intToPtr gives strange results, presumably because of alignment and/or secret field. @offsetOf doesn't work, which I think you'd mentioned.
<andrewrk>
MajorLag_, I'll think about it. I don't have an answer for you right away
<MajorLag_>
No rush.
<zesterer>
andrewrk: Power at every opportunity if often not the best solution to a problem. It seems needlessly unreasonable to require that 4 separate lines of code, none of them particularly short, must be manually called before a program may print to the screen using stdout.
<zesterer>
Or, even better, have a dedicated error for each kind of failure but still pass it through the one print function
<andrewrk>
on windows that makes an unnecessary syscall for every call to that function
<zesterer>
Make the stdout stream a singleton, of course
<andrewrk>
that's not concurrency-safe
<andrewrk>
hm that last thing, might be ok
<zesterer>
And of course Zig has no global constructors so calling it on program start is impractical (and adds overhead)
<zesterer>
Hmmm. This problem must have an elegant solution.
<andrewrk>
really, 90% of the time people want std.debug.warn
<andrewrk>
and the other 10%, just have the 2 lines, it's not that bad. you're going to set up stdout 1 time over the course of an entire project, and then never touch that code again
<andrewrk>
and then there's no hiding how the underlying OS APIs actually work
<zesterer>
Perhaps you're right. Can "Expose the problem space transparently" become a Zen objective? :D
<andrewrk>
yes
<andrewrk>
I like that a lot actually
<zesterer>
I don't think it's explicitly covered by any of the others
<zesterer>
"Edge cases matter" only partially covers it
<GitHub89>
[zig] corngood opened pull request #738: WIP: make lld include paths private (master...cygwin-fixes) https://git.io/vNN00
jason__ has joined #zig
jason__ has quit [Ping timeout: 260 seconds]
hoppetosse has quit [Ping timeout: 240 seconds]
hoppetosse has joined #zig
Hejsil has joined #zig
<zesterer>
andrewrk: How's this for an acceptable alternative? Certainly simplifies the syntax. https://pastebin.com/u3n37w63
<andrewrk>
I don't think that compiles
<GitHub130>
[zig] andrewrk closed pull request #738: WIP: make lld include paths private (master...cygwin-fixes) https://git.io/vNN00
<GitHub69>
zig/master 15eb28e Andrew Kelley: Merge pull request #738 from corngood/cygwin-fixes...
<GitHub69>
zig/master 4ec856b David McFarland: make lld include paths private...
<zesterer>
andrewrk: Compiles fine on mine. Only change I've made from the master branch is reenabling tabs as whitespace. Other than that, it's all working Zig.
<andrewrk>
let me look again
<andrewrk>
oh, I see
<andrewrk>
what about the other useful methods of OutStream? what about if you wanted to pass a std.io.File of stdout?
<zesterer>
Then you're stuffed. This is just a helpful wrapper for stdout specifically. Although I'm sure it could be adapted accordingly.
davr0s has joined #zig
davr0s has quit [Quit: My MacBook Pro has gone to sleep. ZZZzzz…]
davr0s has joined #zig
<MajorLag_>
I'm curious what the correct behavior of @offsetOf should be when it is fed a 0 byte field.
hoppetosse has quit [Ping timeout: 276 seconds]
zesterer has quit [Quit: zesterer]
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…]
<MajorLag_>
My problem with comptime is that it isn't obvious what will run at comptime vs runtime. I thought @offsetOf throwing a compiler error is something I wouldn't be able to branch my way out of, for instance.
<MajorLag_>
Could just be because I'm not used to it I guess.
return0e has quit [Read error: No route to host]
return0e has joined #zig
<andrewrk>
MajorLag_: why couldn't you branch your way out of it?
<andrewrk>
In fact you can branch your way out of compile errors
hoppetosse has joined #zig
arBmind has joined #zig
cenomla has joined #zig
hoppetosse has quit [Ping timeout: 256 seconds]
<MajorLag_>
Yeah, I know that from trying, but it the logic of it wasn't obvious to me. It seemed to me that the values would be filled in at comptime while the branch would happen at runtime. I see now it's more like anything that requires a comptime value to evaluate happens at comptime.
davr0s has joined #zig
dd3 has joined #zig
davr0s has quit [Quit: My MacBook Pro has gone to sleep. ZZZzzz…]
<noonien>
andrewrk: Hello, have you given vtables/interfaces any thoughts recently?
davr0s has joined #zig
ofelas has quit [Ping timeout: 240 seconds]
davr0s has quit [Quit: My MacBook Pro has gone to sleep. ZZZzzz…]
davr0s has joined #zig
cenomla has quit [Quit: cenomla]
hoppetosse has joined #zig
ofelas has joined #zig
<hoppetosse>
noonien: I'm not sure what the plans are, but I'm convinced it can be implemented as a library =P
<noonien>
i don't see a point in implementing it as a library
<noonien>
from what I can tell, the stdlib can greatly benefit from them
<hoppetosse>
Yeah, I agree with you completely, I was just trying to make a point about how much can already be accomplished
<hoppetosse>
There's definitely been discussions about interfaces/traits
<hoppetosse>
Zig has a sort of "trait pattern" - look at the Allocator type
<hoppetosse>
struct
<noonien>
i had a quick glance at the stdlib code, handling streams seems to be as bad as c++, if not even worse
<hoppetosse>
the stdlib is young a lot needs to be ironed out
<hoppetosse>
the language itself isn't fully ironed out, but it's been evolving at a great pace
<noonien>
yeah, i've noticed the pattern of structs with function fields, seems rather cumbersome
<noonien>
streams seem to be handeled in the same way
<hoppetosse>
yeah, I guess you could call them manual vtables
<hoppetosse>
I've been meaning to ask andrewrk about this too actually
<noonien>
i've suggested taking inspiration from go interfaces. i really like that any type that satisfies the interface automatically implements it
<hoppetosse>
it goes well with zig's compile-time duck typing ideas
<noonien>
just wanted to ask if any futher thought has been given, since if the stdlib matures further, i'm afraid the current pattern of callback tables will have more adoption
davr0s has quit [Quit: My MacBook Pro has gone to sleep. ZZZzzz…]
dd3 has quit [Ping timeout: 256 seconds]
<hoppetosse>
andrewrk: are tuples necessarily incompatible with vararg params?
<hoppetosse>
I'd very much like to be able to store sets of function arguments