<fubd>
then everywhere I access the vector, I have to use my_vec.data[1]
<scientes>
that isn't a vector
<scientes>
use (comptime vlen: u32, v: @Vector(vlen, foo))
ky0ko has quit [Disconnected by services]
ky1ko has joined #zig
<fubd>
I was scared away by the docs on using @Vector yet
<fubd>
but if anyone has actual game code that is using it and wants to share examples I'd love to see
<fubd>
s/game/anything
<daurnimator>
fubd: yeah @Vector needs more work. scientes has been doing most of it.
kristoff_it has joined #zig
<fubd>
awesome :)
<scientes>
I really need inferred return types to be implemented
<scientes>
I know that can be a foot-gun, but it means that much more can be implemented in user-space
<fubd>
oh yeah, i ran into that with something else...
<scientes>
also, maybe someone could help with C ABI for @Vector
<fubd>
daurnimator: one thing that nags at me about using :var for overloading is definitely that you use the clarity of seeing function types for each parameter in the function definition
kristoff_it has quit [Ping timeout: 248 seconds]
<fubd>
in odin you can just say
<fubd>
foo :: proc{
<fubd>
and then look to the definitions of each function for the possible matches
<fubd>
i suppose having proper pattern matching could let you unpack types right in the first couple lines of a var function
<fubd>
but yeah it definitely feels less readable/discoverable
<fubd>
\/toolable
<scientes>
yeah but the only "fix" for that is something like Haskell's type system, which honestly I don't understand
<scientes>
this is kind of a side-effect of powerful comptime
<fubd>
the syntax for explicit function overloading couldn't just write out the comptime function for a set of type switches?
<Tetralux>
It's not clear why burying what's happening from the compiler is useful for that.
<Tetralux>
How are tools meant to determine the overloads if they can't just be told by the compiler?
<Tetralux>
Besides which, having 'overload {}' makes parsing all you need to do to discover it.
fubd has quit [Ping timeout: 260 seconds]
laaron has joined #zig
marijnfs_ has joined #zig
marijnfs has quit [Ping timeout: 245 seconds]
<Tetralux>
I actually quite like `fn { overload1, overload2 }` .. quick to type - easy to understand, surely?
<daurnimator>
Tetralux: I'm not a fan.... requires a lot of context to understand
<Tetralux>
A lot of context? You mean like is it `fn(` or `fn{` ? xD
<Tetralux>
Gotta say - that seems fairly trivial to me.
<Tetralux>
Did you have a specific example in mind?
<daurnimator>
Tetralux: like... why would that not be an array initialiser of functions?
<daurnimator>
i dunno, it just looks quite close to other things to me.
<Tetralux>
Wouldn't functions need to have the parens `fn()` so that you know it takes no args?
<daurnimator>
no? it could be referencing functions in scope
<daurnimator>
the only difference would be [_] preceding it
<Tetralux>
I mean, if you have fns that have different signatures -- or the same for that matter -- and you wanted to store them in a typed array, you would not be able to specify them as the eltype because the signature is part of the type.
<Tetralux>
But also, `fn` is not a function pointer, `*fn` is.
<scientes>
the way of having a function without a type signature, not sure about that
<scientes>
`naked` is a similar concept
<Tetralux>
Maybe you get around it with `.{initWithString, initWithSelf}`
<scientes>
no, don't need new syntax
<Tetralux>
Yeah, but we're getting that syntax anyway right.
<Tetralux>
the `fn {` seems weird in that though.
<scientes>
now its naked fn() {
<Tetralux>
`init = fn {` that is.
<scientes>
init = naked fn() {
NI33_ has quit [Ping timeout: 245 seconds]
Tetralux has quit [Ping timeout: 245 seconds]
<nairou>
So this is confusing... I wrote a build.zig to compile an existing C-only program (no zig code). Compiles fine, but immediately crashes when run. I try to debug it, and the very first thing it does (before even reaching main) is hit a panic. zig code. "Cannot access memory at address 0xfffffffffffffff8". I'm not sure where to start with this. Why is there zig code in here? What would cause it to crash before it even began?
laaron has quit [Remote host closed the connection]
laaron has joined #zig
<gonz_>
04:10:50 <Tetralux> If I had my way, we'd already have function overloading.
<gonz_>
If everyone had their way with one thing we'd have everything.
mikdusan1 has joined #zig
<gonz_>
Overloading is obviously popular, I'm not discounting that. Most bad features that complicates languages at the very least start out popular enough to be implemented.
<gonz_>
This is why I was trying to stress values as an up-front thing a while ago. If you have certain values that you can point to and say "These things are more important than X, and this compromises them" it's much easier to coalesce on these kinds of things.
<gonz_>
But also to actually have concrete examples would be good.
mikdusan has quit [Ping timeout: 268 seconds]
<gonz_>
It would be more helpful if people could infer easily that "my unwillingness to type 10 lines is not as important for zig as the willingness to keep odd keywords and complication out of it"
rom1504 has joined #zig
laaron has quit [Remote host closed the connection]
laaron has joined #zig
gamester has quit [Quit: Leaving]
NI33_ has quit [Ping timeout: 272 seconds]
Ichorio has joined #zig
ntgg has joined #zig
<mq32>
hey
NI33_ has joined #zig
Ichorio has quit [Ping timeout: 264 seconds]
<samtebbs>
mq32: o/
<mq32>
i had a realization the last days:
<mq32>
if zig gets both the function literals (#1717) and the proposed object semantics (#2938), making closures would be quite elegant via interfaces
<mq32>
having a generic interface Callable(T:type) that has only one function "invoke" with the same signature as T
<mq32>
a closure could then be an object that just implements this interface
_whitelogger has joined #zig
ntgg has quit [Ping timeout: 245 seconds]
andersfr has joined #zig
andersfr has quit []
<samtebbs>
Then you'd need to figure out how capturing would work
ntgg has joined #zig
<samtebbs>
You could go with the C++ route and make each "closure" a struct that has a field for each variable captured, and then assign to those fields when creating the closure
<samtebbs>
The suitability of that to Zig is up for debate though
<mq32>
it seems like the only possible way to do so
<shachaf>
D has a nice feature for closures that are only used while a stack frame is active, where captures are made relative to the stack frame.
<mq32>
that only works when you have stack frames
<shachaf>
Yes, it's not suitable for general closures.
<mq32>
samtebbs: the idea behind this interface thing is: i *could* implement closures with interfaces in userland, so a capturing closure would just be a syntactic sugar coating to remove redundant code
<mq32>
let's say we capture everything by-value, but expose the captured variables as pub struct fields
laaron has quit [Remote host closed the connection]
laaron has joined #zig
laaron has quit [Remote host closed the connection]
laaron- has joined #zig
<samtebbs>
Looks good to me
<daurnimator>
what if closures took a @Frame?
<mq32>
daurnimator: i don't think @Frame and closures are compatible without doing more hacks
<daurnimator>
Aren't @Frames essentially a struct of local variables to a function?
<daurnimator>
I guess with a closure you'd want to refer to multiple parent scopes...
<mq32>
it depends on how @Frames are generated
<mq32>
if they capture all local variables, it would be inefficient because closures can allocate all local variables on the stack and require only the captures to be stored
<daurnimator>
mq32: I would think that they are a union of all local variables in scope at the various suspend points
<daurnimator>
though now I'm having some memories bubble up of that time I implemented closures in another thing...
<daurnimator>
let me go read my old code for a min
<mq32>
👍
<daurnimator>
okay nope; that implementation used stack indirection. let me go check lua's which I've audited before...
<daurnimator>
okay. lua's implementation is at least more translatable to zig; but it may violate the "hidden control flow" rule.... so we may need to make things explicit
<daurnimator>
In lua, *if* a function created a closure, then when it returns, it "closes" that closure.
<daurnimator>
what does that mean? => closure always use values by reference; however, each variable in the closure has an additional "hidden-ish" field
<daurnimator>
when a closure is "closed", then it swaps the reference from a reference to the parent's variable, to storing it in the hidden field
<daurnimator>
Lets imagine the following zig code: `fn foo() (fn() i32) { var x = getx(); const bar = fn() u32 { return x; }; return bar; }`
<daurnimator>
at the point *before* foo returns, then bar's `x` points to the x on the stack. after the `return`, it has to be captured inside of `bar`
<daurnimator>
mq32: ^ make sense?
<mq32>
i'm trying to follow
<mq32>
but if i understand correctly, this would require move semantics, right?
<mq32>
(when the closure is moved(closed), the reference stored in the closure must update)
<daurnimator>
yes.... though you may want to define what you mean by "move semantics"
<mq32>
(moving the closure would require to change the captured reference)
<daurnimator>
what do you mean by "moving the closure"
<mq32>
copying/returning/otherwise changing its address
<daurnimator>
we haven't got to "moving closures" yet (which is another topic we should get to). with the example above the value of `x` will get moved though
<mq32>
so our closure requires to have some transparent field "x : *i32" and "x_backing_store : i32" and as soon as we close the closure, x will point to the backing_store, right?
<daurnimator>
yep
<mq32>
what value will bar reference, then?
<mq32>
because returning the closure "bar" in the example will "change" the location of x
<daurnimator>
ah yes. that's what you mean
<mq32>
address of x_backing_store will change then
<mq32>
also when i copy the closure value
<daurnimator>
I haven't brought that up yet because copy elision semantics means we haven't hit that yet ;)
<mq32>
heh
<mq32>
assuming i would only use the return value at the point where i got it
<mq32>
var a = make_closure(); var b = a; // this would break stuff
<daurnimator>
mq32: well one thing is that it means the return value is a "fat function"
<daurnimator>
==> it's more than a function pointer getting returned; it's a function pointer + the closed variables
<mq32>
that's clear
<mq32>
but we just said that we require a backing store for the closed variables
<daurnimator>
so... what if it returned a value of type @Closure
<mq32>
and a reference that may be changed
<mq32>
imho for most usecases it would be sufficient to have "downward closures" (so passing them *down* the call stack, not upwards)
<mq32>
creating closures that allow this is easier (proposed solution is above)
<mq32>
but: having full-featured closures would be still nice
<daurnimator>
what would be the point of a "downward closure" as you call them?
<mq32>
it's simpler in terms of memory management, implementation and explanation
<mq32>
(because every captured variable just needs to be a pointer to the original var
<mq32>
but that will not work if you leave your current stack frame
<daurnimator>
I meant in terms of usage
<daurnimator>
and also... I wouldn't call this a closure
<daurnimator>
the whole thing about closures is the ... closing :P
<daurnimator>
otherwise they're just "functions inside of functions" or something
<mq32>
ah
<mq32>
it's an improved callback thing
<mq32>
so passing a compare function with dynamic comparison value
<daurnimator>
So what if we had... `const bar = @Closure(somefunc); var x = bar.valueOf("x"); bar.close("x", &x);`
<daurnimator>
mmm no. that wouldn't work well with the above example
ntgg has joined #zig
laaron- has quit [Remote host closed the connection]
laaron has quit [Remote host closed the connection]
laaron has joined #zig
nairou has joined #zig
ntgg has quit [Read error: Connection reset by peer]
batok has joined #zig
andersfr has joined #zig
lluchs has joined #zig
andersfr has quit []
marijnfs has quit [Remote host closed the connection]
marijnfs has joined #zig
laaron has quit [Remote host closed the connection]
Akuli has joined #zig
laaron has joined #zig
<fengb>
Do processors naturally span alignment boundaries? e.g. struct { a: u29, b: u6, c: u29 }
<daurnimator>
'processors'?
<daurnimator>
fengb: in general: no unless you use `packed`
<fengb>
I mean can CPUs even access that type of data or should I split it out to pairs of u29 + u3 and merge the u6 together manually
<Tetralux>
I feel like that version of a closure is WAY too overcomplicated for zig.
<fengb>
This scrollback is long
<Tetralux>
The idea of an interface for a closure is also a no-no. I hate FnOnce/FnMut in Rust. It's not clear what those names even mean at face value.
<Tetralux>
Things should be trivial to understand by their transparency.
<Tetralux>
Otherwise, it becomes like exceptions: I don't really know how it works, but it does.
<Tetralux>
I'd consider that a bad thing.
<fengb>
We need something like an interface if we have fat closures
<Tetralux>
I'm not sure we even need closures.
<fengb>
That's a different topic then
<Tetralux>
Whereas, the embedded type semantics I'd probably use a decent amount.
<Tetralux>
I'd rather have locally-defined fns than closures personally.
<gonz_>
Tetralux: The issue is mostly that everyone has their own pet feature. I think I agree mostly with what you said but I also am skeptical that my personal feelings about "Things that would be nice to have" have much merit.
<Tetralux>
I mean... things are emperically useful.
<fengb>
Therefore C++ is the most useful >_>
<Tetralux>
You can look at code that uses certain features.
<mikdusan1>
Tetralux: what do you mean by "locally-defined fns" ? we already can define fns
<Tetralux>
See how readable, understandable, and neat it is.
<gonz_>
Tetralux: The usefulness of things can be less than the complication they add in the long run.
<Tetralux>
And think about how features could be used, maybe gravitate usage towards the best one.
<Tetralux>
The point being: The syntax is the same regardless of declaration scope.
<mikdusan1>
ok so just sugar. we can do that today with struct.
<Tetralux>
In _no_ way is that sugar.
<gonz_>
I keep harping on about explicitly stating values and here's where I think that's useful. Making clear what zig emphasizes and examples of what that encompasses is valuable.
<Tetralux>
It just means "f is not visible outside this scope."
<Tetralux>
But it's a static fn, _just_ like 'f' is.
<fengb>
I think anon functions need local definition semantics
<Tetralux>
Wait - why would I want a struct in order to declare a fn locally?
<mq32>
<Tetralux> The idea of an interface for a closure is also a no-no.
<Tetralux>
That makes no sense xD
<fengb>
Implementation detail. Functions can only go "inside" of structs
<Tetralux>
An incorrect detail. xD
<Tetralux>
That comment is somewhat tongue-in-cheek, since
<Tetralux>
It's VERY clear what that paste does.
<mq32>
why is that a no-no? *if* we got interfaces, it would be an "only one way to do things"-thingy with syntax sugar for trivial @Callable() interfaces
<Tetralux>
We don't need anything so opaque, for one thing.
<daurnimator>
which could be pass 2 arguments automatically
<daurnimator>
or a⭆foo() to pass 4 arguments ;)
rsdimenus has joined #zig
<rsdimenus>
has anyone done a stack allocator in zig yet?
<daurnimator>
rsdimenus: huh? what do you mean by that?
<daurnimator>
rsdimenus: just use a FixedBufferAllocator on some stack allocated memory
<Tetralux>
Is the idea for interfaces that they are an comptime-only thing that doesn't make it to machine code?
<Tetralux>
Or are they really more a Go-like thing?
<fengb>
We probably need something like vtable dispatch
<Tetralux>
That sounds awful.
<scientes>
ehhhh
<scientes>
i don't want a runtime
<fengb>
You don't but people do
<daurnimator>
tiehuis has gone through 4 or 5 different interface proposals
<daurnimator>
you should have a look at them
<Tetralux>
I'd rather it was just the structs that implement the interface and the interface it just a way of saying "yes, this struct must have these methods" or something.
<fengb>
tgschultz also has some ideas
<gonz_>
rsdimenus: There is a `StackFallbackAllocator` in `std.heap`
<daurnimator>
oh right sorry it was tgschultz not tiehuis
<mq32>
comptime solution for interfaces is quite restricted and we already have that (just pass a var parameter and validate it's interface)
<rsdimenus>
gonz_: thanks that's what I'm looking for I think
<fengb>
Current ideas are keeping it in userland unless proven otherwise
<gonz_>
rsdimenus: I suspect so too, but honestly I have neither used it nor really read the source, I've just seen it in passing.
<fengb>
@fieldParentPtr can be used as an adhoc interface, but it's a slight footgun
<fengb>
That's how we currently do it and it works, but there's a few issues
<rsdimenus>
basically i just have a bunch of work to do in a function and I want to free the whole chunk in a block
<daurnimator>
fengb: I've been messing around in traceback generation and the current Steam/SeekableStream interface is *terrible*
<mq32>
fengb: vtable-interfaces would require a "fat pointer" with pointer+vtable
<mikdusan1>
weakness with go is looking at a struct and it's implementation, how do you tell that oh this struct conforms to an interface by... you know... looking at the code
LargeEpsilon has quit [Ping timeout: 245 seconds]
<mq32>
mikdusan1, yeah i prefer the explicit statement: "i want to implement this interface" better
<fengb>
But the strength is you can define adhoc partial interfaces and don't need to muck around with consumed code
<mq32>
rust does that for traits with separated blocks
<mq32>
fengb: yeah i can see that point beeing a good argument
<fengb>
Hey wat, you're not allowed to agree with me on the internet
<mq32>
ha! i'm breaking the law of the internetz!
<mq32>
i really like that we can explore programming language concepts here without everyone saying: "this is stupid"
<companion_cube>
mq32: this is stupid
<mq32>
kek
<companion_cube>
(don't thank me)
<scientes>
mq32, hehe
<scientes>
I got good feedback on my SIMD questions here
<fengb>
There are no bad ideas, only tradeoffs
<scientes>
it was much faster than github
<companion_cube>
I don't know, I feel like some things truly are bad ideas
<companion_cube>
like auto coercions à la JS' ==
<mq32>
fengb: we could do a malloc on every local variable we have and store them in a malloc'd frame for every function call!
<fengb>
I'm trying to be nice :(
<companion_cube>
:D
<mq32>
companion_cube: I can find positive arguments for the == thing :D
<mq32>
oh and another one: we could make the default number type a 16 bit half-float!
<mq32>
got to go
<fengb>
The only number type
<companion_cube>
why not f17? 🤔
<fengb>
Okay, let's remove JS from the equation >_>
<scientes>
yeah lets do NAN packing for no reason at all :)
<rsdimenus>
ah, the bug was actually with SplitIterator
<rsdimenus>
it was returning true for an extra loop than it should have
<andrewrk>
rsdimenus, double check those docs
<andrewrk>
you might be getting mem.separate and mem.tokenize mixed up
<rsdimenus>
no, i can see the docs say that it should return null
<rsdimenus>
but it doesn't
<rsdimenus>
if start and end are both 0, it still returns a valid slice not the '
<rsdimenus>
null value
<nairou>
andrewrk, you asked last night what the error was when my C-only program panics in zig code when I run it. Here's what I see in gdb: https://pastebin.com/CUEgMYFM
<andrewrk>
looks like that behavior is documented in a test case
<andrewrk>
nairou, can I see your build script?
<andrewrk>
I'm guessing you're running an old binary that didn't get updated as you thought it did
<nairou>
I delete zig-cache before builds, to be safe
<rsdimenus>
andrewrk: my apologies, of what use is the first scenario?
<rsdimenus>
eg an empty string
<andrewrk>
nairou, I'm pretty sure you depend on libc
<andrewrk>
but you're not linking it
<andrewrk>
linkSystemLibrary with "dl" "m" "pthread" those are all part of libc. delete those and uncomment your linkSystemLibrary "c"
<nairou>
andrewrk: Thanks. I had that line uncommented before and got all sorts of other linker errors, but now I'm thinking I might know what the other errors come from. I'll try that, thanks.
<rsdimenus>
nevermind, I get it. sorry false alarm!
<andrewrk>
no worries rsdimenus there are plenty of bugs so your paranoia is justified
<rsdimenus>
tokenize is the right one for line parsing, eg tokenize(file_slice, "\r\n")
<nairou>
Yup, that did the trick, after fixing the other link error. Woot
<andrewrk>
rsdimenus, yes and the other one is good for deserializing, e.g. CSV
kristoff_it has quit [Ping timeout: 245 seconds]
kristoff_it has joined #zig
kristoff_it has quit [Ping timeout: 258 seconds]
wootehfoot has joined #zig
Akuli has joined #zig
LargeEpsilon_ has quit [Read error: Connection reset by peer]
LargeEpsilon_ has joined #zig
batok has quit [Remote host closed the connection]
LargeEpsilon_ has quit [Ping timeout: 245 seconds]
kristoff_it has joined #zig
<mq32>
andrewrk, do you have a plan when you stream next?
<nairou>
Yeah I've been loving the status update streams
omglasers2 has joined #zig
<andrewrk>
planning to do one today at 17:00 EDT (3.5 hours from now)
<andrewrk>
oh did the part where it produced invalid LLVM not show up?
<Firefox317>
Nope you didn't run any of the file url download example
<Firefox317>
Before that the stream already went down
<andrewrk>
maybe I'll have the bug fixed by the time it finishes uploading to youtube :)
<fengb>
Twitch said “no more bugs” and it was good
<vramana>
if (T == @field(Node, @memberName(Id, i))) This line is incredibly confusing. @memberName call will gave possible value in Id enum after that @field will be called with Node and a value of Id but that's not a field of Node at all. I am misreading something I don't know what.
<Firefox317>
So you are not gonna continue the stream? Anyways the progress on the branch is awesome
<andrewrk>
Firefox317, I finished it offline and uploading to youtube now. Next week's demo should be more complete
<Firefox317>
Great!
<vramana>
I get it now. It accessing the struct type inside the Node.
<vramana>
I feel so dumb.
<batok>
what was the name of the branch shown in twitch?
Ichorio has quit [Ping timeout: 264 seconds]
<andrewrk>
batok, rewrite-coroutines
<batok>
cool thanks
Firefox317 has quit [Ping timeout: 260 seconds]
laaron has quit [Remote host closed the connection]
laaron has joined #zig
kristoff_it has joined #zig
schme245 has quit [Remote host closed the connection]
kristoff_it has quit [Ping timeout: 246 seconds]
mikdusan1 has quit [Ping timeout: 246 seconds]
<fengb>
These new async semantics are so elegant
<fengb>
Is there something equivalent to @packedSizeOf?
<Tetralux>
Is that not just @sizeOf?
<Tetralux>
Does @sizeOf ignore if the struct is padded or not?
<Tetralux>
Surely not.
<fengb>
@sizeOf is padded size
<fengb>
I’ll just hardcode this stuff for now. No need to make it generic yet