7 ms·
The way zig does generics is brilliant, and made me think "this is how every language should do it". One of those things that seems obvious in retrospect: just
by sekao 5y ago
The way zig does generics is brilliant, and made me think "this is how every language should do it". One of those things that seems obvious in retrospect: just pass the types as normal parameters, and for generic data structures just represent their type as a function that receives those parameters and returns a new type. Man that's just beautiful. Only downside is, i suppose the types can never be inferred so they always need to be explicitly passed. But being explicit seems to be their thing anyway.
- naasking 5y agoZig's approach isn't unique, it's basically what dependently typed languages do. The problem is that if you don't do it right, it's too expressive and the type checker can loop forever. Of course, this is also true of C++ templates since they're Turing complete, but it's not true of generics in most languages.
- dnautics 5y ago> the type checker can loop forever Oversimplifying: Zig anyways gives you "compiler branching tokens" so your type system can't loop forever, if I'm not mistaken
- uh_uh 5y agoKind of how Ethereum uses "gas" to make sure that bad/lazy actors won't waste CPU cycles when running smart contracts.
- dnautics 5y agosure, but you aren't going to run out of compiler tokens unless you are trying to do something really crazy, like generate a precompiled table of prime numbers, as I have done. And I don't think you use them up in general, just when your compiler is taking certain branching operations (i don't actually know what the rules are)... I believe you can have a long program that consumes as many tokens as a short program, if their typesystems are the same and you don't ever use compile-time branches in the functions you're writing.
- rackjack 5y agoThis isn't a gripe directed at you specifically. I've noticed that when somebody says they like a growing language (Rust, Zig, ...) for this or that feature, people often come out of the woodwork to claim that it isn't unique, that some research project did it 5 years ago, etc. etc. First, that's not even what they were saying. They like a feature of the language, they weren't making a claim about the novelty of it. Second, even if they did erroneously make a claim about the feature's novelty, I think the theory type of people dismiss these sorts of languages too readily. Yes, somebody did it before. But it is usually very hard to bring these features into the mainstream or even adjacent to it. It's just annoying when we're appreciating a language and the work that went into it and somebody pops their head in and says "Ackshually, Joe Gringoff published a paper in '95 detailing that exact thing, so it isn't anything new." Like I'm trying to enjoy "Samson and Delilah", I'm not really thinking about who did that kind of lighting first, so why are you using the lack of novelty to diminish the effort put into the lighting? If you want to say, "Fun fact, Giorno Capucelli was the first one to popularize that kind of lighting!" Then that's cool, but instead these people always use these facts to diminish something else instead of enhancing it. Just let me enjoy their handiwork!
- Findecanor 5y agoComments like that provide context that you could use as search terms for finding more documents from which you could learn learn more about the feature. If you're interested in programming languages in particular, the earlier papers could tell you about the philosophy and rationale about how and why the feature came about in the first place.
- Mathnerd314 5y agoI argue to the contrary that it's quite disappointing to see features developed without referencing previous work. The annoying "Actually, so-and-so" is really just a symptom of the general lack of citations. Maybe it's possible to design a language de novo without being aware of previous designs in the space, as Zig seems to be doing, but it seems quite dangerous - one wrong step and you've locked in a bad design. Whereas using proven designs (as Rust claims to be doing in their FAQ) is at least making use of some form of validation.
- wk_end 5y ago> but it's not true of generics in most languages not sure how true that is. * TypeScript: https://github.com/microsoft/TypeScript/issues/14833 https://github.com/microsoft/TypeScript/issues/14833 * Rust: https://sdleffler.github.io/RustTypeSystemTuringComplete/ https://sdleffler.github.io/RustTypeSystemTuringComplete/ * Haskell (GHC): https://mail.haskell.org/pipermail/haskell/2006-August/018355.html https://mail.haskell.org/pipermail/haskell/2006-August/01835... * Scala: https://michid.wordpress.com/2010/01/29/scala-type-level-encoding-of-the-ski-calculus/ https://michid.wordpress.com/2010/01/29/scala-type-level-enc... * Java: https://arxiv.org/abs/1605.05274 https://arxiv.org/abs/1605.05274
- naasking 5y agoMost of that cleverness requires generics + something else, usually some kind of subtyping. This is the case at least for Java, Haskell, Scala and Rust. Generics alone typically do not admit Turing complete expressions. In Zig and dependently typed languages where types are ordinary values, you typically have the regular looping/recursion available, and so Turing completeness follows naturally unless you take steps to mitigate this. Zig makes a hard distinction between runtime and comptime which might solve this, and dependently typed languages have termination checkers which extend this sort of distinction in more flexible ways.
- jules 5y agoDependent types go beyond what Zig does by removing the distinction between comptime variables and runtime variables (so types can depend on runtime variables). Zig goes beyond dependent types in the sense that the comptime/runtime distinction allows Zig to handle all comptime values at compile time, which is important for efficiency. It would be interesting to combine the two approaches, via partial evaluation or staging.
- naasking 5y agoTo my understanding, comptime is a form of partial evaluation. PE is typically done by a "binding time analysis"; comptime declarations are explicit binding time declarations. You can also see Zig as a three stage language (comptime+compile time+runtime), where most compiled languages are two stage languages (compile time+runtime). There's a lot of overlap here.
- specialist 5y agoDo you have a preferred (favorite) implementation of dependent types? Quickly scanning the list on wiki... Ada is the only imperative language listed. Corecursive has had a few episodes about dependent types. Here's two: https://corecursive.com/015-dependant-types-in-haskell-with-stephanie-weirich/ https://corecursive.com/015-dependant-types-in-haskell-with-... https://corecursive.com/023-little-typer-and-pie-language/ https://corecursive.com/023-little-typer-and-pie-language/ Learning more is on my to do list. To noob me, the descriptions remind me of Eiffel's constraints (asserts, pre/post-conditions). And maybe user defined typedefs, like constraining dayOfWeek to values 0..6, a bit like enums.