[HN Gopher] How I Built Zig-SQLite
       ___________________________________________________________________
        
       How I Built Zig-SQLite
        
       Author : Sphax
       Score  : 202 points
       Date   : 2022-05-27 09:16 UTC (13 hours ago)
        
 (HTM) web link (rischmann.fr)
 (TXT) w3m dump (rischmann.fr)
        
       | curist wrote:
       | By using comptime, the statement couldn't be runtime composed,
       | right? That's currently the major holdback for me to spend more
       | time on zig: if using comptime become more common in zig
       | community, the libs could be less flexible to use. It feels sort
       | of like function coloring to me, that the whole call chain also
       | need to pass down the value as comptime variable. I've only spend
       | 2 days with zig, so I would love to learn if I'm wrong on this
       | subject.
        
         | throwawaymaths wrote:
         | Generally I wouldn't call zig comptime function coloring. (I
         | have written a prime sieve algorithm that uses the runtime code
         | to precalculate some primes at comptime. Yes, I had to be very
         | careful about what was in the prime number algorithm, but
         | comptime supports _that level of complexity_ and it was
         | certainly possible to call runtime-intended code at comptime.
         | 
         | Can you call comptime-intended code at runtime? No? (Yes? B/c
         | the call site is "in" the runtime code?) But just make it
         | runtime code instead of comptime code?
        
         | skybrian wrote:
         | Often, comptime code couldn't be executed at runtime because
         | the language features it accesses aren't available then. But I
         | agree that if a parameter could go either way, you shouldn't
         | have to write two versions.
        
         | Sphax wrote:
         | Only the metadata of the statement is comptime, that is the
         | type annotation for each bind parameters. So if you have this
         | query                   SELECT * FROM user WHERE age =
         | $age{u16}
         | 
         | You _must_ provide a u16 bind parameter. However the value
         | itself is of course not required to be comptime-known, that
         | would make the whole thing unusable.
         | 
         | For what it's worth there are in zig-sqlite variants of the
         | method which bypass the comptime checks; they're not documented
         | properly yet but see all methods named `xyzDynamic`, for
         | example https://github.com/vrischmann/zig-
         | sqlite/blob/master/sqlite....
        
       | nickysielicki wrote:
       | constexpr/consteval/comptime/etc is a game changer for the
       | systems programmer and it feels so close but yet so far. Can
       | someone speak to what language has the best support for this?
       | Some things that I feel are missing in C++:
       | 
       | * arbitrary file I/O. I can take my compile time data and write a
       | python script to put it in a std::array, but I shouldn't have to.
       | 
       | * non-fixed-sized containers, ie vector
       | 
       | * a generic memoization utility in the standard library for
       | caching. If I want my function to handle any input at runtime,
       | but I want to pre-populate a cache at compile time for values
       | that I know will be called, it's doable but not as easy as it
       | should be. (In general, given the amount of algorithms that rely
       | on memoization, I'm somewhat surprised that Python is the only
       | language I know that makes memoization as easy as a decorator).
        
         | ntoskrnl wrote:
         | > Can someone speak to what language has the best support for
         | this?
         | 
         | I can give you the Rust perspective, but I'm not sure it's the
         | best.
         | 
         | > arbitrary file I/O
         | 
         | include_str! and include_bytes! make the contents of a file
         | available as a string or a byte array. More complex types would
         | need a build script (or transmute).
         | 
         | > non-fixed-sized containers, ie vector
         | 
         | No support in `const fn`, but you can again use a build script
         | as an escape hatch.
         | 
         | > a generic memoization utility in the standard library for
         | caching
         | 
         | There's nothing in the stdlib, but there are a few third party
         | crates that give you the easy one-line syntax, such as
         | https://crates.io/crates/memoize
        
         | [deleted]
        
         | dataangel wrote:
         | All of this is already done in Lisp. Greenspun's 10th rule.
        
           | ArtixFox wrote:
           | ...is there any lisp that can be used for systems programming
           | and that does NOT produce huge binaries, does not use GC,
           | generates fast n small binaries and is still interactive?
           | everyone claims lisp can be used for anything, same goes for
           | forths, but i cant see a lisp like that, and about
           | forths...none of the free ones are fast, and the fast ones
           | are still slow
           | 
           | on the same note, lets say if someone is creating something[i
           | am thinking of] like this, what would be a better option, go
           | the forth way or the lisp way cuz both offer same stuff to
           | some extent
        
             | throwawaymaths wrote:
             | I mean there was a "lisp machine" in the distant past that
             | actually ran lisp on metal. Does that count?
        
               | ArtixFox wrote:
               | obviously no, we dont care about a language that was once
               | used in a machine specifically for it, cuz we cant go in
               | past and program in that specific machine.
               | 
               | i think ive realised what is up with lisps, forths, etc.
               | theoretically you can build all kinds of beautiful
               | abstractions over it and use them for anything
               | 
               | but in reality these languages cant do that and/or their
               | communities dont care to implement it/its not their goal
               | 
               | it might sound bad but it is what it is
               | 
               | if i would have to say it in a worse way, these languages
               | are all talk
        
         | formerly_proven wrote:
         | > * arbitrary file I/O. I can take my compile time data and
         | write a python script to put it in a std::array, but I
         | shouldn't have to.
         | 
         | https://ziglang.org/documentation/0.9.1/#embedFile
         | 
         | I haven't tried, but because it should just be equivalent to a
         | string literal you should be able to further process it using
         | comptime as well.
         | 
         | > * non-fixed-sized containers, ie vector
         | 
         | One way is to just have a function count how many entries you
         | need and use arrays. This is all pretty straightforward because
         | comptime.
         | 
         | Real dynamic comptime containers are dependent on making a
         | comptime allocator available. There's a ticket for that:
         | https://github.com/ziglang/zig/issues/1291
         | 
         | > * a generic memoization utility in the standard library for
         | caching. If I want my function to handle any input at runtime,
         | but I want to pre-populate a cache at compile time for values
         | that I know will be called, it's doable but not as easy as it
         | should be. (In general, given the amount of algorithms that
         | rely on memoization, I'm somewhat surprised that Python is the
         | only language I know that makes memoization as easy as a
         | decorator).
         | 
         | I don't think it's possible to use comptime to generate wrapper
         | functions duplicating the signature of a given function, at
         | least I haven't found a way to do so. The function signature
         | has to be spelled out in the comptime code.
        
         | jdrek1 wrote:
         | > arbitrary file I/O. I can take my compile time data and write
         | a python script to put it in a std::array, but I shouldn't have
         | to.
         | 
         | There's a proposal for that https://open-
         | std.org/JTC1/SC22/WG21/docs/papers/2020/p1040r6...
         | 
         | > non-fixed-sized containers, ie vector
         | 
         | You can already use them in a constexpr context, you just can't
         | leave it yet. So creating a vector on compile time and then
         | using it on runtime is sadly not working right now but I think
         | that's being worked on as well.
        
         | [deleted]
        
       | codethief wrote:
       | This is really cool, thanks for providing such an in-depth view
       | into Zig's comptime features and how you used them!
        
         | ewalk153 wrote:
         | Agree. This is one of the most instructive tutorials on the
         | comptime language feature.
        
           | Sphax wrote:
           | I didn't really intend to write a tutorial but glad you liked
           | the post !
        
       | longrod wrote:
       | This looks really neat and handy especially the type annotations
       | part. I always got frustrated when accidentally putting the wrong
       | type into a column.
       | 
       | How's the Language Server support for this? Last time I tried
       | ZLS, it was quite well rounded so I am curious to know if this
       | type annotations would work with it or not. Would be really cool
       | if they do.
       | 
       | I have never been able to fully adopt zig due to how frustrating
       | working with strings is but I absolutely loved the comptime
       | functionality.
        
         | xmorse wrote:
         | ZLS currently does not run any comptime code as far as i know
         | 
         | It would be cool to have an official Zig language server that
         | can do it
        
           | Shadonototra wrote:
           | from what i understood, that is what they are planning to do,
           | have an official built in language server
        
           | Tiberium wrote:
           | I think the only real way you can run make a language server
           | understand comptime code is using the compiler as a library,
           | similar to how Nim does it - nimsuggest (the tool for
           | autocompletion, definitions, etc) is basically the compiler
           | itself with some nimsuggest-specific stuff, so it understand
           | macros, templates, compile time code evaluation, etc.
        
             | gpderetta wrote:
             | Isn't that's how most LSP servers are implemented? I'm only
             | vaguely familiar with clangd.
        
               | carlhjerpe wrote:
               | It's moving in that direction, but far from all are based
               | on their compiler still.
        
         | Sphax wrote:
         | zls doesn't support this unfortunately. I don't know what the
         | plans are for comptime support.
        
       | noodledoodletwo wrote:
       | Cool article.
       | 
       | I can't figure out why i am supposed to care about zig beyond
       | it's fun? I get that it's interesting and more safe than C
       | (honestly though what the hell isn 't).
       | 
       | Say you write rust pretty regularly for new product development,
       | what does zig offer to make my life better, my products more
       | stable, etc?
        
         | [deleted]
        
           | [deleted]
        
         | pbronez wrote:
         | The Zig website [0] has an FAQ for this. I'll copy in an
         | abridged version here for convenience:
         | 
         | ==========
         | 
         | Why Zig When There is Already C++, D, and Rust?
         | 
         | - No hidden control flow. If Zig code doesn't look like it's
         | jumping away to call a function, then it isn't.
         | 
         | - No hidden allocations. Zig has a hands-off approach when it
         | comes to heap allocation. There is no new keyword or any other
         | language feature that uses a heap allocator. The entire concept
         | of the heap is managed by library and application code, not by
         | the language.
         | 
         | - First-class support for no standard library. Zig has an
         | entirely optional standard library. Each std lib API only gets
         | compiled into your program if you use it. Zig has equal support
         | for either linking against libc or not linking against it. Zig
         | is friendly to bare-metal and high-performance development.
         | 
         | - A Portable Language for Libraries. Zig is attempting to
         | become the new portable language for libraries by
         | simultaneously making it straightforward to conform to the C
         | ABI for external functions, and introducing safety and language
         | design that prevents common bugs within the implementations.
         | 
         | - A Package Manager and Build System for Existing Projects. Not
         | only can you write Zig code instead of C or C++ code, but you
         | can use Zig as a replacement for autotools, cmake, make, scons,
         | ninja, etc. And on top of this, it (will) provide a package
         | manager for native dependencies. This build system is intended
         | to be appropriate even if the entirety of a project's codebase
         | is in C or C++.
         | 
         | - Simplicity. Zig has no macros and no metaprogramming, yet is
         | still powerful enough to express complex programs in a clear,
         | non-repetitive way. Even Rust has macros with special cases
         | like format!, which is implemented in the compiler itself.
         | Meanwhile in Zig, the equivalent function is implemented in the
         | standard library with no special case code in the compiler.
         | 
         | - Tooling. Zig provides binary archives for Linux, Windows,
         | macOS and FreeBSD. It is installed by downloading and
         | extracting a single archive, no system configuration needed. It
         | is statically compiled, uses LLVM, has out of the box cross-
         | compilation to most major platforms, and ships w/ libc source
         | and dynamically compiles when needed. The Zig build system has
         | caching and compiles C and C++ code with libc support
         | 
         | ==========
         | 
         | [0] https://ziglang.org/learn/why_zig_rust_d_cpp/
        
           | noodledoodletwo wrote:
           | Yea I feel like most of these differentiators aren't things
           | most people care about barring one. Tight integrations with
           | c/c++ is potentially useful, beyond that I don't really get
           | it. It's kind of like Hare in that regard?
        
             | stonemetal12 wrote:
             | In general those are the reasons I see people give for why
             | they still use C instead of C++ or newer languages. Also
             | all of those things were, and maybe still are necessary for
             | embedded systems where C still dominates.
             | 
             | To me it comes down to Zig is a "modern" C, but unlike most
             | other attempts at replacing C it doesn't skip some of C's
             | use cases.
        
             | noodledoodletwo wrote:
             | See I got downvoted a bit... Let me rephrase, other modern
             | languages offer something along the lines of these, of the
             | things that aren't there for say rust, close integration
             | with c/c++ is nice. Ie rust has nostd, etc.
        
               | ptato wrote:
               | out of that list, rust doesn't offer "no macros and no
               | metaprogramming" and "no hidden control flow". maybe
               | these just aren't things you care about?
        
               | noodledoodletwo wrote:
               | Yea but for the most part you can avoid macros, and areas
               | where you can't you can consider them to be keywords in
               | my opinion anyways. Macros aren't all bad, but they do
               | get abused a lot and make a nightmare for others. Fwiw
               | Ive only written one macro and it was for learning
               | purposes only.
        
           | b3morales wrote:
           | > Simplicity. Zig has no macros and no metaprogramming
           | 
           | This one is an odd point; this very article is a
           | demonstration of metaprogramming*:
           | 
           | > Thanks to Zig's type reflection we can read a row of data
           | into a user-provided type without needing to write any
           | "mapping" function: we know the type we want to read (here
           | the User struct) and can analyse it at compile-time.
           | 
           | * Which is a feature I favor, for the record.
        
             | throwawaymaths wrote:
             | I think the poster meant "no macros" (and _especially_ no
             | c-style lexical macros)
        
             | formerly_proven wrote:
             | No metaprogramming as in no separate metalanguage (e.g.
             | templates, macro_rules!)
        
         | DixieDev wrote:
         | Most likely you specifically don't have much reason to care
         | about Zig. Meanwhile, C can still often be found in areas where
         | high performance and precise control over memory are important
         | - such as in small embedded systems and game engine development
         | - and Zig is a great fit as a replacement.
         | 
         | While you can technically use Rust in these domains you'll find
         | yourself jumping through hoops and fighting against quirks that
         | come with it being fairly high-level and very opinionated on
         | how to enforce memory safety.
         | 
         | One such scenario I've encountered is implementing my own
         | memcpy with a loop like `for i in 0..len`. This works in
         | release builds, but without optimisations this gets a deeeeep
         | callstack that eventually also calls memcpy, so you get a stack
         | overflow. Note how memcpy is implemented in rlibc to avoid this
         | issue: https://docs.rs/rlibc/latest/src/rlibc/lib.rs.html#30-38
        
           | noodledoodletwo wrote:
           | Fair enough thanks for explaining. Basically if you want to
           | make your own Malloc or things like it, zig is friendlier.
           | Will say though, I've used rust for gamedev, and found the
           | experience to be really nice. Was I writing my own memcpy
           | though, nope.
           | 
           | It's funny how in rust you can write raw asm, but there seem
           | to be quirks somewhere in the middle.
        
         | winter_squirrel wrote:
         | As someone who uses both for different personal projects:
         | 
         | - I use zig as my build system for both rust, zig, C libraries
         | and linking since the build system works really well for this
         | purpose
         | 
         | - When I need to write applications or libraries that can
         | benefit from compile-time code, I always try and use zigs since
         | it's much easier to use comptime then a combination of rust
         | macros and generics
         | 
         | - I like the zig async story a lot better. Or at least it's
         | much easier to wrap my head around and write code in compared
         | to rust + tokyo
         | 
         | On the other hand, sometimes I know a project will benefit from
         | the borrow checker or I want to use some of the awesome rust
         | crates that the community made and I'll use rust instead.
        
           | noodledoodletwo wrote:
           | Does a really short summary of this read kind of like, "zig
           | is a modern c, but I like using rust as a modern c++"?
           | 
           | Agree, Tokio is a little tricky for people new to rust no
           | doubt, but it's tricky for a reason. It's saving lives in
           | production.
        
             | soggybutter wrote:
             | This is actually the frame of reference I've taken to
             | giving most folks. Zig is to C what Rust is to C++ in my
             | mind. Is there a lot of overlap between all 4? Absolutely.
             | But devs still choose C over C++ (and Rust) in some cases,
             | and I think it'll be similar for Zig
        
               | noodledoodletwo wrote:
               | Thanks for explaining, I really appreciate it.
        
             | throwawaymaths wrote:
             | Just FYI: things that are actually "saving lives" are
             | probably realtime applications, which need things like
             | deterministic execution time, no allocation from the os,
             | bounded memory usage, which rust generally does not give
             | you without a ton of effort.
        
             | verdagon wrote:
             | Can you elaborate on the savings lives part? I sense a good
             | story, would love to hear.
        
             | orangetuba wrote:
             | Yes, but Rust offers something more than just modernizing
             | C++. The borrow checker provides something entirely new
             | that has the potential to make a huge impact.
        
               | jmull wrote:
               | Just semantics, but I think the borrow checker is part of
               | modernizing C++.
               | 
               | (The way to manage memory in C++ and C is to opt in to a
               | memory management pattern... _hopefully_ you 've chosen a
               | good pattern and _hopefully_ you follow it consistently.
               | Patterns are generally backed by utilities and primitives
               | that are _hopefully_ correct, complete, and _hopefully_
               | make it relatively easy to follow the pattern
               | consistently. _Hopefully_ you can get a linter to help
               | you too. In a sense Rust takes the same approach, but was
               | implemented from the ground up to eliminate all the gaps
               | so you essentially don 't have to _hope_ to successfully
               | bridge the gaps yourself.)
        
         | sryie wrote:
         | If zig catches on then the question may change from "why zig"
         | to "do I really need rust?". Rust has a higher entry barrier
         | and is harder to use daily. Is the safety guarantee worth it?
         | In my experience, it is easier to fix a bug than to prove to
         | the rust compiler that there is no bug. I just need a language
         | that finds and reports the bugs (before production). Zig's
         | error handling is interesting in this regard and it may be
         | "good enough". Beyond that, I would prefer to spend my time on
         | the real problem rather than appeasing the compiler.
        
           | noodledoodletwo wrote:
           | It's really not that hard to use once you invest some time
           | into it. I know where you are coming from, but appeasing the
           | compiler actually means "I am writing safe code". Rather then
           | "it compiled let's see what happens in production"
        
             | sryie wrote:
             | "some time" is the entry barrier I was referring to and
             | increases the cost of onboarding and adoption. However,
             | rust also incurs a non-negligible ongoing productivity cost
             | for its complexity.
             | 
             | Rust can provide some guarantees but it still won't protect
             | you from logic errors or a "clever" coworker. In
             | comparison, zig is simple and at the end of the day
             | readability is my best defense against bugs/errors.
             | 
             | There was an interesting comparison (and discussion) of zig
             | vs rust safety a few months ago:
             | https://news.ycombinator.com/item?id=26537693
             | 
             | I find myself agreeing with pron and others in that
             | discussion when they say no one really wants to use a safe
             | language. What they want are correct programs.
             | 
             | What remains to be seen is how easy it is to write correct
             | programs in each and the values people place on the deltas
             | between the two languages.
        
           | throwawaymaths wrote:
           | I think a static borrow checker tool is very likely going to
           | be in the future of zig ecosystem (unlikely to be in the
           | mainline, but that's okay), especially after the intermediate
           | representations stabilize.
        
             | noodledoodletwo wrote:
             | I'll believe it when I see it hit 1.0 and has a healthy
             | user base.
        
         | mongol wrote:
         | Yes, but say you are not yet writing Rust, perhaps you should
         | choose Zig instead of it?
        
           | giancarlostoro wrote:
           | I think you're both asking the same question from different
           | angles. If I understand correctly, and I could be
           | misremembering but Zig is supposed to be compatible with C++
           | not just C, which is something that is not necessarily
           | straight forward in other C / C++ competing languages. I hear
           | even D has some issues with mangling and what not.
           | 
           | In all honesty, I prefer the syntax of D over all the others,
           | it feels the most like Java or C# but with a lot of modern
           | benefits. D is trying to do too much though it feels like and
           | I would love for the next D standard library to support OOTB
           | similar to what Go supports, especially a very minimalist web
           | server, I think all modern programming languages should be
           | capable of spinning up web servers out of the box. This is
           | one small detail Go got right in my opinion.
           | 
           | Here's an article from the Chromium team on challenges they
           | faced with trying to integrate Rust (or at least evaluating
           | it) note the entry was last updated in 2020:
           | 
           | https://www.chromium.org/Home/chromium-security/memory-
           | safet...
        
             | noodledoodletwo wrote:
             | D nim and a few others offer nicer syntax over what's
             | normally C for sure. Yea it doesn't surprise me that an
             | established product had trouble incorporating rust, but at
             | the same time, there's a reason why they went through with
             | it right? Memory safety, no data races, etc. Like there is
             | a motivating reason for using it. Meanwhile lots of other
             | products have found ways of integrating Rust and some of
             | them are risk averse products.
        
           | noodledoodletwo wrote:
           | I see where you are coming from, zig is easier to learn, but
           | zig doesn't offer what rust does with respect to safety. That
           | feature is so hard for me to ignore. I respect it though,
           | some people want to be up and running with a new technology
           | in a day or whatever, rust doesn't give you that unless you
           | are very seasoned.
        
             | throwawaymaths wrote:
             | Honestly many applications don't need the level of safety
             | that rust provides (for small single threaded cli apps or
             | cloud lambdas, just allocate into an arena and throw
             | everything away when the program quits, no UAF or DF
             | because _you 're never freeing_)
             | 
             | At the other extreme, if you're writing an operating system
             | or a language VM, you probably want contextual allocators
             | (like an allocator that takes a runtime argument like
             | "which green thread I'm allocating on") which rust makes
             | extremely difficult.
             | 
             | If you really need memory and resource safety I think the
             | best answer is to be patient. Zig is very easy to parse and
             | I imagine it will be the case that static analysis build
             | tools will come about which can do what you want out of
             | rust.... Being decoupled from the compiler chain you would
             | be able to run fast but guard your prs to main/dev/release
             | (as you see fit) with static analysis tools that will
             | protect you with the safety you seek in an isomorphic
             | fashion to "how rust does it". There's no reason why
             | someone couldn't write it now, but with a lot of things
             | (like ZIR/AIR) being highly unstable -- and these are what
             | you're likely to want to statically analyze for such a tool
             | -- for ones sanity I don't recommend building out a tool
             | like that now.
        
         | hansvm wrote:
         | I write Rust for $day_job and Zig for fun. Rust is great, but
         | if I had to rip on a few places where it's lacking for some
         | applications: Zig maintains a small language footprint, is
         | easier to interop with C, and makes it readily apparent when
         | your code is doing anything non-trivial. To make that concrete:
         | 
         | - The small footprint in Zig enables fast compilation (and
         | getting faster) and fast feedback cycles.
         | 
         | - Arbitrary nastiness can happen using From and other traits in
         | Rust, and the tendency to shadow names and rely on type
         | inference can make that unpleasant to track down. In Zig you'd
         | be forced to make a choice (for any non-trivial type) at the
         | return or call site of how you were going to convert things.
         | 
         | - If you want to use the stdlib and have any non-trivial
         | control over how objects are allocated you're in for a rough
         | time in Rust (say, a circular buffer backing some objects and a
         | reusable arena for others). You'll probably be reinventing a
         | lot of wheels.
         | 
         | - Similarly with issues like implicit locking in stdout. It's
         | executing a syscall per line anyway, but the lock can
         | inadvertently make contended writes 1000x slower, so suddenly
         | logging in multithreaded code needs a dedicated logger, and not
         | any of the common options since those fall back to the locking
         | stdout we're trying to avoid.
        
           | adamdusty wrote:
           | Rust probably had a fairly small "language footprint" when it
           | was only a few years old with no production use cases as
           | well. I've used both in some small hobby projects. I like
           | writing zig significantly more than rust, but we'll see how
           | long the language remains small and compact.
        
             | AndyKelley wrote:
             | On the contrary, it had a larger one because it had green
             | threads which require an entire runtime (similar to Go).
        
       | SkeuomorphicBee wrote:
       | In case anyone else is unfamiliar with Zig syntax and wondering:
       | in Zig the .{ "somevalue"} represents an anonymous list literal
       | [1], and .{.somename = "somevalue"} is an anonymous struct
       | literal [2].
       | 
       | (A bit off topic rant, but Zig documentation is quite bad, it
       | took me a lot more effort that it should to discover the facts
       | above.)
       | 
       | [1] https://ziglang.org/documentation/master/#Anonymous-List-
       | Lit...
       | 
       | [2] https://ziglang.org/documentation/master/#Anonymous-
       | Struct-L...
        
         | LAC-Tech wrote:
         | Zig is still not 1.0. I can forgive its lack of docs at this
         | point, especially how surprisingly readable the std lib is.
        
         | akira2501 wrote:
         | I'm not wild about the new trend of languages of making a bunch
         | of syntax dependent on a single small sigil. It gives me a
         | strong feeling of Perl's historical "eclecticness" and I feel
         | like I'm putting more effort into correctly reading the program
         | back into my mind than I should ideally have to.
        
           | kzrdude wrote:
           | I'm wondering what the point of the period is here, could it
           | be done without it?
        
             | alpaca128 wrote:
             | I don't know why, but this is a part of the language's
             | syntax, for example when matching a union type each named
             | variant also has that period. Same with the argument for
             | print statements (`print("{s}", .{var})`).
        
               | kzrdude wrote:
               | aha, seems like they use the list argument to print
               | instead of having varargs functions then?
        
         | jmull wrote:
         | I thought the docs were quite good.
         | 
         | I used "ziglearn" to understand ("chapter 1" and "chapter 2"
         | have tons of foundational stuff):
         | https://ziglearn.org/chapter-1/
         | 
         | I used the language reference for the details:
         | https://ziglang.org/documentation/master/#Introduction
         | 
         | I agree the standard library docs aren't useful (unless
         | something changed a lot in the last six months)... it seemed
         | always better to just search and read the standard library
         | source directly.
        
           | messe wrote:
           | > I agree the standard library docs aren't useful (unless
           | something changed a lot in the last six months)... it seemed
           | always better to just search and read the standard library
           | source directly.
           | 
           | They're automatically generated. As I understand it they've
           | been holding off on improving them until they have the self
           | hosted compiler working, as it will be easier at that point.
        
           | throwawaymaths wrote:
           | To be fair it's really hard to "search" for tuples and
           | anyonymous structs and get an understanding from "reading the
           | stdlib". It's also enough of a departure from C (but not
           | obviously readable like types on the left) to warrant some
           | sort of big red flag in the lang docs... Understanding this
           | tripped me up a bit
        
       | jhgb wrote:
       | Here's an absolutely crazy idea that I had the other day... Since
       | Zig has comptime, couldn't a Zig reimplementation of SQLite use
       | comptime for compile-time query compilation? Including generating
       | native code for fixed queries? So far I haven't been able to come
       | up with any counterargument for why this wouldn't work.
        
         | AndyKelley wrote:
         | Similar idea: https://andrewkelley.me/post/string-matching-
         | comptime-perfec...
        
         | pvg wrote:
         | The counter-argument is interpreting the query is not what
         | takes up the time in executing a typical RDBMS query. Imagine a
         | db is just a key-value store, the query is some keys and the db
         | just spits out whatever it found in a giant hashtable. That's
         | not going to get faster if you 'compile' the query. It's not
         | going to get much faster if your db is a more realistic three
         | hashtables, two big arrays and a partridge in a b-tree.
        
           | jhgb wrote:
           | It might not be worth for everything, but extremely simple
           | queries on extremely simple schemas would not be the goal
           | here.
        
         | cryptonector wrote:
         | You lose at "reimplementation of SQLite".
        
           | jhgb wrote:
           | Possibly, but then again, if one's aim is to replace C with
           | Zig in the future perhaps completely, because SQLite became
           | de-facto standard file format for many applications (see OGC
           | GeoPackage for example), you might need some implementation
           | of SQLite for that. If a file format is going to stick for
           | decades, you'll definitely get other implementations of that
           | file format sooner or later in environments that can't or
           | don't want to use C.
        
             | cryptonector wrote:
             | So, yes, it'd be nice to have an implementation of SQLite3
             | in some non-C language. However, that's a tall order.
             | 
             | And here you're proposing Zig while someone else will
             | prefer Rust, and someone else Go. So you'll need N>1
             | rewrites.
             | 
             | This is why SQLite3 is written in C then, because for all
             | the ways in which C sucks, it is the most common (lowest)
             | denominator that ticks the portability checkbox.
             | 
             | Language runtimes that want to not have a C runtime
             | embedded are the hardest hit. The best thing to do for
             | those in the short-term is to talk to a C-coded IPC service
             | that runs the C-coded thing that otherwise can't be run.
        
               | jhgb wrote:
               | > because for all the ways in which C sucks, it is the
               | most common (lowest) denominator that ticks the
               | portability checkbox.
               | 
               | This is actually something that Zig is supposed to do as
               | well. There should be nothing that you can do in C but
               | can't do in Zig. So hypothetically, in the future (say,
               | twenty years from now), a Zig implementation of SQLite
               | could be a preferred one since you're not losing anything
               | with it. (With the additional benefit that should you
               | want to, you might be able to compile application-
               | specific queries into it.)
        
             | noodledoodletwo wrote:
             | What environment cannot run C?
        
               | Const-me wrote:
               | GPUs are weird.
               | 
               | HLSL and CUDA have C-like syntax, but underneath the
               | syntax these things are very different from C.
               | 
               | On GPU almost nothing has an address, there's no stack,
               | no malloc/free, no files or printf, and every instruction
               | runs on 32+ threads in lockstep.
        
               | jhgb wrote:
               | Well, for instance, famously, any multiple-stack machines
               | will have a hard time trying to run C because C assumes a
               | single hardware stack. Although I imagine that
               | _currently_ , in most cases, you'll want to avoid C for
               | software reasons, rather than hardware reasons (for
               | example, you're required to deploy pure Java code, or
               | pure C# code, or want to avoid any unsafe code in Rust,
               | things like that).
        
               | cryptonector wrote:
               | > C assumes a single hardware stack
               | 
               | No, it doesn't. C does not even assume a stack. A
               | platform where function call frames are allocated on the
               | heap would not be incompatible with C.
               | 
               | You could say that _some_ C code assumes a stack, but
               | that 's pretty exceptional.
               | 
               | > Although I imagine that currently, in most cases,
               | you'll want to avoid C for software reasons,
               | 
               | Yes.
               | 
               | > rather than hardware reasons
               | 
               | Hard to imagine hardware on which C could not run. Maybe
               | a JVM chip, but even then, you could compile C to
               | bytecode.
        
               | jhgb wrote:
               | > No, it doesn't. C does not even assume a stack. A
               | platform where function call frames are allocated on the
               | heap would not be incompatible with C.
               | 
               | The problem is not with call frames being on the stack or
               | on the heap; even a spaghetti stack would be problematic.
               | One of the problems is that return addresses and data are
               | interleaved in C-style frames, whereas multiple stack
               | machines require them to be separate. It's not that you
               | _couldn 't_ write an implementation of C for a stack
               | machine, it's just that it would be probably very
               | primitive and slow. Yes, you can run C at the very least
               | the way it was done on Lisp machines, by allocating a
               | large byte array and treating it as your physical memory,
               | but surely you would want to avoid it if you could. There
               | really is a reason why stack machines historically ran
               | somewhat exotic languages like Forth.
        
               | cryptonector wrote:
               | No, really, the C language makes no assumptions about
               | this.
        
               | jhgb wrote:
               | You can't take an address of pretty much any input
               | parameter, return value, or local variable of a function
               | on a stack machine because they're all on the stack CPU
               | core's hardware data stack which has no addresses for its
               | elements. In C you should be able to take the address of
               | these objects, using an ampersand. That's not making an
               | assumption?
        
         | [deleted]
        
         | apavlo wrote:
         | > couldn't a Zig reimplementation of SQLite use comptime for
         | compile-time query compilation? Including generating native
         | code for fixed queries?
         | 
         | SQLite already compiles queries into opcodes and then uses its
         | own VM to interpret them. You would have to reimplement the
         | internal VM.
        
           | jhgb wrote:
           | I'm aware of that, but these elementary operations have some
           | definitions in code. Even just calling them in a fixed
           | sequence (as opposed to dispatching at runtime one opcode at
           | a time) would be something optimizable for a sufficiently
           | smart compiler. However, given a good-enough design of the
           | whole system, straight code generation from the query plan
           | shouldn't be a problem either (and at that point, the Zig
           | compiler should be able to do even more work with the
           | generated query code). I mean, any reimplementation would
           | presumably use Zig features heavily anyway -- otherwise you
           | could just link with the C code.
        
       | voigt wrote:
       | I see Zig, I vote up ;) Exciting new language with compelling
       | features!
       | 
       | Great work of the author explaining comptime!
        
         | [deleted]
        
       ___________________________________________________________________
       (page generated 2022-05-27 23:01 UTC)