ChanServ changed the topic of #zig to: zig programming language | ziglang.org | be excellent to each other | channel logs: https://irclog.whitequark.org/zig/
davr0s has quit [Quit: My MacBook Pro has gone to sleep. ZZZzzz…]
<very-mediocre>
After reading that tuple discussion, I have a kneejerk reaction to want to generalize arrays, structs and tuples as a single thing since they are all just sequences of fields...
Hejsil has joined #zig
<Hejsil>
very-mediocre, well they do have some differences
<Hejsil>
You can't iterate over fields of tuples and structs at runtime
<very-mediocre>
That's an implementation detail.
m4ge123 has quit [Ping timeout: 246 seconds]
<very-mediocre>
Conceptually you "could"
<Hejsil>
Well, if it's effects userspace, then it is not an implementation detail
<Hejsil>
affects*
<very-mediocre>
I don't mean it like "it's a hidden behind-the-scenes thing"
<very-mediocre>
I mean it's the status quo, but things *could* conceptually be the way i described
<very-mediocre>
that's what i mean by implementation detail here.
<Hejsil>
I'd love to see this combined abstraction, I just think we lose some "nice to haves"
<Hejsil>
Slices would never work
<very-mediocre>
Yeah, it's really just a kneejerk reaction
<very-mediocre>
I've never seen any respectable language do it
<Hejsil>
The ultimate abstraction! []u8
<very-mediocre>
haha
<very-mediocre>
technically everything is like an iterable dictionary
<very-mediocre>
conceptually that is
<very-mediocre>
you could represent structs, arrays and tuples that way
<Hejsil>
I think, one could get far by having namespaces, []u8 and functions
<Hejsil>
Let's say we can define a unique type like this: const Point = distinct [4]u8;
<Hejsil>
And we could add methods to this type through comptime refelction
<Hejsil>
Now, you can basicly implement structs in userland
<very-mediocre>
right
m4ge123 has joined #zig
<very-mediocre>
I feel like there's always a compromise when you use a struct vs a tuple
<very-mediocre>
it's really all just mixed data with possible padding
<very-mediocre>
I'm OCD about there not being an ideal solution
<Hejsil>
What do you think of the tuple proposal though? I'd like to get some opinions before I start working on it (andrews opinion is not enough!)
<very-mediocre>
I'm a big pontificator, I do a lot of "academic" type thinking so maybe my opinion sucks
<very-mediocre>
That said, I like the proposal a lot.
<very-mediocre>
It's good that you can use the bracket accessor to access tuple fields by index, and cast tuples to arrays
<very-mediocre>
but that also makes me OCD because I can't unsee that array is a special case of tuple
<Hejsil>
I don't think "cast to array" is gonna be in the initial implementation, as we don't know of the usecase for that yet
<very-mediocre>
maybe the reason you don't know the use case for that, is that array is just a special case of tuple :)
<Hejsil>
:)
<very-mediocre>
so if you had a function that accepts an array, and elsewhere you have a tuple...
<very-mediocre>
you're better off changing the function to accept a tuple
<very-mediocre>
in order to accept the "elsewhere" value as a param
<Hejsil>
Imagine writing [32]u8 as a tuples though :)
<very-mediocre>
I did imagine it
<very-mediocre>
You'd write provide the 32 somehow
<very-mediocre>
instead of writing each one
<Hejsil>
tuple.{u8} ** 32 :)
<very-mediocre>
yeah
<Hejsil>
I don't think we're going to unify tuples and arrays, because we have slices
<Hejsil>
And slices only work on arrays
<Hejsil>
So tuples are not a strict superset
very-mediocre_ has joined #zig
<very-mediocre_>
got disconnected
<very-mediocre_>
tuples are not currently a strict superset, but in theory they could be
<very-mediocre_>
i'm only talking theory here :)
<Hejsil>
Righto
<very-mediocre_>
I noticed there's quite a bit of friction in many languages when using a mix of structs/tuples/arrays
<very-mediocre_>
even dynamic languages like horrible PHP
<very-mediocre_>
I suffered immensely last week working on a legacy REST API for work, because some functions returned objects while others returned arrays
very-mediocre has quit [Ping timeout: 256 seconds]
<very-mediocre_>
and both were used to represent the same kinds of data
very-mediocre_ is now known as very-mediocre
<very-mediocre>
Similar things happen in JS and TypeScript too
<very-mediocre>
with Object literals vs. es6 classes, etc
<very-mediocre>
It drives me crazy that there are so many ways to represent the same kinds of data..
<very-mediocre>
Maybe no solution exists but that's annoying.
<Hejsil>
I think this is where best practices come in
<Hejsil>
All data could be []u8
<Hejsil>
But really, if certain section could be given a name
<Hejsil>
Then a struct is probably better
<Hejsil>
I get the pain, but I don't think there is a solution
<very-mediocre>
Yeah but there's always that problem of, say a library takes an array for something
<very-mediocre>
while another uses tuples
<very-mediocre>
and yet another might use a struct to represent the same dataset
<Hejsil>
At least tuple<->array could have a wrapper func that at most, does a memcpy in Zig
<Hejsil>
Or, tuple->array, I can imagine
<Hejsil>
But array->tuple is probably harder/not possible to write
<very-mediocre>
That feels like an overhead that exists in code but not in concept
<Hejsil>
Yea
<very-mediocre>
Stuff like vec3, Point, etc
<very-mediocre>
I've seen them as classes, structs, arrays, tuples
<very-mediocre>
Wouldn't it be great if that distinction could be eliminated?
<Hejsil>
I don't think tuples should be used for vec3 :)
<Hejsil>
but struct<->array is a problem yes
<very-mediocre>
Why not?
<Hejsil>
Arrays does everything the tuple does
<very-mediocre>
the field names in vec3 or vec4 are interchangeable, you'd store xyzw or rgba
<Hejsil>
But I guess, some api could take a generic tuple.{f32,f32,f32} and you want to pass your vec3
<very-mediocre>
Well if arrays do everything tuples do, then why do you need tuples?
<Hejsil>
For vec3, i ment
<Hejsil>
Not in general
<very-mediocre>
ah
<Hejsil>
My bad
<very-mediocre>
yes actually I also had a brainfart there
<very-mediocre>
obviously the "mixed fields" thing is huge.
<very-mediocre>
I'm not expressing myself well today
<very-mediocre>
My overall point is I question the need for all 3 of tuples, arrays and structs to exist
<very-mediocre>
there's a lot of overlap and it opens up a lot of different ways to do some of the same things
<Hejsil>
True. They only reason tuple is being considered is that they can replace varargs and give multible return types
<very-mediocre>
Yeah, and I really like that
<very-mediocre>
Although sometimes I wonder if we are stuck in the boundaries of things we've seen other languages do.
<Hejsil>
Actually, maybe we don't need tuples
<Hejsil>
If we could deconstruct structs, then we have multiple return values and inferred structs could (in theory) do what tuples do for varargs (a little more verbose)
<very-mediocre>
I like that, if only as a thought exercise
<Hejsil>
I'll give this some thought. One of the goal of Zig is "only one obvious way to do things" after all
<very-mediocre>
Is there a reason why structs that have the same fields are not considered equal?
<Hejsil>
Same name+type yes?
<very-mediocre>
Yeah
<Hejsil>
Their might be two structs which have the same fields, but which mean different things
<Hejsil>
I can't really think any other reason
<very-mediocre>
OK. Sorry for bashing you on the head with this btw
<Hejsil>
Np, lol.
<very-mediocre>
I'm an insufferable debater, I debate everything infinitely.
<Hejsil>
If we think of structs, and kinda the same a enums, it make sense
<very-mediocre>
Should be the same for structs then.
<Hejsil>
Well, maybe not, but this is how I see it
<Hejsil>
Structs have a lower chance of collision
<very-mediocre>
Allows the compiler to prevent the programmer from using weird types, it makes the code harder to read
<very-mediocre>
It would probably be harder to read if someone passed `FireNuke.Yes` to a something that took a less nukey enum type, say, GoToSleep with .{Yes, No}
<very-mediocre>
I can envision similar situations for structs.
<MajorLag>
I had a crazy idea a while back to unify struct/union/enum into a namespace type. You could just arbitrarily declare reular fields (struct), alternate views of them (union), and constants (enum) in one block. Adding tuples to that would just mean allowing fields to be indexed by declared position I suppose. Probably not actually a helpful way to do things though.
<very-mediocre>
>crazy idea -> my favorite kind of idea :)
<MajorLag>
Come to think of it, inferred structs and accessing struct members by index is all you need to replicate a tuple. Maybe we don't need a special type?
<Hejsil>
^
<Hejsil>
Good point
<Hejsil>
Or, well. You'd have to call warn like this: warn("{}{}", .{.a = u8(1). b = " " })
<Hejsil>
And you don't need to have indexing on structs, as we have @field
<Hejsil>
+ @typeInf
<MajorLag>
ok, so you also need anonymous position-only fields... at that point maybe a special type is better.
<Hejsil>
Or maybe not. Maybe this is better: warn("{a:x}, {b:x}", .{ .a = u8(0), .b = u8(1) })
<Hejsil>
Free named position independed fmt
<MajorLag>
hmmm
<Hejsil>
You just can't call warn without the names
<Hejsil>
But this is easier to read and debug
<very-mediocre>
MajorLag: the problem is iirc zig might reorder struct fields internally
<MajorLag>
actually you could still call warn without the names, because you can get the fields by position from `@typeInfo`
<MajorLag>
I don't think reordering is an issue, indexing by position would be against the declared position.
<MajorLag>
which typeInfo already does I think.
<very-mediocre>
Well I agree wholeheartedly then with this, it's kind of what i was saying, they are really all the same thing
<very-mediocre>
a struct is just a tuple with named field accessors
<very-mediocre>
and an array is a tuple with the same field types
<MajorLag>
right, the real question is "are they different enough that it's useful to separate the concepts"? I'm honestly not sure.
<very-mediocre>
Yeah, that's exactly the question that's driving me crazy
<very-mediocre>
and so far I have spared the chatroom another argument that is now a dead horse
<very-mediocre>
interfaces.
<MajorLag>
well that one does have a 49-post thread already.
<very-mediocre>
Yep, but it ties into structs/tuples
<very-mediocre>
One point of annoyance is if a library that exposes a function that takes a [4]u8 param for example, and you want to use it with another library that has the relevant data represented as a tuple with 4 values...
<very-mediocre>
or a struct...
<very-mediocre>
Some forms of interfaces can address that.
<euantor>
Nim's idea of concepts is a pretty nice way to solve that
<MajorLag>
My own though, detailed in the thread, is that we can just pass an `fn(type)bool` to `var` which can determine the suitability of a type using arbitrary inspection. `const isIterator = trait.hasFn("next"); fn func(iter: var<isIterator>) void {}`; No new language constructs, just a small extension to var.
<very-mediocre>
Hejsil: having field names for warn sounds good, but for some uses wouldn't you want it the passed thing to be iterable?
<very-mediocre>
MajorLag: that's awesome
<very-mediocre>
I had similar thoughts when reading that Concepts link
<very-mediocre>
since comptime is a thing in zig
<Hejsil>
very-mediocre, have an example. Not sure i understand
<Hejsil>
Also, what is your github handle. I wonna post this counter proposal, and give credit :) (MajorLag too, but I'm pretty sure you are @tgschultz)
<MajorLag>
yes, I am the infamous @tgschultz
<very-mediocre>
Hejsil: I meant: `warn("{b} {a}", .{ .a = u8(1), .b = "yo" });` <-- the ability to use .a and .b here in the warn function is great, but for things other than `warn` it's unnecessarily verbose to have to write .a and .b
<very-mediocre>
I'm nodefish on github
<Hejsil>
That is true
<Hejsil>
We can't have our cake and eat it too
<MajorLag>
Allowing structs to have unnamed, position-index-only fields could get weird. I think that's the strongest argument for a separate tuple type.
<MajorLag>
But then all it really does is save some verbosity, so... I dunno.
<very-mediocre>
If we "zoom out" we can think of all of these things as dictionaries
<very-mediocre>
perhaps you could declare a struct like
<very-mediocre>
{ .a = u8(1), u8(5) }
<very-mediocre>
and have the second field be at index 1
<very-mediocre>
but this is somewhat scary for readability
<very-mediocre>
it also makes structs iterable, which I don't know if that's cool or horrible
<MajorLag>
To be fair, they already are via `@typeInfo`. My arbitrary type I/O code relies on it.
<very-mediocre>
hm right, but then there is implicit behavior that is somewhat against the zen of zig if structs are directly iterable
very-mediocre_ has joined #zig
<very-mediocre_>
(disconnected) e.g. if you have a struct that is basically a tuple (arraylike set of data), you'd want to iterate through the data fields only but not any methods
<MajorLag>
well....maybe they don't have to be directly indexable like an array. The meta code for implementing a fieldIndex function isn't bad. We could prvide that in meta.zig, then we just need a way to have unnamed struct members I think.
very-mediocre has quit [Ping timeout: 256 seconds]
<very-mediocre>
MajorLag: upon further reflection, I really like what you proposed for "Concepts"
<very-mediocre>
passing a constraint function would be great.
<MajorLag>
thanks. I thought it fit the zen pretty well.
<Hejsil>
I agree too. It's pretty good
<very-mediocre>
It's also very close to the various shenanigans people have been doing to try and make interfaces happen
<very-mediocre>
in the sense that it's an arbitrary comptime check
<very-mediocre>
so it's a nice natural conclusion to that thought process
<very-mediocre>
and it opens up doors for things like interfaces should users want them.
<Hejsil>
One can even define constraints that works on multible args: fn add(a: var, b: var<canAddWith(a)>) AddResult(a, b) { return a + b; }
<Hejsil>
Or, it would probably look like this: fn add(a: var, b: var<canAddWith(@typeOf(a))>)
<very-mediocre>
euantor dropped that Concepts link just in the nick of time :)
<very-mediocre>
and saved us all from the impending interface discussion
<very-mediocre>
Hejsil that is awesome
<very-mediocre>
I hit a brick wall previously trying to do something like this in totally the wrong way
<very-mediocre>
my idea for interfaces was to be able to write functions like, IsAShape, which returned a union type of all implementers
<very-mediocre>
and thus you'd be able to pass, say, a boxed Circle and then unbox it in the function body
<very-mediocre>
alas, this doesn't work because you can't use `comptime var` in the top level context so such a union is impossible.
<very-mediocre>
MajorLag's idea removes the need for a "parent type" to be generated at comptime (whether interface or abstract class), which is impossible
<very-mediocre>
Should be a separate proposal probably
<very-mediocre>
It opens up interfaces and varargs and probably many other things
<MajorLag>
Maybe I'll put something together later today if my workload is light enough.
<very-mediocre>
Get a couple more opinions first maybe, I can never tell if my judgment is crazy or not :)
<very-mediocre>
but I have to say I would really like to use that feature in code.
<Hejsil>
I like how the Zen of Zig basically says "you can't solve every usecase with a new feature, because we wonna be simple". It forces people to be creative and come up with simple and orthogonal concepts
<Hejsil>
Maybe var should always take a parameter: fn a(b: var<any>) void
<very-mediocre>
Hm, can't think of any reason why not actually
<very-mediocre>
that elevates `var` to the same level of strictness as normal function params
<Hejsil>
A good reason for this, is that the default should not be the hardest to reason about.
<Hejsil>
With var<something>, nothing is the default, and the user have to choose
<very-mediocre>
yeah that makes sense
<Hejsil>
Going even further, maybe paramter types can be of type `type` or `fn(type)bool` :)
<Hejsil>
Removing var completly
<Hejsil>
But that might be weird
<very-mediocre>
wouldn't that indicate that you're passing a function as the param, rather than it being a comptime checking function?
<Hejsil>
So far, params look like this fn f(name: any_expr_evaluating_to_type)
<Hejsil>
fn f(name: <type>) this for short
<Hejsil>
I propose this: fn f(name: <type or fn(type)bool>)
<Hejsil>
So an expression that evaluates to fn(type)bool
<very-mediocre>
I see
<Hejsil>
But it was hard to explain, so it's probably hard to understand
<Hejsil>
So, maybe var<func> is better
<very-mediocre>
Yeah it is
<very-mediocre>
@typeOf(fn(type)bool) == type <--- this is not intuitive
<MajorLag>
I think var<fn> communicates clearly that the parameter is a comptime-variable type. I don't think that is the case with a naked fn.
<Hejsil>
Agreed
<Hejsil>
Was just throwing it out there
<Hejsil>
@typeOf(fn a(T: type) bool {}) == fn(type)bool. @typeOf(fn(type)bool) == type. @typeOf(type) == type (I think)
<very-mediocre>
This flies over my head somewhat
<very-mediocre>
I don't get this: @typeOf(fn(type)bool) == type
<MajorLag>
`fn(type)bool` is a type. It's the type of a function that takes a type parameter and returns a bool.
<very-mediocre>
ah, a type of a function is a type?
<very-mediocre>
OK, I am grossly unfamiliar with some of zig's type system
<very-mediocre>
Spend too much time getting brain damage from legacy PHP codebases :)
<Hejsil>
Lol
<Hejsil>
i8, []u8, struct{}... all have @typeOf() == type
<Hejsil>
This is how Zig generics work
<very-mediocre>
Yes that I know
<euantor>
Looks like I dropped that link just in the nick of time before I went out for lunch
<very-mediocre>
brainstorming is an art
<very-mediocre>
it's like those moments in that old TV show "House" where he figures out the diagnosis while doing something unrelated
<very-mediocre>
Just seeing the word "Concepts" made me think back to the interface shenanigans i was doing
<very-mediocre>
(in a different way, otherwise I might have reopened the existing interface discussion)
<euantor>
Nim has hit some stumbling blocks along the way to implementing them, but they did start implementing them fairly late in the game
<very-mediocre>
Nim is so in flux all the time, you'd think I designed it
<very-mediocre>
(being an insufferable "devil's advocate)
<very-mediocre>
It's gonna be cool when it hits 1.0 if they manage to cut out a lot of the fat
<very-mediocre>
last time I checked there were a lot of incongruent ideas in Nim
<very-mediocre>
some really good ones, but at some point they need to coalesce into a language.
<euantor>
I've written a fair bunch of Nim code, but I'm hedging my bets between it and Zig
<euantor>
Nim has some nice features, but things keep changing constantly - such as the now pivot towards destructors and such rather than GC
<Hejsil>
You can quote me on this: "A programming language cannot be turning complete, if you cannot write an ugly hack in it"
<Hejsil>
(I really hope this is true, or I'll look stupid) :)
<very-mediocre>
define "ugly hack"
<very-mediocre>
If you were a mean person, you could make a killer comeback here
<Hejsil>
Well, that can be debated (ugly hack) :)
<Hejsil>
Ooh, i get the second one now
<very-mediocre>
:)
<Hejsil>
Hmmm. That make me think. Could you "breed" programs :)
<Hejsil>
made*
<Hejsil>
"Breeder program": Takes two programs, and makes a third one
<very-mediocre>
Hejsil, I think it's time for the talk
<Hejsil>
Lol
<very-mediocre>
You see, when a compiler loves a userland program very much...
<Hejsil>
No, you stop that!
<Hejsil>
I was more think, compiled programs :)
<Hejsil>
And if "Breeder" somehow outputs a "working" program, that is probably an ugly hack
<very-mediocre>
The Breeder would qualify as a compiler
<Hejsil>
True
<Hejsil>
Hmm. I guess there is no reason that the inputs should be compiled
<Hejsil>
Hold op
<Hejsil>
Gcc is a breeder
<Hejsil>
All compilers are breeders (if the can compile more that one file)
<Hejsil>
I should probably just leave
<very-mediocre>
lol
<very-mediocre>
stick around, you're making me look good
<Hejsil>
Idk if that is a good thing
<very-mediocre>
not an easy feat!
<Hejsil>
git merge, is a breeder
<Hejsil>
I'm done now
<Hejsil>
I take back this: "that is probably an ugly hack"
<very-mediocre>
it was valid when you had binaries in mind maybe
<andrewrk>
Hejsil, I think that destructuring structs based on variable names is problematic given that we don't allow shadowing
<Hejsil>
andrewrk, I was thinking in terms of position and not name
<andrewrk>
ahhh ok
<andrewrk>
I misread your comment
<andrewrk>
Hejsil, ok now I'm thinking about how easy it would be to re-order fields and introduce a bug
<Hejsil>
We can never win, can we? :)
<andrewrk>
I like that you solved all the important use cases without tuples
<andrewrk>
I think you're on to something here
<Hejsil>
Well, MajorLag and very-mediocre where very helpful on this one
<andrewrk>
indeed - I read the log
<andrewrk>
so multiple return values from a function/block would be a struct, in order to get mixed types, yes?
<Hejsil>
Yes
<Hejsil>
And, most of the time, names are more useful than no names. fn findMinMax() struct{min: T, max: T} is better than using a tuple
<andrewrk>
agreed
<Hejsil>
Maybe we don't even need deconstructing of structs
<andrewrk>
I'm completely with you in that we'd rather not have tuples, we just have a handful of important use cases
<Hejsil>
Or...
<Hejsil>
var a, const b = . requires deconstructing
<andrewrk>
I think the printf example with the struct initializer is adequate - just at the boundary of "too much API friction" but not quite over the line yet
<Hejsil>
When you need to format many values, my proposal even outshines it's friction because the fmt string can refer to names
<andrewrk>
the goal with multiple return values is to avoid use of `undefined`
<Hejsil>
Which helps readability
<andrewrk>
agreed
<andrewrk>
an API which is more cumbersome to type, but handles even the complicated cases the same way as the simple ones, is in line with zig's philosophy
<Hejsil>
I'd say multiple return values also allows const variable to actually be const, which I think is important
<Hejsil>
Because "communicate intent"
<andrewrk>
yes that's important too
<andrewrk>
I wonder if just having anon struct initializers would solve the multiple block return value use case
<andrewrk>
because they can have runtime values
<andrewrk>
just return an inferred literal from a block and then access the fields. why does there need to be 2 variables?
<Hejsil>
The only usecase i can think of is const a, var b =
<andrewrk>
ah right
<andrewrk>
that's a good point
<Hejsil>
But maybe that is so rare, that it is not worth it
<Hejsil>
Also @Manuzor just posted an interesting syntax for return types: fn sum(a: i32, b: i32 -> i32) { return a + b; }
<andrewrk>
hm that is indeed interesting
<Hejsil>
We could have used these proposals before I changed everything :)
<Hejsil>
But then again, a git revert, could probably fix most of it back
davr0s has quit [Quit: My MacBook Pro has gone to sleep. ZZZzzz…]
<andrewrk>
Hejsil, now you see why I was personally putting that change off :)
<andrewrk>
I'm not going to get in your way though!
<Hejsil>
I don't think people would have gotten all these great ideas without me ruining Zig for them :)
<Hejsil>
My change sparked the discussion!
<Hejsil>
It makes Zig better in the end!
<andrewrk>
:)
<Hejsil>
Even if MajorLag will have to change all his code again!
<andrewrk>
it was for great justice
<Hejsil>
Indeed
<bheads>
If we did this would we be able to define the struct in the return? fn foo() struct.{min: i32, max: i32} {}
<very-mediocre>
It was to move zig
<Hejsil>
bheads, pretty sure we can already do this
<Hejsil>
The problem was always error sets and initializers
<andrewrk>
yeah that already works, the problem is that we don't have anon struct initializers
<Hejsil>
Never struct/union/enum decls
<andrewrk>
so you have to name your anonymous struct in the initializer which defeats the point of it being anonymous
<Hejsil>
This too ^
<bheads>
okay, so would we get that with the innfered initilizer
<Hejsil>
Yes!
<andrewrk>
Hejsil, what if we have anon array initializers but no tuples
<andrewrk>
var a, const b = blk: { break :blk .{expr1, expr2} };
<Hejsil>
What happens if we pass that to var?
<andrewrk>
segfault
<Hejsil>
Or stores it: var a = .{expr1, expr2}
<andrewrk>
just kidding. it would work
<Hejsil>
Lol
<Hejsil>
How would that work with multiple different types.
<bheads>
it would have to be a struct then
<bheads>
maybe a default naming
<Hejsil>
I don't think default naming is a good idea
<very-mediocre>
or indexable structs, which brings us full circle to the whole convo today
<bheads>
then you would have to name the,
<Hejsil>
We don't want this to work: const a: struct.{a: u8, b: u8} = .{1, 2};
<andrewrk>
agreed
<very-mediocre>
Why is it bad that you have to name them
<very-mediocre>
Hejsil argued above that named is better than unnamed for mixed data
<andrewrk>
Hejsil, it could be a "tuple" type in the same way that a "comptime_int" has to have its value known (and the value is not in the type), it has to have its member types known, but they are not in the type
<bheads>
extra verbose is all
<andrewrk>
very-mediocre, it's bad that you can re-order struct fields and cause bugs accidentally
<Hejsil>
Hmmmm. Seems like we just got varargs back, but used in a different place
<Hejsil>
(the implementation that is)
<very-mediocre>
andrewrk: such re-ordering would be explicit though
<very-mediocre>
it applies to anything ordered and named, such as function params
<bheads>
plus if this is used to replace varargs, you now have to name all of the args
<andrewrk>
very-mediocre, how would you destructure a struct into variables?
<very-mediocre>
ok, for destructuring you have a point
<andrewrk>
destructuring structs is ok, but the destructuring syntax has to redundantly say which fields they're getting and not just rely on position
<Hejsil>
Maybe destructuring is just a bad idea. Unless we do it with field names, there is no way to catch the bug where two fields changed order
<very-mediocre>
could varargs allow one to pass arrays or structs?
<Hejsil>
pass them where?
<very-mediocre>
bheads wrote: `plus if this is used to replace varargs, you now have to name all of the args`
<very-mediocre>
i figure in the use case where you'd use a tuple, you'd instead use a struct
<very-mediocre>
and in other cases an array
<Hejsil>
Ye, that's probably the plan
<very-mediocre>
so you'd have to name the fields only in the tuple-esque use case (struct)
<very-mediocre>
maybe that's not so bad.
<bheads>
in may cases the name is meaning less
<bheads>
the position is what is in portant
<bheads>
like a join function
<very-mediocre>
if you're returning data as a bundle, is it not related data?
<Hejsil>
join would use []const u8 and .{"a", "b"}
<Hejsil>
So no names here, as we can accept an array
<Hejsil>
varargs usecase is printf
<bheads>
why does join only join strings?
<Hejsil>
Well :)
<Hejsil>
That depends
<Hejsil>
what are you trying to join
<bheads>
all base types
<bheads>
numbers string arrays of strings
<very-mediocre>
good point, that's a tuple, straight up. :/
<Hejsil>
Well, wouldn't you use format for that
<bheads>
no cause my join sends it over a socket :)
<Hejsil>
Then implement fmt to send over the socket :)
<andrewrk>
you can already do that with OutStream
<bheads>
the goal of the function is not important, I want a vararg that I will iterate over
<bheads>
with mixed types
<Hejsil>
Well, we have to figure out if such a function would ever exist in code
<Hejsil>
A usecase
<very-mediocre>
MajorLag suggested earlier that a userland function can be provided for iterating over struct fields
<Hejsil>
^
<very-mediocre>
I don't know if I like that though.
<Hejsil>
That's how warn/fmt would be implemented with the latest proposal on removing varargs
<andrewrk>
I think the "typeless tuple" idea is worth exploring
<bheads>
so on fmt you would have to name all of the fields
<Hejsil>
That's what is discussed now at least
<Hejsil>
Nothing is final
<Hejsil>
andrewrk, as a replacement for varargs, or for multiple returns?
<Hejsil>
Isn't varargs a tuple?
<Hejsil>
I think we'll end up with the same implementation if we go the "typeless tuple" idea
<Hejsil>
as varargs that is
<Hejsil>
But idk, I don't have the full picture of this "typeless tuple" thingy
<bheads>
So far the only ligit purpose of mixed types if printing functions
<bheads>
not having tuples in most languages has really limited our imaginations
<very-mediocre>
it feels wrong to have mixed types in most cases
<very-mediocre>
maybe it's even "wrong" for printing ultimately
<very-mediocre>
are you printing a uint, or a u8 representation of a uint?
<very-mediocre>
maybe it's the programmer's responsibility to provide an array of u8s to print
<very-mediocre>
instead of a mixed list.
<bheads>
I dont think so, cause you then end up with lots of extra temp memory at the call site
<Hejsil>
very-mediocre that would require the construction of a string. fmt does not do this
<very-mediocre>
I mean it's the programmer's responsibility to pass pre-converted items to the print function
<bheads>
you also lose some memory optimization
<very-mediocre>
yeah, but it feels more "right" despite running worse
<Hejsil>
Idk about that
<bheads>
well haskell reels right sometimes
<bheads>
doesnt mean its good
<very-mediocre>
I just find it weird that the print function has to care about converting the params it receives into something printable
<bheads>
then call print(fmt(... ))
<very-mediocre>
that's my point, then you don't need mixed lists
<very-mediocre>
what you pass to print is an array of []u8
<Hejsil>
Sadly, what we like, and what is efficient/fast is different, and certain systems have to care
<bheads>
you do if you want to optimize the fmt
<very-mediocre>
ok so conversely, then, are we sure mixed lists of things are only useful for printing?
<bheads>
thats the only good use case I have found so var...
<bheads>
lots of code uses tuples as annon structs...
<bheads>
which is bad
<bheads>
so yeah I do think we want that
<bheads>
I dont****
<bheads>
maybe tuples are a bad idea
Hejsil has quit [Ping timeout: 256 seconds]
<very-mediocre>
somehow everything is really just contiguous memory, yet no one representation really nails it
<bheads>
humm, most tuples are strong const
<andrewrk>
if it works, then printf looks roughly the same as today, and it gets us multiple block values, and it isn't really an alternative to structs
<andrewrk>
so there's no cognitive dissonance
<bheads>
I can live with naming the fields for print and fmt
<bheads>
it has some benifits
<bheads>
I was tring to thing of a cases where you only cared about the order, but cant think of any that are mixed types
wink_ has joined #zig
<very-mediocre>
I guess if there is associated data that isn't part of the "concept" of what the main return value is
<very-mediocre>
yet is associated somehow, e.g. an error
andrewrk has quit [*.net *.split]
edr has quit [*.net *.split]
<bheads>
zig already has a better what to deal with errors
<very-mediocre>
you don't really want to pollute your returned struct with that field
<very-mediocre>
yes I know, but let's say "errorlike" things are not always zig errors
<bheads>
so warnings
<very-mediocre>
say a return status from an XmlHttpRequest
<bheads>
right but you would always have that
<bheads>
and what that
<very-mediocre>
you don't want it to pollute your data struct
<bheads>
but you would
<very-mediocre>
say your data struct is a Model in MVC
<very-mediocre>
then you wouldn't
<very-mediocre>
I mean, sure, you could architect around it
<bheads>
thats an abstraction above the http request, the code that made the request should be checking for a 200
<very-mediocre>
but it's still conceivable that some cases exist that we can't think of that warrant multiple mixed return types
<bheads>
yeah and a struct gives you that
<very-mediocre>
eh I guess.
<very-mediocre>
ok, I tried
<bheads>
yeah I know
<very-mediocre>
I can't think of any mixed data that feels "correct"
<very-mediocre>
lol
<bheads>
thats what I feel right now
<bheads>
tuples finds feel wrong
<euantor>
The response from an XmlHttpRequest would be a XmlHttpResponse struct, with a headers/status field, and a body field
<bheads>
yup and the response code
<very-mediocre>
Yeah, I'd architect it as such. I work with that stuff 24/7 so I know it can be done neatly.
<very-mediocre>
I kind of scrambled to find an "errorlike" type
<bheads>
ugh the OCP framework I maintain puts everything in a java HashMap<String, Object> ....
<very-mediocre>
that didn't fit zig errors
<very-mediocre>
lol
<very-mediocre>
That's JavaScriptesque
<very-mediocre>
everything in JS is an associative array
<bheads>
its lazy 90's java
<bheads>
to many people working on a code base, so no way we can use strong typed data structs
<bheads>
so lets play the guessing game on data stored in the session and pipeline!
<bheads>
also XmlHttpResponse would probably return socket errors for its error types
<very-mediocre>
Yeah, true.
<bheads>
maybe returns errors on 400s or 500s
<very-mediocre>
My example was ill-conceived
<bheads>
I get what you were trying to go at
<very-mediocre>
XmlHttpRequest in js environments does throw errors on 500
<very-mediocre>
there's an onerror handler
<bheads>
right
<very-mediocre>
So, I got nothing
<very-mediocre>
I don't know when you'd use mixed data.
<bheads>
so far formatting is the only good use case...
<very-mediocre>
I can't unsee how "wrong" it is now, that the print function needs to know what a struct is, what a u32 is, etc
<bheads>
most cases you want them to be the same type
<very-mediocre>
the few cases that come to mind use dynamic memory
<very-mediocre>
and they are bad designs
davr0s has joined #zig
very-mediocre has quit [Ping timeout: 256 seconds]
very-mediocre has joined #zig
<bheads>
I think if we got innfered initilizers for arrays, struct, unioms, and enums we can remove varargs and we would get multiple return types
<bheads>
return syntax may need to be tweaked
tolitius has joined #zig
tolitius has quit [Ping timeout: 252 seconds]
edr has joined #zig
<very-mediocre>
maybe really crazy idea: add tuples but they must be mixed
<very-mediocre>
this avoids the problem of 1 api using an array while another uses a tuple to represent the same thing
<very-mediocre>
although they still overlap with structs...
<very-mediocre>
ok, I'm done for now.
<bheads>
lol
Hejsil has joined #zig
andrewrk has joined #zig
Hejsil has quit [Quit: Page closed]
Hejsil has joined #zig
darithorn has joined #zig
<bheads>
I wonder if the usage of var tp say you want a "tuple
<bheads>
will be a problem
<Hejsil>
You mean this? fn a(b: tuple) void
<bheads>
well I though there were example of warn(fmt: []u8, args: var) void {}
<Hejsil>
I think, with something like MajorLags proposal for var, we can have this instead: fn a(b: var<isTuple>) void
<bheads>
ah is that for the interface work
<Hejsil>
Ye, i like MajorLags idea for this. Again, nothing final, but it looks good
<bheads>
my assumption is the isTuple is a comptime function checking the type
<Hejsil>
Yea
<bheads>
nice
<bheads>
very simular to D's static ifs
<bheads>
thats just a more compact and parameter focued version
<bheads>
would b: const<isTuple> also make sense?
<Hejsil>
what would that do?
<bheads>
same but b is const in the function scope
<Hejsil>
B is already const in function scode (if it is a parameter)
<Hejsil>
b*
<bheads>
using var for const is confusing to me
<Hejsil>
Oooh, right. var in functions is different from var on variable decls
<bheads>
yep
<bheads>
its mean changes
<bheads>
meaning***
<bheads>
I really need to slow down my typing.
<bheads>
in fact the more I think about, I am not sure what is and isn't const in params
<bheads>
nice, I have been using zig so far and never ran into that error...
<bheads>
I guess that means I have been following good programing practices and didn't even notice
very-mediocre has quit [Ping timeout: 256 seconds]
<Hejsil>
:)
<bheads>
okay then so the only odd things is that var has two meanings, but thats minor
very-mediocre has joined #zig
davr0s has quit [Quit: My MacBook Pro has gone to sleep. ZZZzzz…]
porky11 has joined #zig
tolitius has joined #zig
<tolitius>
is it ok to ask 101/beginner questions here or there is a better channel/way?
andrewrk has quit [Ping timeout: 252 seconds]
<Hejsil>
tolitius, go ahead. Here is probably the best place to ask :)
<tolitius>
great, thanks. I going through the doc examples and the first struct ("const Timestamp = struct {...}") from "Doc comments" section does not compile:
<tolitius>
error: expected token '.', found '{'
<tolitius>
const Timestamp = struct {
<tolitius>
^
<tolitius>
$ zig version
<tolitius>
0.3.0+eeb4f376
<bheads>
Thats a new change that went live yesterday in the master branch
<tolitius>
probably something really elementary
<bheads>
you need to put a . there
<bheads>
struct.{.. }
<Hejsil>
Aaah right. The website has not been updated to newest syntax
<tolitius>
ah.. k, so the docs are not updated?
<Hejsil>
andrewrk!
<Hejsil>
We have them updated locally, but it just needs to be put on the site
<bheads>
I thought the docs online got auto deployed
davr0s has quit [Quit: My MacBook Pro has gone to sleep. ZZZzzz…]
<tolitius>
should I open an issue about auto deployable docs (as my first contribution? :) )
<tolitius>
or this is just a glitch
<Hejsil>
Might as well
<Hejsil>
Open an issue that is
<tolitius>
done: #1660
<tolitius>
is there a way to have assert show what the actual value was on failure?
<tolitius>
i.e. "assert(foo == 42)" just says foo was not 42, but does not say what it was
<Hejsil>
No. Using a debugger is probably your best option
<very-mediocre>
you could implement something similar to JS test frameworks
<very-mediocre>
e.g. assert(something).toEqual(42)
<very-mediocre>
you'd have to add types using generics though
<Hejsil>
True, but a debugger is probably easier to do :)
<very-mediocre>
yep. :]
<tolitius>
I see, was curious if it's in the language itself. will go with what's built in, this is not really a problem just "would be good to have" since the runtime knows the value anyway
tolitius has quit [Remote host closed the connection]
Ichorio has joined #zig
<ltr_>
hello everyone, im trying to compile zig against libc++ but im stuck with errors about cmath functions/symbols not defined, ie. isfinite, anyone had a similar error?, it is not related with zig it self but i want to know if it is common.
Ichorio has quit [Read error: Connection reset by peer]
Ichorio has joined #zig
return0xe has joined #zig
tolitius has joined #zig
return0e has quit [Ping timeout: 245 seconds]
davr0s has joined #zig
Jenz has joined #zig
tolitius has quit [Remote host closed the connection]
davr0s has quit [Quit: My MacBook Pro has gone to sleep. ZZZzzz…]
<Jenz>
What's the zig equivalent of e.g. gcc -D foo=bar ?