[HN Gopher] Zig is hard but worth it
___________________________________________________________________
Zig is hard but worth it
Author : signa11
Score : 329 points
Date : 2023-06-01 10:44 UTC (12 hours ago)
(HTM) web link (ratfactor.com)
(TXT) w3m dump (ratfactor.com)
| Alifatisk wrote:
| May I ask what the hype is with Zig? What makes it so attractive?
|
| Is it the performance? The easy interop with C? The ease of
| controlling the memory allocation?
| cynicalsecurity wrote:
| Wait, it's a real language? I thought it was a sarcastic article
| about an imaginary language called zig making fun of hipster
| languages desperately trying to replace C/C++.
| nickelcitymario wrote:
| > [...] easy things seem easy primarily because they are
| familiar. Easy is subjective. But simple things are simple
| because they do not complicate; they have fewer concepts. Simple
| is objective.
|
| This should be printed out as a large poster in every office.
| erichocean wrote:
| Rich Hickey has done more to popularize that idea in recent
| years than perhaps anyone else. [0]
|
| In a lot of ways, Zig is to the _systems programming_ space
| what Clojure is to the _information processing_ space.
|
| If you have 5+ years experience, you want simple, not easy.
| Both languages deliver real advances on that promise in their
| respective domains.
|
| ----
|
| Back to the article, perhaps not coincidentally, the product my
| startup is developing is written primarily in Zig (language
| runtime), Clojure, and an in-house Forth/Factor/Joy derivative
| for user-level scripting. I guess I really do care about
| simplicity...
|
| [0] Simple Made Easy:
| https://www.youtube.com/watch?v=SxdOUGdseq4
| WhereIsTheTruth wrote:
| The issues I have with Zig are similar to the ones I have with
| Rust, the syntax.. I will never get used to it, I find it
| tasteless and non-ergonomic
|
| But, I manage to set it aside because it provides enough
| benefits, I mainly use Zig as a toolchain to crosscompile my
| libraries.. and write some helper externs
|
| Hopefully they manage to improve and ease out the syntax by 1.0,
| I have hopes
| jadodev wrote:
| Have any examples of syntax you find tasteless? Things in Zig
| that feel ergonomic to me: comptime params > separate generic
| args; ptr.* > *ptr; optional pointers > possibly null normal
| pointers; separate syntax for slices, arrays, & pointers > 1
| syntax for ptr & arrays.
| WhereIsTheTruth wrote:
| var t: ?i32 = null; if (t) { t +=1;
| }
|
| This for example doesn't work, you have to capture, many
| little things like that that stacks up and ends up creating a
| non-ergonomic syntax
|
| No for loop, so you have to do multilines things like, and
| now you meet a new : construct, this pseudo for loop now
| looks confusing to look at var i: i32 = 0;
| while (i < 42) : (i+=1) { }
|
| Then constant casting between integers, and also floats..
| also no operator overload for the math types etc..
|
| Also not a fan of the pointer difference between [] * [:0],
| too much different nitpicking that makes iterating slow and
| painful, I understand the benefits, but the way it's done is
| not enjoyable, at least to me
|
| That's just whats on the top of my head, it's been a while I
| haven't wrote Zig code so I may be remembering wrong
| askkk wrote:
| In new last version 0.10.1 it seems that for is not working with
| two arguments? const std = @import("std");
| const expect = std.testing.expect; test "for basics"
| { const items = [_]i32 {4,5,3,4,0}; var sum: i32
| = 0; for(items, 0.. ) |value,_| { sum += value;
| } try expect(sum == 16); } ubuntu
| 22.04, snap zig version 0.10.1 , zig test 1.zig produces:
| 1.zig:7:12: error: expected ')', found ',' for(items, 0.. )
| |value,_| { ^
|
| Edited: To update, I tried snap, but using snap install --classic
| --beta zig is a security risk because it can change the system
| and is not sandboxed.
| EscapeFromNY wrote:
| For loop syntax was changed since 0.10.1.
|
| Zig 0.10.1: for(items) |value| {}
| for(items) |value, index| {}
|
| Zig 0.11-dev: for(items) |value| {}
| for(items, 0..) |value, index| {} for(as, bs, cs, ds,
| 0..) |a, b, c, d, index| {}
| jeroenhd wrote:
| I like Zig as a concept, but every time I've tried it, the
| toolchain lacked good IDE and debugger support. I've tried some
| plugins half a year ago but they either didn't work reliably or
| they missed important features. I'm personally sticking with Rust
| until the day comes that I can just add a VSCode/Clion plugin
| that'll give me an interactive debugger with full autocomplete
| support without fiddling around too much.
|
| There's a lot to like with Zig, despite its unconvential syntax
| and some language decisions I personally disagree with. The
| language is still in development but it's very promising and I'll
| definitely try to learn it before it reaches that magical 1.0
| release.
| jcalabro wrote:
| I've definitely had a good experience writing Zig in VS Code
| with the CodeLLDB extension on Linux [0] and the Microsoft C++
| [1] one on Windows. It's also got the Zig extension which comes
| with the Zig language server [2].
|
| [0]
| https://marketplace.visualstudio.com/items?itemName=vadimcn....
| [1] https://marketplace.visualstudio.com/items?itemName=ms-
| vscod... [2]
| https://marketplace.visualstudio.com/items?itemName=ziglang....
| LispSporks22 wrote:
| > Only time will tell if comptime is the "greatest thing since
| sliced bread" or not.
|
| Common Lisp user here. Am I missing anything that Zig has in the
| compile time department?
|
| edit: Also, does the code in the comptime block have to be valid
| Zig?
| kllrnohj wrote:
| Personally I think comptime is a questionably design and is
| something both Rust & C++ did much better.
|
| In C++ branches that don't have to "compile" are explicitly
| marked as such with `if constexpr`. In Rust you've got macros
| that are also explicit with required `!`. In Zig any branch can
| be a ticking code rot time bomb, just like it was with C
| #ifdefs. It's better in Zig in that it at least has to parse
| and so you've got fewer blatant problems, but the category of
| problems of "I flipped DEBUG from `false` to `true` and now I
| have dozens of build errors to go fix" is still there. And you
| really don't have any warning signs other than "this is
| branching on something that _might_ be known at compile time "
|
| But honestly that's also my general impression of Zig as a
| whole. It's very definitely a "better C", not something that's
| necessarily good/competitive with the broader state of the
| ecosystem. It's like a love letter to C, completely with many
| of the same general problems that C is known to have and that
| other languages have addressed.
| kps wrote:
| It only has to be syntactically valid (parseable).
| cies wrote:
| From the article:
|
| > Easy is subjective. But simple things are simple because they
| do not complicate; they have fewer concepts. Simple is objective.
|
| I'd argue both are subjective, or with a better word: relative.
|
| I'd say Zig is easier and simpler than C in almost all regards.
| The article does not specify what Zig is compared to in order to
| make these statements. Probably the author had C in mind, but
| that was not explicitly mentioned.
| bakuninsbart wrote:
| Where do you guys see good use cases for Zig? I'm intrigued by
| the language but don't really have any good ideas on where to try
| it out.
|
| I thought about trying it out in as small data engineering
| project, but I'm not sure if language support is sufficient for
| the kind of tooling I would need eg. Database adapters.
| jgalt212 wrote:
| I've been thinking about using it for Python hot paths. I'm not
| smart enough to write rust (at least without limitless supplies
| of aspirin). And I'd like to avoid C for all the obvious
| reasons.
| Dowwie wrote:
| Try Elixir.
| pjmlp wrote:
| In what concerns userspace, I don't see any good case, if I
| want a better C, without much features, I rather stick to Go
| even if I dislike some of the design decisions.
|
| Or D, Nim, Swift, OCaml, Haskell, AOT C#, AOT Java,...
|
| If any kind of automatic memory isn't possible/allowed, I would
| be reaching out for Rust, not a language that still allows for
| use-after-free errors.
|
| Maybe it is a good language for those that would like to have
| Modula-2 with a C like syntax, and metaprogramming
| capabilities, and are ex-Objective-C developers.
| distcs wrote:
| > If any kind of automatic memory isn't possible/allowed, I
| would be reaching out for Rust
|
| I have come to the same conclusion but then I also fear that
| Rust will continue to expand in scope and become a monster
| language like C++. Do you or anyone fear that? Is that a
| possibility?
| TwentyPosts wrote:
| Will Rust keep growing? Yes, I think so.
|
| Will it turn into a C++-like monster? I don't know. Maybe,
| but when it comes to C++ it always feels like its "monster"
| status is largely a result of previous mistakes or early
| design decisions piling up, and causing trouble (eg.
| C-style arrays, exceptions, implicit conversions, fiddly
| sum types rather than first class support, no pattern
| matching etc.).
|
| Rust will grow large, and probably complicated, but the
| real issue with C++ are all these past mistakes and a shaky
| foundation, and Rust is doing much, much better in that
| regard. Time will tell if we'll eventually look back some
| of Rust's design decisions as bad or unwieldy (probably).
| riceart wrote:
| > Time will tell if we'll eventually look back some of
| Rust's design decisions as bad or unwieldy (probably).
|
| I think time has already told for things like async and
| lifetimes.
| pjmlp wrote:
| async, yeah it could be better, given the pains. However
| note that adding async to .NET and C++ hasn't been a
| panacea either, to the point that there is a prototype of
| adding Go/Java green threading to .NET, done by the .NET
| team. While with the C++ standard library there isn't an
| executor runtime in the box.
|
| Lifetimes are painful, and a other languages are
| exploring better ergonomics or combining automatic memory
| management with affine/linear types, yet it was Rust's
| adoption that pushed other language designers to actually
| look into this. So from that point of view, quite a
| success, even if Rust vanishes tomorrow.
| TwentyPosts wrote:
| Can't say much about async, since I really lack the
| experience to say whether async in Rust could feasibly
| and realistically be much better than it currently is.
| Some people say that it'd be great if it worked as
| effortlessly as in Go, but I assume that you don't get to
| have that without performance tradeoffs.
|
| As for lifetimes, what's the issue? Do you have any
| reason to believe lifetimes are frustrating because they
| were badly designed, rather than the fact that they're
| making complexity explicit which was previously hidden?
| vilunov wrote:
| Rust hasn't grown in scope very much since its release, but
| in places where it has grown, particularly async and unpin,
| I find that there features interact very badly with
| lifetimes and borrowing. I am often forced to ditch
| borrowing across async method calls and to put everything
| in Arcs, even when the lifetime is well-defined and it
| could be easily used if it had been scoped threads instead
| of futures. I fear that newer features will be incompatible
| with older ones in a similar way, but fortunately there are
| no such features on the horizon.
|
| Considering all that, I still see Rust as the most sane
| choice for writing native programs. I don't really want a
| "better C", I want to write memory-safe software with
| confidence, and that means static analysis or a thick safe
| runtime, whatever is more suitable for the use case.
| mr_00ff00 wrote:
| Technically though, isn't memory safety not necessary in
| some cases?
|
| For example, single player video games. You can exploit
| your own machine if you want, but that's not an issue.
|
| I like rust, but if I ran into async issues and annoying
| stuff, I could see a world where I grab a non-memory safe
| language to make games easily.
| nequo wrote:
| Crashing the program during runtime and having to debug
| it then is still a worse experience than knowing before
| running it that it cannot crash (due to memory errors).
|
| This certainty comes at a cost, either by negotiating
| with the Rust compiler or by putting up with a GC. But
| depending on your calculus, that cost might be worth
| paying.
| yjftsjthsd-h wrote:
| Memory safety isn't just a security thing, it's also a
| reliability thing. That is, even if my games have zero
| security sensitivity I'd still like them to not crash or
| corrupt data.
| pjmlp wrote:
| It is an issue if it also allows players to work around
| DLC and other goodies.
|
| Or if having the game on the system can be used by
| another malicious application as jumping point into root
| access, starting it as subprocess and injecting the
| exploit.
|
| Example, Windows attacks via Notepad.
| chjj wrote:
| Do you maintain any C projects? Personally, I tried using zig
| for its build system (which can also compile C and whose build
| files are written in zig). One of the benefits of this was easy
| cross-compilation to all major platforms.
|
| It might not be a _real_ use-case or anything, but writing a
| `build.zig` file for an existing C project might be a good way
| to at least dip your toe in the water.
| mcdonje wrote:
| >Use Zig as a zero-dependency, drop-in C/C++ compiler that
| supports cross-compilation out-of-the-box.
|
| - ziglang.org homepage
| ldelossa wrote:
| I'm surprised that the reason I'm mostly interested in Zig is not
| mentioned.
|
| This is C interop.
|
| I work with C quite a bit and I enjoy it, however writing a large
| project in C can be tiresome.
|
| Having an option like Zig which can import C headers and call C
| functions without bindings is pretty attractive, especially when
| you want to write something a big larger but still stay in C
| world.
| ziml77 wrote:
| The thing that's espcially nice about that interop is that Zig
| includes its own C compiler. That eliminates the pain of having
| a build script locate an installed C compiler and figure out
| what options should be passed to it.
| lost_tourist wrote:
| Why would I use zig c compiler in place of gcc or clang?
| Mainly for zig interactivity or does it have some advantage
| other than that over the aforementioned compilers?
| TUSF wrote:
| Zig's C/C++ compiler is just clang, but with header files
| for most major platforms included, and sane defaults, so
| there's no hassle getting it it to cross-compile. Some
| companies have been using Zig solely for an easier to use
| clang.
| lost_tourist wrote:
| Ah I see, thanks for your answer!
| workethics wrote:
| Not only that, but zig makes linking against old glibc versions
| easy. For example, to make an x86_64 linux build linked against
| glibc 2.9 when using zig build all you have to do is pass:
| -Dtarget=x86_64-linux-gnu.2.9
| GordonS wrote:
| Damn, that's a magnificent feature! Maybe I should have
| another look at Zig...
| beefcafe wrote:
| This is a killer feature for CTFs/OSCP/etc and why I started
| using it.
| Fiahil wrote:
| C interop is not as much a "killer feature" as it used to be.
| When you deal with data science, web and other similar domains,
| reading and writing JSON ergonomically is much more important
| than being able to call a C function directly. It's just a
| nice-to-have.
| afdbcreid wrote:
| Yeah, but when you're doing systems programming (which Zig
| aims at if I understand correctly), easy interop with C is
| much more important than easy JSON marshalling.
| billfruit wrote:
| What about c++ interop?
| Conscat wrote:
| You can call internal and external linkage C++ functions from
| Zig, but you can't do anything interesting like specialize
| templates or evaluate constexpr functions.
| esjeon wrote:
| C-interop is pretty perfect for most usecases. The only trouble
| I had was that, since command line arguments are converted to
| slices in Zig, I have to convert them back to null-terminated
| strings whenever I call C functions using any of the arguments.
| Nothing difficult but slightly painful.
| thih9 wrote:
| > "I learned Zig in a weekend! ... Six hours! ... 6us!" say the
| blissful lizards.
|
| I don't get it; is this a reference? Could someone explain?
| tylerscott wrote:
| IIRC the mascot is a lizard so here the comment is portraying a
| Zig enthusiast keen on promoting the ease of learning Zig as a
| lizard. That was my take.
| codedokode wrote:
| I don't know anything about Zig except that it is a low-level
| language. Can someone please explain how it is better than Rust?
| Decabytes wrote:
| Zig is not my favorite language to program in, but I think it's
| focusing on a lot of the right stuff.
|
| 1. Easy Build System 2. Drop in Replacement for c/c++ compiler
| (zig cc) 3. Easy cross compliation 4. Single executable compiler
| 5. Package manager 6. Debugabillity
|
| It's the sort of developer focus that has a huge impact
| especially when you are doing it for more than just a hobby.
| Crystal, another language I love, is weak in this area. No tree
| sitter, No tier1 windows support, Major libraries like the Lucky
| Framework that don't build on Windows, a buggy LSP etc. Don't get
| me wrong I love the language, and I will continue to work in it,
| and all of these things are in various states of progress, but
| it's already at 1.8 and some of these issues haven't been ironed
| out yet. I'm not just armchair complaining, I know these are
| hard, and I will contribute once I am more familiar with the
| language
| jsheard wrote:
| I get what Zig is going for in making all operations as explicit
| as possible, but I fear that it's going to turn away fields like
| graphics and game development where it _would_ be a good fit
| except for the lack of operator overloading forcing you to go
| back to C-style math function spaghetti. It 's all fun and games
| until what should be a straightforward math expression turns into
| 8 nested function calls.
| audunw wrote:
| I like Zigs justification for not having general purpose
| operator overloading (no hidden function calls and loops)
|
| But I wish they added:
|
| 1. Ability to declare completely pure functions that have no
| loops except those which can be evaluated at compile time.
| Something with similar constraints as eBPF in other words.
| These could be useful in many contexts. 2. Ability to
| explicitly import overloaded operators, that can only be
| implemented using these pure guaranteed-to-finish-in-a-fixed-
| number-of-cycles functions.
|
| Then you'd get operator overloading that can be used to
| implement any kind of mathematical function, but not all kinds
| of crazy DSL-like stuff which is outside the scope of Zig (I
| have nothing against that, I've done crazy stuff in Ruby
| myself, but it's not suitable for Zig)
| TwentyPosts wrote:
| I am not much of a Zig-head, but the best compromise I can
| think of is having a few operators which purely and solely
| exist for this purpose. In other words, there is no operator
| overloading, but you can define, say, "#+" for any two structs,
| or something like that.
|
| So if you want to encode matrix multiplication, then you'll
| always have to write `mat1 #* mat2`. This feels like a hack,
| and isn't all that elegant, but it'd be clear that every usage
| of such an operator is a disguised function call. (And
| according to what Andrew Kelley said, it's all about not hiding
| function calls or complex operations in seemingly innocent
| 'overloaded' symbols.)
|
| If you want to take this one step further you'd probably have
| to allow users to define infix functions, which would be its
| own can of worms.
|
| Honestly, I am not particularly happy with any of these ideas,
| but I can't think of anything better either!
| ljlolel wrote:
| Idea: allow some weird Unicode operators like Julia does.
| Then it'll be clear the weird operator is doing something
| weird and new. And this already works in other languages.
| There are lots of Unicode
| spenczar5 wrote:
| Writing greek symbols is sufficiently annoying that I
| always kind of resent code that does this. It's not just
| about the first time you are writing code, but also when
| you are reviewing it, or trying to share a snippet with a
| coworker, or lots more scenarios. Maybe it's just me, but
| writing 'z = x [?] d' is really tedious.
| kps wrote:
| [?] is near-worst-case since it's not even Greek. I think
| domain-specific keyboard layouts are as much of a good
| idea as language-specific layouts, but they're a nuisance
| to install on *nix (trivial on OS X). Using .XCompose is
| the most practical *nix approach, in the absence of
| program-specific methods like Julia's tab-completable
| backslash names.
| Conscat wrote:
| I interpret this as meaning that ibus is difficult to set
| up. FWIW, Emacs and Kitty let you input unicode without
| it.
| lvass wrote:
| Just use C-x 8 in Emacs and you'll get any symbol by
| name, with autocomplete.
| [deleted]
| thechao wrote:
| Maybe an operator-overloading _region_? #{
| m3 = m1 * m2 + m3; m3 += m4; }
|
| Basically, pure syntactic sugar to help the author express
| _intent_ without having to add a bunch of line-chatter.
|
| Speaking of operator-overloading, I really wish C++ (anyone!)
| had a `.` prefix for operator-overloading which basically
| says "this is more arguments for the highest-precedence
| operator in the current expression: a := b
| * c .+ d;
|
| Which translates to: a := fma(b, c, d)
| MH15 wrote:
| Huh I've never seen this approach. Very interesting
| solution, could be adapted to the JavaScript matrix
| libraries I bet.
| estebank wrote:
| In Rust you could use a proc macro that parsed the block
| and translates the token to a new token stream that uses
| method calls with the appropriate operator precedence,
| for arbitrary operations you could want to define. You're
| effectively writing a compiler plugin and language
| extension at that point. For targeted niche domains, this
| might be worthwhile.
| bakkoting wrote:
| There's a not-very-active proposal to add operator
| overloading to JS which takes a similar scoped approach:
|
| https://github.com/tc39/proposal-operator-overloading
| thechao wrote:
| This is how TeX handles math -- the "$" operator is an
| "inline" version of the same.
| renox wrote:
| > I am not much of a Zig-head, but the best compromise I can
| think of is having a few operators which purely and solely
| exist for this purpose. In other words, there is no operator
| overloading, but you can define, say, "#+" for any two
| structs, or something like that.
|
| And those operators wouldn't have any precedence.
|
| > If you want to take this one step further you'd probably
| have to allow users to define infix functions, which would be
| its own can of worms.
|
| As long as these infix function are preceded by a
| recognizable operator ("#" in your example), I think that
| this would be fine.
| flohofwoe wrote:
| Zig has a builtin @Vector type that might come in handy for
| most cases where in C++ a math library with operator
| overloading would be used:
|
| https://www.godbolt.org/z/7zbxnncv6
|
| ...maybe one day there will also be a @Matrix builtin.
| jsheard wrote:
| That still breaks if you layer any abstractions on top, for
| example if you wanted to build an AoSoA packet of Vec3s you'd
| have to define an addition of those in terms of a function.
|
| https://www.godbolt.org/z/v8Ta8hEbv
|
| Zig is exactly the kind of language where you'd _want_ to
| build a performance-oriented primitive like that, but AFAICT
| the language doesn 't let you do it ergonomically.
| flohofwoe wrote:
| That's true, but OTH that's already getting into territory
| where operator overloading might start to become
| detrimental because it hides important implementation
| details which might not be expected from a simple '+'.
| Conscat wrote:
| It's a LOT worse than C++ SIMD libraries.
|
| In C++ (EVE, Vc, Highway, xsimd, stdlib), you can specify the
| ABI of a vector, which allows you to make platform specific
| optimizations in multifunctions. Or you can write vector code
| of a lowest-common-denominator width (like 16 bytes, rather
| than specifying the number of lanes), which runs the same on
| NEON and SSE2. Or you can write SIMD that is automatically
| natively optimized for just a single platform. These features
| are available on every notable C++ SIMD library, and they're
| basically indispensable for serious performance code.
| throwawaymaths wrote:
| Probably not. @Vector is not a mathematical vector, it's
| SIMD. it makes sense because there are times when those live
| in registers and a poly fill for stack memory isn't
| burdensome.
|
| @Matrix makes less sense because when it gets big, where are
| you getting memory from?
| flohofwoe wrote:
| For 'game-ey' math code, a matrix is at most 4x4 floats (64
| bytes), that's fine for a value type that might live on the
| stack.
|
| vec2..4 and matching matrix types up to 4x4 is basically
| also what's provided in GPU shading languages as primitive
| types, and personally I would prefer such a set of "SIMD-y"
| primitive types for Zig (maybe a bit more luxurious than
| @Vector, e.g. with things like component swizzling syntax -
| basically what this Clang extension offers: https://clang.l
| lvm.org/docs/LanguageExtensions.html#vectors-...).
| cmbothwell wrote:
| You might like Odin, it has a similar philosophy to Zig
| and supports swizzling:
|
| https://odin-lang.org/docs/overview/#swizzle-operations
|
| Matrix types are also built in:
|
| https://odin-lang.org/docs/overview/#matrix-type
|
| I've thought for a little while that Odin could be a
| secret weapon for game dev and similar pieces of
| software.
| flohofwoe wrote:
| I'm actually dabbling with Odin a bit in the scope of
| language bindings for the sokol headers:
|
| https://github.com/floooh/sokol-odin
|
| It's a very enjoyable language!
| pron wrote:
| As someone who works on another language that is relatively
| reluctant to add language features (Java) we regularly face
| such dilemmas. A user shows up with a problem that could be
| helped by the language. The problem is real and a language
| feature would work, but there are many such problems, and
| adding features to solve all of them will make the language
| much bigger, overall causing greater harm (even those who don't
| themselves use the feature need to learn it to be able to read
| code). What we try to ascertain is how big of a problem it is,
| how many programs or lines of code it affects, and is there
| possibly a single feature that could solve multiple problems at
| once.
|
| So I would ask you this: what portion of your program suffers
| from a lack of user-defined infix operators and how big of a
| problem is it overall? Even if it turns out that the problem is
| worth fixing in the language, it often makes sense to wait some
| years and then prioritise the various problems that have been
| reported. Zig's simplicity and its no-overload (not just
| operator overloads!) single-dispatch is among its greatest
| features, and meant to be one of its greatest draws.
| markisus wrote:
| In robotics, numerical linear algebra expressions comprise a
| large part of the code base. If not by line count, then
| definitely by the amount of time spent writing, reading, and
| debugging such code. This makes Zig unusable for these
| applications, at least not without additional tooling. You
| can get a feel for how unergonomic this is by avoiding the
| use of all arithmetic operators in your code and instead
| forcing yourself to use user defined plus(a,b), minus(a,b),
| assign(a,b), etc, or programming directly with the C blas
| api.
| erichocean wrote:
| > _You can get a feel for how unergonomic this is by
| avoiding the use of all arithmetic operators in your code
| and instead forcing yourself to use user defined plus(a,b),
| minus(a,b), assign(a,b), etc, or programming directly with
| the C blas api._
|
| You've dramatically overstated your case, since that's true
| of every Lisp-like language.
|
| Lisp is a perfectly suitable language for developing
| mathematics in, see SICM [0] for details.
|
| If you want to see SICM in action, the Emmy Computer
| Algebra System [1] [2] [3] [4] is a Clojure project that
| ported SICM to both Clojure and Clerk notebooks (like
| Jupyter notebooks, but better for programmers).
|
| [0] https://mitpress.mit.edu/9780262028967/structure-and-
| interpr...
|
| [1] Emmy project: https://emmy.mentat.org/
|
| [2] Emmy source code: https://github.com/mentat-
| collective/emmy
|
| [3] Emmy implementation talk (2017): "Physics in Clojure"
| https://www.youtube.com/watch?v=7PoajCqNKpg
|
| [4] Emmy notebooks talk (2023): "Emmy: Moldable Physics and
| Lispy Microworlds":
| https://www.youtube.com/watch?v=B9kqD8vBuwU
| KerrAvon wrote:
| Why do you think this is true of Lisps? Emmy would not
| seem to be a good example because it actually does
| overload arithmetic operators to support extended data
| structures. Look at, for example:
|
| https://cljdoc.org/d/org.mentat/emmy/0.30.0/doc/data-
| types/m...
| erichocean wrote:
| > _forcing yourself to use user defined plus(a,b),
| minus(a,b), assign(a,b)_
|
| This is the complaint I was responding to. Here is that
| code in Clojure (a Lisp): // What the
| GP claims is bad for doing math: plus(a,b)
| minus(a,b) assign(a,b) // <= I have no idea what
| this does, or has to do with math. //
| Let's actually use the original math operators, but with
| function notation: +(a,b) -(a,b)
| // And here's the Clojure/Lisp syntax for the same:
| (+ a b) (- a b)
|
| Lisp doesn't have "operators", so it doesn't have
| "operator overloading." What it does have is multi-
| dispatch, so yeah, the implementation of `+` can depend
| on the (dynamic) types of both `a` and `b`. That's a good
| thing, it means that the `+` and `-` tokens aren't hard-
| coded to whatever the language designer decided they
| should be in year 0, with whatever precedence and
| evaluation rules they picked at the time.
|
| The point I'm making is that you absolutely DO NOT need
| to have special-cased, infix math operators to "do math"
| in a reasonable, readable way. SICP is proof, and Emmy is
| a breeze to work with. And it turns out, there are a lot
| of advantages in NOT hard-coding your infix operators and
| precedence rules into the syntax of the language.
| hellcow wrote:
| Using plus(a,b) for complex types sounds fine to me... I
| have to imagine if I were working with a huge file of these
| for a while it would start to feel normal, just like every
| language has a different syntax but you eventually feel
| comfortable using.
| KerrAvon wrote:
| Are you sure you would find this more ergonomically
| pleasing:
|
| assign(x, plus(a, plus(b, plus(c, b))))
|
| When you could have:
|
| x = a + b + c + d;
|
| Or:
|
| (let x (+ a b c d))
|
| ?
| tuhats wrote:
| I have played around with using @Vector for linear algebra.
|
| This removes the need for operator overloading for a vector
| type, which covers most use cases of operator overloading and I
| often in fact think is the only legitimate use case.
|
| I don't get to use `*` for matrix multiplication, but I have
| found I do not mind using a function for this.
|
| I have only been playing with this in small toy programs that
| don't to much serious linear algebra and I haven't looked at
| the asm I am generating with this approach, but I have been
| enjoying it so far!
| bodge5000 wrote:
| I'm no expert on zig, but the one area I have seen it shooting
| up in popularity is game dev. Though I guess that is largely as
| a replacement for C, so "C-style" wouldnt be much of a concern
| jsheard wrote:
| Zig looks like a fine C replacement, but C isn't what people
| are using to make games in the vast majority of cases. It's
| all C++, and operator overloading is part of the "sane
| subset" that everyone uses even if they hate the excesses of
| modern C++ as a whole.
| felixgallo wrote:
| as a long time game dev, I actively don't want operator
| overloading. That's some spooky action at a distance
| nonsense. I'm not sure I have seen a codebase that involved
| operator overloading, either, and I've worked in or near a
| good quantity of well-known titles.
| jsheard wrote:
| There's no accounting for taste, but the two major
| publicly available engines (Unreal and Unity) both use
| operator overloading in their standard math types.
| Taywee wrote:
| You'd rather use explicit function calls for all linear
| algebra and geometry operations? I don't think adding two
| vectors using an overloaded + is that spooky or distant.
| flohofwoe wrote:
| FWIW Zig can do that without operator overloading:
| https://www.godbolt.org/z/7zbxnncv6
| cyber_kinetist wrote:
| First of all that only works with vectors, but I want
| operator overloading to also work on things like matrices
| or custom types (for example quaterions, or a symmat3
| struct that represents a symmetric 3x3 matrix using only
| 6 floats).
|
| Additionally, for efficient math code you often want
| vector / matrix types in AOSOA fasion: for example
| Vec3<Float8> to store an AVX lane for each X/Y/Z
| component. I want vector/matrix operations to work on
| SIMD lanes, not just for scalar types, and Zig currently
| can't support math operators on these kinds of types.
| felixgallo wrote:
| I have a marvelous proof that you can solve that with
| comptime but unfortunately the margins of this website
| are too small to contain it.
| lvass wrote:
| Do us a pastebin, please.
| kprotty wrote:
| Vectors in Zig are SIMD types. Vectors in games are
| probably algebraic types. Using SIMD for the latter may
| not be that useful if 1) specific elements are accessed
| frequently 2) transformations involve a different
| operation happen on each element.
| mr_00ff00 wrote:
| Would love to see zig in game dev. I've tried some rust and
| while I love rust in general, I find game dev in it a bit of
| a mess.
| adastra22 wrote:
| Have you tried bevy? I'm starting with bevy for a non-game
| project, but I'm blown away by how simple it is to use once
| you get used to the magic.
| the__alchemist wrote:
| Bevy isn't on the same level as tools like UE and Godot.
| adastra22 wrote:
| Depends on what you're doing. I'm writing a non-game app
| that requires a scenegraph, raycast mouse selection tool,
| and other tools of the sort typically required by games
| and provided by a game engine. But there's a lot of game
| stuff I don't need, and I need to make major
| customizations to the rendering engine. It ended up being
| easier to implement in bevy, due to its modularity, than
| it would have been in UE4 or Godot.
| Ygg2 wrote:
| To be fair Godot isn't on same level as UE.
| mr_00ff00 wrote:
| Maybe I need to give bevy a second go. My big issue is I
| felt I was learning to speak "bevy" instead of using
| rust. A lot of functions I wrote required queries of
| components, but the queries were built and called behind
| a magically wall.
|
| I don't have much game dev experience though outside of
| simple games using libraries like raylib to just move and
| draw stuff. Maybe once things get complicated enough they
| are all like bevy.
| adastra22 wrote:
| This is true on both fronts, I think. Bevy magics away
| the interface between you and the engine via the ECS
| macros, in a way that is very unusual for a systems
| programming language like Rust. But that's more or less
| how all game engines are these days from what I
| understand.
| pjmlp wrote:
| Not really, it is mostly around communities like Handmade,
| most studios couldn't care less and it doesn't fit most
| engines that they are using.
| sigsev_251 wrote:
| To be fair, there is an operator overloading proposal for
| C2y/C3a and there is at least one compiler that offers operator
| overloading as an extension.
| kapperchino wrote:
| For the math stuff you can do things like a builder pattern
| where you can flatten the nested functions. But operator
| overloading is definitely preferred
| iskander wrote:
| Is there anything akin to Maturin for Zig?
|
| I would love to use it as an extension language for Python.
| helen___keller wrote:
| My main issue with Zig is that I'm scared to invest time in
| writing something nontrivial to see the community/adoption
| flounder then regret not using Rust or C++ later
|
| The language itself is fun. The explicit-ness of choosing how
| allocation is done feels novel, and comptime is a clean solution
| for problems that are ugly in most languages.
|
| Aside from lack of community I'd say the biggest nuisance is
| error handling in nearly everything including allocations. I get
| that allocation can fail but the vast majority of programs I
| write, I just want to panic on an allocation failure (granted
| these aren't production programs...)
|
| Edit: in retrospect, allocator error handling verbosity is
| probably necessary due to the power the language gives you in
| choosing allocators. If I use the general purpose allocator then
| my edge case is PC out of memory; if I use a fixed buffer
| allocator, a failed allocation is a code bug or a common error
| case, so we might want to handle the failed allocation and
| recover
| faitswulff wrote:
| My impression of the Zig language as a total outsider is that
| it seems like it has the underpinnings of success: it has a
| niche, it has a governance model, and it has real commercial
| users. It just has to not blunder very hard on the way to some
| level of promised stability.
| distcs wrote:
| > If I use the general purpose allocator then my edge case is
| PC out of memory
|
| What does PC mean in this context?
| nativecoinc wrote:
| Maybe "the whole computer is out of memory" (general purpose
| allocator). Contrast with a custom allocator which might only
| be able to work with a few kilobytes (for example).
| helen___keller wrote:
| Personal computer
| kubanczyk wrote:
| player character
| loeg wrote:
| > Aside from lack of community I'd say the biggest nuisance is
| error handling in nearly everything including allocations. I
| get that allocation can fail but the vast majority of programs
| I write, I just want to panic on an allocation failure (granted
| these aren't production programs...)
|
| The C strategy for this was just to wrap malloc() with
| something called xmalloc or malloc_nofail or whatever:
| void *malloc_nofail(...) { void *res = malloc(...);
| if (res == NULL) { abort(); } return
| res; }
|
| (Or whatever.) The same would work in Zig, I think.
| helen___keller wrote:
| Yes you can easily make a one liner allocation function in
| zig that takes an allocator as input with a comptime type and
| panics if allocation fails and returns the unwrapped
| allocation
|
| I just say nuisance because zig code often looks like Go code
| in that almost every return type becomes an error union as
| allocation error handling (and maybe other errors) trickle up
| TylerE wrote:
| From my experience with Zig (limited but not zero) it seems
| like an ok solution to a problem I don't have, and don't
| forsee having.
| bsder wrote:
| > My main issue with Zig is that I'm scared to invest time in
| writing something nontrivial to see the community/adoption
| flounder then regret not using Rust or C++ later
|
| This is 100% a real concern.
|
| If I'm going to choose Zig, it's because it is _SO_ much better
| on some axis that the community /adoption isn't an issue as I
| gain the benefits almost immediately. That means that C++ and
| Rust probably aren't in the scope of choice anyway.
|
| I especially like the comment from elsewhere in thread where
| they are using it for scripting, of all things, because they
| can pop out code that builds and works on Windows _and_ Linux.
| That 's a good example--you gain the benefits immediately even
| if you later have to unwind that to something like Python.
| kuroguro wrote:
| I suppose you could write a few line wrapper that panics :)
|
| But yeah, most of the time I don't even want to think which
| allocator to use let alone handle it's errors.
| eatonphil wrote:
| This is basically what I've come to do in the Zig scripts I
| write at work.
|
| It took a bit of getting used to when I joined but we agreed
| as a team to have all meaningful scripts written in Zig not
| bash (for one, bash doesn't work on Windows without WSL and
| we need to support Windows builds/testing/etc.).
|
| It makes about as much sense as any other cross-platform
| scripting option once I got used to it!
|
| Some examples:
|
| Docs generation: https://github.com/tigerbeetledb/tigerbeetle
| /blob/main/src/c...
|
| Integration testing sample code: https://github.com/tigerbeet
| ledb/tigerbeetle/blob/main/src/c...
|
| Running a command wrapped in a TigerBeetle server run: https:
| //github.com/tigerbeetledb/tigerbeetle/blob/main/src/c...
| rowls66 wrote:
| I am truly puzzled by this. I understood Zig to be a very
| low level language like 'C'. Why would you write scripts in
| it?
| eatonphil wrote:
| It's significantly nicer to write than C (my opinion
| obviously). I see it as a general purpose language.
|
| But mostly the team decided to do this because we wanted
| to unify on one language and double down on the
| investment in Zig.
|
| I'm not a fanboy (nothing wrong if anyone is, just
| clarifying about myself); I think this choice was right.
| 59nadir wrote:
| For what it's worth I think this is an excellent choice.
| Back in 2019 I was deciding whether I wanted to pursue
| Zig full-time and one of the upsides that I determined
| was that once you reach critical mass writing all of your
| code for tools and things in Zig you end up with things
| that are really exactly what you need and with a very
| high baseline for speed, flexibility, and so on.
|
| Right now I'm considering the same thing but with Odin
| and for many of the same reasons that I had for Zig; it's
| an excellent language to write foundational code in and
| once you do, you end up being able to build significantly
| more understandable, reliable, stable and consistent
| things.
|
| This, but on a company level, is a real multiplier. Once
| you adopt a couple of Python scripts and that's OK, you
| give up the possibility of wielding this sharp spear.
|
| Edit:
|
| I think "How I program C" by Eskil Steenberg is an
| interesting window into what you can get if you laser
| focus on a language and environment and allow yourself to
| build up a mountain of code that you dogfood:
| https://www.youtube.com/watch?v=443UNeGrFoM
|
| At some point I will likely soft-retire and at that point
| it's exceedingly unlikely that I'll bother with using
| other people's libraries except a few key ones that I
| think are decent, and at that point there really is no
| reason I'd sit down and write these fundamentals in
| anything but a lower-level language. Odin, Zig or
| something like it would pretty much be the only thing on
| the table.
| hoosieree wrote:
| Binary executables are a nice feature, especially for
| distributing to users.
|
| It's much easier for most people to download a standalone
| "mac" or "windows" binary than to know if they already
| have the right version of Python or Perl or Clang (and
| all the transitive dependencies your project adds).
| eatonphil wrote:
| We don't host the built binaries of these scripts (we
| could!), but we bootstrap the local environment through a
| single bash script or batch script (Windows) that pulls
| down the Zig compiler. Then everything else in the repo
| depends only on that until we get until client-language
| specific bits which of course depend on other languages.
|
| But yeah it is quite simple still.
| vaughan wrote:
| I'm moving all my scripting to TypeScript using Bun (JS
| runtime written in Zig).
|
| For scripting its a way better choice. `bun:ffi` also
| makes it trivial to run C or Zig code when you need to.
| rowls66 wrote:
| I guess I don't see C as programming language for writing
| scripts in either. In my view any language that requires
| a separate complication step is not a scripting language,
| and therefore not a language in which one writes scripts.
| In C or Zig you write programs.
|
| Maybe I am just being too pedantic.
| eatonphil wrote:
| I didn't call it a scripting language. Nor do I think C
| would be great to write scripts in either. :) I only said
| we write scripts in Zig. But if you'd like to call these
| files programs instead of scripts then that's ok too!
| chrsig wrote:
| I think for the problem space zig is trying to fit in, it's
| pretty essential to have custom allocator support thoroughly
| baked in.
|
| It's the sort of thing that lets a data structure be used on
| both a gpu and cpu, allocation out of shared memory, or
| ensure that no dynamic allocations are happening at all.
|
| Most programs don't have those concerns - so zig may not be
| the best choice for them. For the programs that do have those
| concerns, forethought about allocators is pretty important.
| Right tool for the job, and all that.
| mgkimsal wrote:
| https://archive.is/cMm11
| galaxyLogic wrote:
| Love the picture. People often say how easy something was for
| them. They are saying they are a very capable, smart person.
| Would you rather hire someone for whom everything is easy, or
| someone for whom things seem difficult?
|
| In other words saying they learned something fast or that
| something is easy for them, is at least partially self-promotion.
| So claims of how easy something was for them it have to be taken
| with a grain of salt.
|
| The interesting thing for the rest of us is WHY something is
| easy, or difficult. That would be helpful for others to know.
| This article is just that, it tells us why Zig can be difficult.
| What to look out for.
| jksmith wrote:
| Is this a writeup about Zig, or any Wirth language written 50
| years ago? Asking for some Modula2 OG.
| latch wrote:
| I've now written a lot of zig code (http.zig, websocket.zig,
| log.zig, zuckdb.zig, etc.) I think Zig falls into an "easy to
| learn, average/hard to master" category.
|
| Some insiders underestimate the effort required for newcomers to
| build non-trivial things. I think this is because some of that
| complexity has to do with things like poor documentation,
| inconsistent stdlib, incompatible releases, slow release cycle,
| lack of package manager, etc. For an insider living and breathing
| Zig, not only aren't these huge challenges, they aren't really
| "Zig" - they are just transient growing pains. For someone
| getting started though, the current state of Zig is Zig.
|
| I wish Zig had a polished package manager (there's one in the
| current development branch, but you don't as much use it as fight
| it). They could then move some of the less polished code into
| official experimental packages, helping to set expectations and
| maybe focus the development efforts.
| JC770 wrote:
| I just start to learn Zig,any suggest to beginners?Bro
| hiccuphippo wrote:
| Other than the main documentation, check ziglearn.org and
| ziglings.org. Also read the std code, specially the tests
| when you want to know how to use something.
| zoogeny wrote:
| I've lately thought that a package manager is as essential to a
| new language as a standard library. I would also add a LSP and
| standard code formatter to that list.
|
| It is a bit unfortunate because all of the above is a pretty
| tall order. We're getting to the point that new languages are
| expected to boil the ocean by the time they reach 1.0
| chrsig wrote:
| > I've lately thought that a package manager is as essential
| to a new language as a standard library. I would also add a
| LSP and standard code formatter to that list.
|
| Agreed. Especially on a formatter. The number of code review
| comments it cuts out is incredibly time and energy saving.
|
| > It is a bit unfortunate because all of the above is a
| pretty tall order. We're getting to the point that new
| languages are expected to boil the ocean by the time they
| reach 1.0
|
| In order to get into production? yes. there are minimum
| requirements that must be met. those are higher now than in
| the past, because of lessons learned the hard way. those
| problems have been solved (for some value of solved) in
| existing ecosystems -- a new language wont change the need
| for them to be solved.
|
| it shatters the dream of hacking up something on a weekend
| and having it turn into a hit success, but it also removes
| the case of hacking up something in 10 days and suffering the
| consequences for the next 30 years.
|
| Until they have what you mentioned, the languages _aren 't_
| ready for large scale use -- they need to grow into it. They
| can be useful prior to that -- enthusiasts and early adopters
| can reap what benefits are provided. That adoption is what
| fuels the development of things like a standard code
| formatter.
|
| edit: fixed omission of a unit of time after '30'
| 6keZbCECT2uB wrote:
| Not sure about lsp, but I think if you defined your
| language in tree sitter, you might be able to define a
| basic autoformatter generically on tree sitter to
| accelerate bootstrapping your language.
|
| You could also use an existing language agnostic package
| manager like nix, guix, or conda to bootstrap your language
| package manager.
|
| Lsp is something I don't know of a way to make that easy
| without overly constraining the design space.
| clessg wrote:
| > but it also removes the case of hacking up something in
| 10 days and suffering the consequences for the next 30
| years
|
| Ha, I thought this sounded distressingly familiar!
|
| "In September 1995, a Netscape programmer named Brandan
| Eich developed a new scripting language in just 10 days. It
| was originally named Mocha, but quickly became known as
| LiveScript and, later, JavaScript."
| savolai wrote:
| Would love to understand better what exactly is language
| specific about package managers? You would think a winner
| would emerge in this space like one has in version control to
| be used with all languages, just separate repos for different
| ecosystems?
| anon84873628 wrote:
| I was also wondering this. Why does every language need to
| reinvent the wheel?
| vineyardmike wrote:
| Different languages do imports differently. There are
| different constructs for "exports" and modules and
| namespaces that prevent a common single directory
| structure.
|
| Pip used to store packages in a global location, now most
| of python used a Virtual Environment per project.
|
| Node uses a "vendor" directory within the project
| structure. This is probably the easiest case.
|
| Go used to store everything globally in the "go path" but
| now with go modules it does something else.
|
| Java doesn't need source code, just single JAR files, but
| it needs it within the classpath.
|
| C/++ is very flexible, but varied depending on how you
| build and set up your project.
|
| Swift/ObjC requires doing whatever apple wants and dealing
| with their tooling.
|
| Everything is different. If you want "one winner" the
| closest you get it is the system package manager (of which
| multiple exist) and pointing your project to its package
| cache. But not all system package managers handle multiple
| concurrent versions of the same package.
|
| Maybe one day people will standardize against Nix which
| seems to be the closest?
| arp242 wrote:
| Zig has a pretty decent LSP.
|
| I'm not so sure a package manager is really all that
| essential; it can certainly be convenient but especially in
| the space Zig is looking at it's pretty workable without one
| (without complex deep dependency trees you can use git
| submodules or just copy a directory). Or let me put it this
| way: I never really missed a package manager in Zig.
| BaculumMeumEst wrote:
| > I'm not so sure a package manager is really all that
| essential
|
| I agree with you, but this is subjective. Not having a
| package manager will probably turn off many from the
| language. But it's OK for the Zig folks to make a call that
| a lot of people won't agree with if it doesn't fit their
| vision of the language.
| ReleaseCandidat wrote:
| > I'm not so sure a package manager is really all that
| essential;
|
| For open source software (libraries or programs, that
| depend on other libraries or programs), it is essential (if
| you're not distributing single functions like with Unison).
| For closed source it doesn't matter that much.
| arp242 wrote:
| "cp -r ~/some-lib ~/my-project/" works well enough if
| some-lib doesn't have dependencies on its own. Or git
| submodules if you want something a bit more fancy. I
| sometimes do this even for languages with package
| managers, as it avoids a world of complexity.
|
| Obviously a package manager is _useful_ , but Zig is
| relatively low-level and long dependency chains are much
| less common than in e.g. Python, Ruby, and of course
| NodeJS. So I'd argue it's not _essential_. All the other
| things mentioned in the to top comment are far bigger
| issues IMO.
| TylerE wrote:
| [flagged]
| tuckerpo wrote:
| Why? A submodule can be frozen at a given commit. They're
| trivially updated or rolled-back, too.
| latchkey wrote:
| > I've lately thought that a package manager is as essential
| to a new language as a standard library.
|
| This was the approach Ceylon took. Sadly, despite a lot of
| effort, the language never took off.
| johnnyjeans wrote:
| I disagree. I actively avoid languages that rely on package
| managers simply because they only give the illusion of being
| beneficial. It ends up being more boilerplate I have to learn
| to use an ecosystem, because they don't actually solve
| dependency hell and now there's a whole additional
| complicated tool with its own DSL I have to contend with in
| order to fix what's broken (or even diagnose issues.)
|
| The more peripheral crap I have to deal with to use your
| language, the less I'm likely to use it in the first place. I
| don't need, want or care to learn yet another idiosyncratic
| fragile system. Finding source tarballs is a complete non-
| issue, and inevitably I'm going to have to manually build
| things anyways to figure out what erroneous assumption a
| library is making about the underlying system which is
| causing the build to fail or the runtime to crash, so the
| package manager just ends up being extra steps. Without fail,
| that has always been my experience with language package
| managers.
|
| In the pursuit of making things simpler, we're really just
| making them harder.
| zoogeny wrote:
| I'm not sure I understand this issue. The existence of a
| standard package manager doesn't prevent you from manually
| vendoring dependencies if you want to. I have personal
| experience working on node.js projects where several
| dependencies were just `cp` into a directory and treated
| like local modules, no npm involved at all.
|
| It's like `apt` or `brew` for system dependency management.
| It is there if you want it but you can just as well
| download a tar and config/make/install yourself if you
| want.
|
| In many ways, it is like a standard lib. No one forces you
| to use it. If you prefer the simplicity of your own
| implementations then I see no reason why you can't just
| write your own.
|
| But when you want the advantages of a package manager, and
| there are advantages that you may not appreciate but others
| do, then having a standard one built into the language
| feels preferable to having a dozen non-standard
| independently competing variations that the community
| cobbles together.
| fauigerzigerk wrote:
| The cynic in me would say that including a standard package
| manager is absolutely necessary to stop several of them
| popping up every year :)
| gen220 wrote:
| Just curious, not snide: what language fits this criteria?
|
| C/C++? Using Python 3.7+ in a way that completely ignores
| Pip, because the stdlib is now quite expansive?
| thegeekpirate wrote:
| Odin
| seba_dos1 wrote:
| Python is quite often being used without pip, as the
| modules are often packaged by distros already (and in
| many distros they _have_ to be packaged this way in order
| to include the application that uses them in the repos).
| paulddraper wrote:
| Must be C/C++.
| JohnFen wrote:
| I agree entirely. Relying on a package manager in order for
| a language to be useful indicates to me that there's a
| deficiency in the language.
| pornel wrote:
| Is every language supposed to come with HTTP and TLS
| stack, clients for every database, de/serializers for
| every format, every image and video codec, every
| de/compressor, GUI toolkits, 3D rendering, Bluetooth...
| where do you stop?
|
| And then how do you maintain all of this bloat to a
| competitive level, so that users don't need to reach for
| faster/newer alternative packages anyway?
|
| And how do you maintain portability and backward
| compatibility of a language with such a vast API surface?
|
| In modern development there's just too much stuff to keep
| everyone happy with batteries included. Sooner or later
| users will need something that isn't built in, and that
| will cause pain and crappy workarounds if the language
| doesn't have first-class support for dependencies.
| pdntspa wrote:
| You could manage it like .net did before
| chocolatey/winget -- pretty much a free-for-all, just add
| yourself to the COM list through whatever means you want
| and have at it
|
| But that was a mess. I still have nightmares from dealing
| with windows assembly cache issues.
|
| Honestly it reminds me of some of the shit I've had to
| deal with with pip (what do you mean you can't resolve
| this dependency???)
| JohnFen wrote:
| I suppose that I just never had a problem maintaining any
| dependencies in code I write. Package managers have long
| been a bit of a pain for me as a developer, and with some
| languages (like Python), they are a huge PITA for me as a
| normal user of applications.
|
| So overall I don't view them in a very positive light.
| They're something I have to put up with.
|
| No matter, it is what it is. Carry on. :)
| pornel wrote:
| When Python was originally designed disk space was
| precious, and access to the Internet was rare, and its
| dependency management was designed for that world. Its
| multiple retrofitted package managers never fully fixed
| it.
|
| However, better integrated package managers can work
| well. In case of Node.js and Cargo, the main argument
| against them is that it's _too easy_ to add dependencies.
| jeroenhd wrote:
| The problem with source tarballs is that you need to then
| manually watch out for updates and bugfixes for every
| dependency you pull in. You also need to deal with the
| bespoke build system of your packages of choice or manually
| build something compatible with your project. You can also
| choose not to and skip vulnerable, buggy code for a few
| years like some companies do, but that's hardly an
| advantage. You also need to ship (and possibly license) all
| of your dependencies.
|
| Alternatively, you can let the system package manager do
| all the hard work for you. That works great, as long as you
| only target one OS or put in the work to maintain
| compatibility with multiple OS releases.
|
| My experience with languages without package managers is
| that large, maintained projects all invent their own
| package manager (remote git repos? shell scripts
| downloading files? a two-stage build process written in the
| language itself?) in combination with some sort of Makefile
| generating hell script that breaks for a while when a new
| OS release comes out.
|
| This approach works if you're the entire system. SerenityOS
| can do this, because it's basically an entire operating
| system and userland all inside one repository. ChromeOS can
| probably do it as well, since the app portion isn't running
| OS-native code anyway. For everyone else, it's just making
| someone else do the work of the package manager manually.
| paulddraper wrote:
| > new languages are expected to boil the ocean by the time
| they reach 1.0
|
| The reason is that there are existing high-quality
| languages/ecosystems.
|
| (Which is a good thing!)
| adamrezich wrote:
| package managers are relatively easy to put together and
| release with your language--provided that you want your new
| package manager and surrounding ecosystem to work exactly the
| same as other, popular ones, without putting any effort into
| improving the status quo. doing better than other languages'
| package managers takes significant effort, because it's both
| a computer engineering problem _and_ a social engineering
| problem.
|
| it's nice when a new language has a package manager right out
| of the gate, but I would like to see more new languages take
| a more measured approach and aim to significantly _improve_
| upon past efforts, instead of merely replicating them out of
| some sense of obligation.
| cassepipe wrote:
| To get an idea, what is your programming background ? Are you a
| C or C++ programmer ?
| VyseofArcadia wrote:
| I used Zig for a weekend project and _loved_ it, but I am
| resolved to not use it for anything else until it hits 1.0. I
| don 't have time to write and re-write and re-re-write my code
| as the language and stlib stabilize.
| Tozen wrote:
| If that's the thinking, looks like it will be a long wait.
| Appears to be another 2 to 3 years before 1.0 hits. And it
| publicly came out in 2016, so add all those years up.
| TaupeRanger wrote:
| Maybe a few years ago it would've been "worth it". But with LLMs
| coming to swallow up all coding tasks and turning programmers
| into prompt engineers within a few years time, I can't see it
| being "worth it" any more.
| mr_00ff00 wrote:
| I don't want to make assumptions, but have you tried systems
| programming with LLMs?
|
| A few years and everyone will be prompt engineers is laughable.
| I hope I can actually use it productively for more than unit
| tests in a few years.
| Taywee wrote:
| You still need to understand the code you are generating,
| testing, and debugging. LLMs don't replace a need for more
| expressive programming languages.
| jiripospisil wrote:
| I've been playing with it and so far but I'm more impressed with
| their build system rather than the language itself (it seems to
| be way more flexible and simpler than alternatives which is
| pretty rare). They did however get the module system right. You
| can just organize the file structure in any way you like. I hate
| Rust's "everything is a single module" system with passion.
| mike_hearn wrote:
| How do you find it simpler? From taking a quick look it appears
| to just be an API for invoking build steps, and the build
| script is itself a Zig program.
|
| I ask if it's really simple, because the JVM space went in the
| same direction with Gradle (build script = program) and by the
| time it gets more sophisticated that can turn out to be pretty
| painful. In particular, IDEs struggle to get the information
| they need, scripts can become highly complex, and there are
| various other problems.
| pjmlp wrote:
| Gradle is Ant reinvented, by those that didn't learn why we
| moved into Maven.
| rayiner wrote:
| Alternative languages are cool, but I struggle to see the point
| of a systems programming language that doesn't offer static
| memory safety in 2023. Rust isn't necessarily the best and final
| answer--it seems like there is a broad design space to explore
| for memory-safe systems programming languages. But Zig seems to
| occupy the same local maximum as C--a relatively simple, non-safe
| systems language--and doesn't have a killer feature that
| justifies not just using C.
| haberman wrote:
| The killer feature of Zig IMO is comptime. C++ has spent over a
| decade now marching towards making more and more of the
| language available at compile time, but in an awkward and
| complicated way (constexpr, consteval, constinit). Zig comes
| out of the gate with a unified and coherent compile-time
| evaluation feature that effectively obsoletes not only
| constexpr/consteval/constinit, but C++ templates too. This is
| "doing more with less" in a way that I find really compelling.
| Conscat wrote:
| Zig does not have anything analogous to constinit, because
| Zig does not have object lifetimes or constructors. Comptime
| is also a massive pain to use for generating new data types
| (you have to return a type from a comptime function), and it
| cannot express anything analogous to CRTP.
| helen___keller wrote:
| If we're comparing C to Zig I'm not sure what memory safety
| even needs to be mentioned for.
|
| For C to Zig there's plenty of reasons one might prefer Zig.
| For memory safety obviously you might opt to choose neither.
| rayiner wrote:
| In a vacuum, one might prefer Zig. But given that everyone
| already knows C and the ecosystem is so highly developed, it
| takes a gamechanging feature like Rust's memory safety to
| make an alternative language attractive (beyond a "this is
| cool" project--which I totally support).
| helen___keller wrote:
| That is probably why Zig has such a focus on seamless C
| interop. There's a good thread in these comments talking
| about this.
|
| Regardless, point taken. You're more or less describing the
| internal fear I have (mentioned in another thread) that if
| I dedicate time to a nontrivial Zig project I will regret
| it if/when there's no Zig community in N years
| alwaysbeconsing wrote:
| I haven't tried Zig, but "all the things you like about C
| plus better versions of most/all of the awkward bits" seems
| like a reasonable value proposition. Especially since the
| compiler can apparently let you use C painlessly alongside
| your Zig -- enabling incremental rewriting.
| j-james wrote:
| Can you use Zig painlessly alongside C? Does `zig cc` or
| an equivalent provide for writing Zig libraries that then
| can be called by a main C function?
| [deleted]
| helen___keller wrote:
| Yes probably as painlessly as a nonC language can get.
| First class support for C calling conventions, struct
| layouts, and so on
|
| https://ziglearn.org/chapter-4/ See here
| j-james wrote:
| Yeah, I read through that: unless I'm missing something I
| think what I'm curious about is "calling C code from Zig
| and vice versa" in the to-be-written section.
|
| Nim also has support for `ctypes` and compiles to C as
| its main target: yet though its interop is powerful it
| lacks in ergonomics, formerly you had to manually wrap
| every function you wished to use and this was only
| recently fixed by a macro-heavy external library.
|
| I'm wondering what Zig does because IMO even if you have
| an excellent technical solution getting people to
| actually use it alongside C is hard, it has to be
| _seamlessly_ seamless. Nim 's C interop is rarely used
| outside of wrappers and it even more rarely is used to
| produce C libraries (though perhaps that's more a fault
| of incompatible type systems)
| TUSF wrote:
| With Zig, you just write something like:
| const c = @cImport({ @cDefine("SOME_MACRO",
| "1"); @cInclude("raylib.h"); });
|
| Which translates the header files directly into Zig and
| allows you to call into them under whatever namespace you
| assigned them under. You even get completions (assuming
| you're using the language server)
| krupan wrote:
| Honest question here (that I have every time I see someone talk
| about memory safety in 2023), are you aware of Ada/Spark?
| sarchertech wrote:
| I tried Zig for a few weeks but ended up choosing Odin for a game
| dev side project I'm working on. Odin feels a lot more high
| level, but still gives you low level control when you need it.
| 59nadir wrote:
| I've settled on Odin as well and I think it's currently way
| ahead for game development than Zig is. Even for other things
| I'm currently more likely to write it in Odin, despite writing
| Zig from 2019 to 2022. The reasons really come down to error
| handling being better in Odin overall with payloads being
| attachable to errors as well as the context system and zero
| values making it relatively painless to really only talk about
| the things that need talking about and letting the rest be
| unsaid.
|
| There are also several similarities: Custom allocators as part
| of the ecosystem and language, no RAII, easy ways to propagate
| and handle errors the right way, tagged unions with table
| stakes like exhaustiveness checking.
|
| I think Odin and Zig have some fundamental differences (and
| plenty of similarities) and when trying Odin out I was
| surprised to find that I preferred the Odin way overall.
|
| For gamedev stuff Odin wins due to a few things; swizzling on a
| code level is super nice, array programming built-in to the
| language, vendor libraries shipped with the language that allow
| you to just get going almost no matter what you're doing, and
| so on.
| truckerbill wrote:
| I want to invest in Odin but I see the velocity and growing
| mindshare that Zig has and I wonder if it's not better to
| settle for that. Also how do you find the compile times?
| Tozen wrote:
| Part of "mindshare" are organizations pushing it on social
| media and marketing. Choose the language that solves your
| problems and that you like. Don't make a choice because a
| group is telling you what to like, is bullying others
| because they like something different, or are trying to
| shove something down your throat for their profit or
| benefit. Perfectly fine to have an independent mind, and
| make decisions best for you.
| 59nadir wrote:
| I think by the time I have a massive project where compile
| times could actually hurt the newest endeavor with
| compiling to an intermediate form, etc., will already be
| released so it's likely that I'll dodge that entirely.
|
| For what it's worth I haven't found any language constructs
| that seem to make the compile time grow considerably, so I
| think the risk of adding a library and suddenly being faced
| with massive compile times is fairly low in comparison to
| some languages. With that said, I'm only using the core lib
| and vendor libraries.
|
| JangaFX by way of GingerBill reports that their 200kloc
| EmberGen[0] project takes 5 seconds to compile:
|
| > On my old machine, it took 5 seconds, and now it takes
| 2.2 seconds on my new machine.
|
| Before some paths in the compiler had multithreading added
| to them that number was 15 seconds for the same project. As
| far as I know both of these numbers are for unoptimized
| builds, i.e. development builds.
| mr_00ff00 wrote:
| Just looked at Odin and I really like the syntax, but I
| feel the same way. I feel like the community and ecosystem
| is the key elements and zig seems to be headed in the
| direction to grab that.
| sarchertech wrote:
| They're very different languages despite having some
| similar capabilities.
|
| I also found the game dev libraries in Odin far easier to
| use then the ones in zig.
| mr_00ff00 wrote:
| Yeah I did briefly look for zig game libraries and
| couldn't find much.
|
| I see the basic differences, but I'll have to dig deeper.
| parasense wrote:
| The main take away is:
|
| > Something that makes Zig harder to learn up front, but easier
| in the long run is lack of undefined behavior.
|
| Reminds me of the old discussions of Fortran Vs C, and
| specifically in the early times before C had a standard library.
| What we call "undefined behaviour" was just an idiom of the
| language where the "behaviour" was sometimes on purpose, but
| recognised might not be portable. And so the point here is the
| idea of undefined behaviour is tied to portability on some
| levels, and isn't just some purely academic idea about the
| compiler or abstract syntax trees.
|
| So I'm concerned about the potential over-zealous prejudice
| against undefined behaviour, but I think we can all agree
| deterministic software is better than otherwise. The catch is
| that sometimes UB is deterministic, and yet dares to not be
| idiomatic.
| kps wrote:
| C89's 'undefined behavior' was a failed attempt to say "you get
| what the hardware gives you".
| jsmith45 wrote:
| Yeah. In hindsight for a fair bit of it, it could have been
| sensibly changed to implementation defined behavior, or to
| constrained unspecified behavior. (Constrained such that
| people know what the possibilities are, but the compiler need
| not document its choice, and might not make the same choice
| in all circumstances. The latter could allow for scenarios
| where letting an optimizer do the faster thing when
| detectable, and what the hardware natively does otherwise,
| for example. Obviously still a potential footgun, but less of
| one than full undefined behavior).
| tialaramex wrote:
| This makes no sense because C89 is defined for execution on a
| abstract machine, something which doesn't exist and thus has
| no hardware.
|
| Such beliefs are however compatible with the inveterate C
| programmer excuse that their nonsense programs _should_ be
| correct if only the standards committee, compiler vendors, OS
| designers, and everybody else in the known universe were not
| conspiring to defeat their clear intent.
| kps wrote:
| From the C89 Rationale, "The potential for efficient code
| generation is one of the most important strengths of C. To
| help ensure that no code explosion occurs for what appears
| to be a very simple operation, many operations are defined
| to be _how the target machine's hardware does it_ rather
| than by a general abstract rule. An example of this
| willingness to live with _what the machine does_ can be
| seen in the rules that govern the widening of char objects
| for use in expressions: whether the values of char objects
| widen to signed or unsigned quantities typically depends on
| which byte operation is more efficient on the target
| machine."
| tialaramex wrote:
| > _many operations are defined_
|
| My emphasis. Undefined Behaviour is not an example of
| operations being defined.
| pklausler wrote:
| Ironically, C is now way more portable than modern Fortran is.
| The Venn diagram of feature portability across the 6 or 7
| actively-maintained Fortran compilers is very messy.
| Symmetry wrote:
| Assuming that bytes are 8 bits long or that negative numbers
| are represented with two's complement is a lot less dangerous
| these days than it was when C came along.
| jasfi wrote:
| Nim isn't hard, it just has a small community.
| anta40 wrote:
| I haven't done any production-level stuff with Nim (still
| learning it), I think overall it's a nice language (I also like
| Python & Pascal).
|
| If your goal is applying for job, Go is obviously a better
| pick.
| michaelcampbell wrote:
| I don't know Zig so I can't comment much on the content, but the
| author's writing style I enjoyed immensely; enough to make me
| want to pick up Zig for fun. I do have some C background, albeit
| decades ago, so maybe I'm in the right spot for it.
| badrabbit wrote:
| Everything is hard when you first learn it. If you find it easy,
| that's only because you don't have to learn part of it because
| you learned the concept in a different language. Even learning to
| count was hard when we were small children.
|
| A better measure IMO is how long it might take _you_
| specifically. For example, Rust is much easier for me to learn
| than Haskell because I have never coded in a functional language
| before. Golang was very easy to pick up on. I never took time to
| learn python and powershell, I just kept referencing existing
| code and googling for examples because they were both mostly
| familiar languages with a different syntax.
| thadt wrote:
| > Crucially, there is basically no documentation for the standard
| library except for the source code itself.
|
| From the viewpoint of someone learning about a new language, I
| find the accessibility of the standard libraries goes a long way
| toward helping me understand how things fit together. It is a
| first stop to see how experts in the language use it. Browsing
| through the standard libraries of languages like Zig, Go, and
| Python - they're usually well-documented and readable enough to
| be a tutorial, even before you've dug into learning it. Others
| (Rust, C++) are a bit more, ah, _technical_ for the novice.
| TwentyPosts wrote:
| Afaik Zig has the issue that basically everything happens on
| the Discord server, where it can't be indexed via search
| engines, or found by anyone who wants to have a quick question
| answered. This would be "fine" if the standard library and
| language were much better documented, but it isn't, and it's
| still ripe with bugs.
|
| In other words, you're forced to use the Zig Discord server if
| you want to find answers to any simple questions, and this is
| (sadly) not obvious at all to newcomers to the language.
| scns wrote:
| The new Zulip version can make chats accessible from the
| outside. In the thread about it someone wrote OSS Projects
| should switch to it.
| girvo wrote:
| This is true for Nim as well, in that most of the discussion
| is on the Discord/Matrix server. I'm not a fan personally, at
| least IRC was easily archived and searchable in practice.
|
| I really dislike how Discord has become "forums in the 2020s"
| Vecr wrote:
| Rust has the standard library documentation at
| https://doc.rust-lang.org/std/ or on your local computer, if
| there's really nothing like that for Zig I think that's a
| problem. Are you sure there's no `info zig` or something like
| that?
| sciolistse wrote:
| There is https://ziglang.org/documentation/master/std but
| it's not always been correct, and the descriptions are
| lacking. The new one should hopefully fix that.
|
| Personally I've never had an issue reading through the source
| for zig std, and if your editor supports it you can just 'go
| to implementation' on most things. Hopefully the code remains
| relatively readable since I find it preferable to see the
| actual code + some basic tests rather than trying to navigate
| those documentation sites.
| tialaramex wrote:
| I certainly wouldn't recommend trying to figure out C++ by
| reading either of the three major C++ standard libraries.
| pron wrote:
| > there's not a direct correlation between the slimness of a
| language's syntax and ease of learning
|
| That's absolutely true, but (the standard library aside) the
| "syntax" -- or, rather the syntax and core semantics -- of a
| programming language are arbitrary axiomatic rules, while
| everything else is derivable from those axioms. So while it is
| true that a small language can lead to a not-necessarily-easy-to-
| learn overall programming experience, it is the only arbitrary
| part, and so the only part you need to _memorise_ (or consult the
| documentation for when dealing with some subtlety you may have
| forgotten). So a smaller language reduces the need for "language
| lawyering" _after_ you learn it.
|
| Some languages (e.g. lisps) are deceptively small by relying on
| macros that form a "second-order" language that interacts with
| the "first-order" language, but Zig doesn't have that. It has
| only one language level, which is small and easy to memorise.
|
| But yes, Zig is a bigger language than C, but a far smaller
| language than C++. What's amazing, though, is that C++ is
| strictly more expressive than C (i.e. there are programs that
| could grow exponentially faster in C than in C++, at least
| without the help of C macros), but Zig is as expressive as C++
| (i.e. program sizes may differ by no more than a small constant
| factor) while being much closer to C in size, and it achieves
| that without the use of macros.
| ImprobableTruth wrote:
| You still have to memorize the "design patterns" that replace
| 'missing' features. Especially annoying for something like
| interfaces where there's a bunch of variants and people often
| use implementations with awful error reporting reminiscent of
| C++ templates.
|
| Now, it's definitely neat that you can do reasoning from first
| principles on it, but I'm not sure how much of a gain that is.
| mannykannot wrote:
| On the other hand, Brainfuck.
| the_duke wrote:
| I'm not a Zig expert, but I have a different take here.
|
| Zig has comptime, which is essentially a compile time macro
| written in the main language and with type reflection
| capabilities.
|
| They can introduce complex behaviour and fail in very cryptic
| and unexpected ways, which results in an experience very
| similar to macros or C++ template literals.
| pron wrote:
| The objects that are manipulatable by comptime are ordinary
| program objects and types -- not ASTs. That means that while
| it's true you can get compile-time errors in similar
| situations to macros, the errors themselves are like ordinary
| runtime errors in an untyped language -- while occurring at
| compile-time, they look like runtime error in Python or JS --
| rather than errors due to some "second-order" manipulation of
| symbols like templates or macros, and so are easier to
| diagnose (you get a regular stack trace for one).
|
| There is also another interesting difference, albeit a
| theoretical one. Zig's comptime is what's known in formal
| languages to be _referentially transparent_ (it basically
| means that you cannot distinguish between two otherwise
| identical objects that differ only in their reference name)
| while macros are not. Because referential transparency is
| strictly less expressive than "opacity" (but it's also
| simpler!), it's surprising that so many practical use cases
| for macros can be addressed with the less powerful (but
| simpler and much easier to debug) comptime. That's quite a
| discovery in language design. While other languages also have
| comptime-like constructs, they also have other complex
| features that have made it hard to see just how powerful
| something like comptime _alone_ can be.
| auggierose wrote:
| It's not really surprising that purely functional
| programming is expressive. Indeed, it is as expressive as
| "opaque" programming.
| pron wrote:
| There's nothing pure functional here (perhaps the term
| "referential transparency", which some FP fans have come
| to misunderstand and perpetuate its misunderstanding is
| what may have given you that impression). Referential
| transparency is very much less expressive than
| referential opacity, as there are certain statements that
| simply cannot be expressed if your language is
| referentially transparent. For example, in programming, a
| referentially opaque expression can refer to the name of
| the variable holding some value. In programming,
| languages like Zig and Java are more referentially
| transparent than languages like C and Haskell because the
| latter have macros.
| auggierose wrote:
| Referentially transparent means that you can replace an
| expression with its value without changing the meaning of
| the program. If everything you can do must be
| referentially transparent, then that's purely functional
| programming, because applying functions without side-
| effects is pretty much the only thing you can do then. Of
| course, there are some other techniques like rewriting,
| which strictly speaking are different from purely
| functional programming, but I consider these two things
| to be pretty much the same thing.
| pron wrote:
| > Referentially transparent means that you can replace an
| expression with its value without changing the meaning of
| the program.
|
| Not quite. A referentially transparent expression (E) is
| one where you can replace any of its subexpressions (A)
| with another (B) that has the same _meaning_ (not
| value!!!!) as (A) without changing the _meaning_ (not
| value!!!) of E. However, in purely functional languages,
| the meaning of any expression is a value, but _that 's_
| the important thing about them, not the fact that they're
| referentially transparent as imperative languages equally
| are. We often use the word "semantics" or "denotation"
| instead of "meaning" in the above, and we say that a pure
| functional one is one that has "value semantics", i.e.
| one where the meaning of an expression is a value.
|
| Most programming languages are referentially transparent
| when not using macros (that was the whole point of
| talking about referential transparency in programming in
| the first place), and that's important because it
| demonstrates both the expressive power and the complexity
| of macros.
| norir wrote:
| Do you have sources for your definition? The original
| definition that I'm finding from Quine seems to broadly
| support the interpretation that an expression is
| referentially transparent if it can be replaced by its
| value without altering program semantics, as others have
| stated. Regardless, it isn't clear to me how macros are
| any more or less referentially transparent than function
| calls in an impure language.
| pron wrote:
| The thing that is preserved is "meaning" or "referent" --
| the term Quine uses (hence, "reference transparency") --
| not "value". The distinction between referent/meaning and
| value is the most important aspect of distinguishing
| between pure FP programming languages and others, and yet
| that's the thing that is so commonly confused by FPers
| using the terminology, which makes it quite pointless.
|
| In most programming languages the reference or meaning of
| a term is _not_ a value; in pure functional languages the
| meaning is a value and _that 's_ what makes them special,
| not their referential transparency which they share with
| imperative languages.
|
| Here's an example from C: int global_x
| = 0; void f() { x++; } void g() {
| x++; }
|
| f and g have the same meaning in C (but the function
| `void h() { x += 2; }` does not) yet `m(f)` and `m(g)`
| will not have the same meaning if M is defined as:
| #define m(x) #x
|
| However, f and g are interchangeable anywhere else (this
| is not actually true because their addresses can be
| obtained and compared; showing that a C-like language
| retains its referential transparency despite the
| existence of so-called l-values was the point of what I
| think is the first paper to introduce the notion
| referential transparency to the study of programming
| languages: https://github.com/papers-we-love/papers-we-
| love/blob/main/l... You may be surprised to see that
| Strachey also uses the word "value" but his point later
| is that value is not what you think it is)
| norir wrote:
| Thank you. That response was clarifying. I understand now
| what you mean. Funnily enough though, the paper you cited
| begins:
|
| "Any discussion on the foundations of computing runs into
| severe problems right at the start. The difficulty is
| that although we all use words such as 'name', 'value',
| 'program', 'expression' or 'command' which we think we
| understand, it often turns out on closer investigation
| that in point of fact we all mean different things by
| these words, so that communication is at best
| precarious."
|
| Rather than debating the semantics of the colloquial
| usage of referential transparency, I'm more interested in
| the question: what can I tell at the call site of a
| function without knowing the definition of the function?
| In an impure language, I cannot tell whether the call has
| side effects without looking at the definition. This is
| true whether I am using a macro or simply a regular
| function call.
|
| Now, even if my language of choice is impure, referential
| transparency of expressions is still a useful concept
| that can inform how I write my program. I can use naming,
| for example, to suggest whether a function call may have
| side effects even if the language compiler can't verify
| the property. Not perfect, but better than nothing. And
| if I'm really confused by a bug, I can always just assume
| that the name is misleading and the function may have
| unintentional side effects. In other words, I can use the
| concept of referential transparency to implement a
| metaprogramming system in my head.
| whateveracct wrote:
| I'm very sure the commenter is being a little pedantic
|
| But even pedantry can't argue that Java is a
| fundamentally more referentially transparent language
| than Haskell lol. That threw me for a loop.
| pron wrote:
| Right, the incorrect and quite pointless common use of
| "referential transparency" in FP fan circles tends to
| throw people off when they first see and understand the
| actual meaning of the term.
| whateveracct wrote:
| Well it's not pointless. The term as used in FP has a
| pretty well-defined meaning [1] and it is a quality only
| some programs have. And a program having that quality
| enhances (fast-and-loose) equational reasoning.
|
| [1] I can point at most Java code and prove how it fails
| the definition. It's not especially hand-wavey.
| auggierose wrote:
| Do you have a pointer to a paper where "referentially
| transparent" is defined in your sense? I grant you that
| values of a programming language should be distinguished
| from the meaning of an expression, which will be a value
| of some sort in the logic. In that sense, _any_ language
| with a denotational semantics will be referentially
| transparent. So maybe what you are really saying is:
| macros usually don 't have a denotational semantics. Not
| sure that it is helpful to call this referential
| transparency, because it differs from the meaning most
| people associate with it.
| whateveracct wrote:
| Can you give me an example of a Haskell expression which
| isn't reverentially transparent (without
| unsafePerformIO)?
|
| > An expression is called referentially transparent if it
| can be replaced with its corresponding value (and vice-
| versa) without changing the program's behavior.
|
| ^ that is the definition of referential transparency I am
| aware of.
|
| You seem to be implying that FPers have bastardized the
| term through their misunderstanding.
|
| But the bog standard FP definition is a real and useful
| concept. Maybe it stole something else's name? But I
| don't think it's due to being mistaken. Because the FP
| concept itself is pretty rigorous.
| pron wrote:
| > Can you give me an example of a Haskell expression
| which isn't reverentially transparent (without
| unsafePerformIO)?
|
| Yes: https://github.com/ncaq/debug-trace-var The trick,
| however, is not unsafePerformIO (destructive mutability
| has nothing to do with referential transparency in
| general, although it breaks it in Haskell specifically)
| but with TemplateHaskell, as quoting has everything to do
| with referential transparency.
|
| > But the bog standard FP definition is a real and useful
| concept.
|
| Actually, it's rather tautological. It defines FP
| circularly (see my comment here:
| https://news.ycombinator.com/item?id=36152488). It says
| nothing more than the far more useful explanation: "the
| meaning of every expression is a value".
| whateveracct wrote:
| hm okay so basically anything that doesn't use TH or
| unsafePerformIO is gonna be referentially transparent.
| And TH is even deferentially transparent at TH-time. It
| only "breaks it" when evaluating the whole program. But
| each "stage" maintains the property.
|
| I'm assuming any pure language with macros is also r.t.
| at each stage and only pedantically breaks r.t. when
| combined. But I don't think that especially hurts the
| ability to do fast and loose reasoning so long as the
| core language is pure.
|
| It definitely doesn't seem correct to say Java is more
| referentially transparent than Haskell here. You don't
| have to go into such niches in Java to lose that
| property.
| pron wrote:
| > You don't have to go into such niches in Java to lose
| that property.
|
| It's not so easy. You'd have to examine debugging
| information in stack traces and use reflection. You can't
| write such a "trace" operator in Java or in Zig. Of
| course, without macros, C is almost perfectly
| referentially transparent and Haskell is, too (except for
| unsafePerformIO).
| whateveracct wrote:
| You can also mutate a list that is passed in and suddenly
| you cannot do substitution to reason about your program.
| norir wrote:
| > Zig's comptime is what's known in formal languages to be
| referentially transparent (it basically means that you
| cannot distinguish between two otherwise identical objects
| that differ only in their reference name) while macros are
| not.
|
| In general this is true, but it is possible to write a
| hygienic macro engine that is referentially transparent.
| Many (likely most) macro engines are indeed unhygienic
| though. I am not convinced that comptime is a better
| approach than a well designed hygienic macro system but it
| is an interesting research area.
| Symmetry wrote:
| I haven't had a chance to play with comptime in Zig yet but
| I'm sort of curious how it compares to Nim's compile time
| facilities. You can declare variables with 'var' for true
| variables, 'let' for things that are runtime constant
| within a scope, or 'const' for compile time constants whose
| values can come from functions or whatever as long as it
| can be resolved by the compiler. And then you've got 'when'
| as a compile time equivalent of 'if'.
| [deleted]
| distcs wrote:
| > Some languages (e.g. lisps) are deceptively small by relying
| on macros that form a "second-order" language that interacts
| with the "first-order" language, but Zig doesn't have that.
|
| What are some other examples of such languages that rely on
| second-order languages? You mentioned Lisps. Would Forth be
| another example? Are there more examples?
| spenczar5 wrote:
| I think Ruby is sometimes used in a way that looks second-
| order. It allows so much metaprogramming that you can really
| make a full DSL. For example, RSpec:
| describe "order" do it "is marked as complete" do
| expect(@order).to be_complete end it
| "is not yet shipped" do expect(@order).not_to
| be_shipped end end
| pron wrote:
| C++ templates. Also the rich type-level language in languages
| like Idris (these are qualitatively different, but I'd say
| they're another example of a second-language-within-a-
| language that operates at a different level of objects).
| ImprobableTruth wrote:
| If type level functions are a "second language", then so is
| Zig's comptime.
| pron wrote:
| It's not. comptime reifies types as regular objects
| (pretty much like maps), so you're not working at the
| type level; it's no more of a second language than
| reflection in Java. Of course, you cannot express things
| like the famous vector concatenation that's expressible
| with dependent types
| (https://gist.github.com/cbiffle/82d15e015ab1191b73c3)
| (unless the vector sizes are known at compile time,
| obviously).
| KingLancelot wrote:
| [dead]
| ok123456 wrote:
| One annoying thing I ran into when trying zig is they don't
| distribute debs any more for Debian distributions. They just tell
| you to use a snap. I don't have snap, and don't want it.
|
| Compiling it requires the latest llvm toolchian (16), which is
| only realistically going to be available as a package if you're
| on a bleeding edge distribution.
| pacaro wrote:
| I understand this, but haven't found this to be an issue
| personally. I just download the pre built tarball, expand it,
| make sure that /opt/zig-latest symlinks to the right folder,
| and setup path
|
| That's more work than apt-get install for sure, but not so much
| more
| hellcow wrote:
| You can also use something like zigup to make fetching the
| latest master/managing multiple versions easier.
| eatonphil wrote:
| What's wrong with downloading the binary? curl + mv + chown
| should do it?
| netule wrote:
| Zig's in the process of getting added to the mainline Debian
| repositories: https://bugs.debian.org/cgi-
| bin/bugreport.cgi?bug=995670
|
| Hopefully, this process will continue soon as the bug seems to
| be getting a bit stale.
| stared wrote:
| What are the use-cases in which it might be worth switching from
| Rust to Zig?
| epage wrote:
| matklad, of rust-analyzer fame among many other things, wrote
| up their thoughts on Zig:
| https://matklad.github.io/2023/03/26/zig-and-rust.html
|
| I've seen some put it as "zig is good when `unsafe` heavy
| code".
|
| Personally, even when writing life-or-death software,
| allocation errors were too much of a pain to deal with and much
| prefer Rust's approach for 99% of software. The question is if
| another language like zig provides enough value to justify
| existing for that 1% of use cases (all numbers made up :) ).
| logicchains wrote:
| When you need to be very careful about memory allocation and
| use various custom allocators for stuff, and you don't care too
| much about memory safety. Rust makes working with custom
| allocators somewhat painful, in exchange for safety, so if you
| don't need the safety, no point going through that pain.
| notfed wrote:
| What kinds of programs don't care about memory safety?
___________________________________________________________________
(page generated 2023-06-01 23:00 UTC)