Hacker Timesnew | past | comments | ask | show | jobs | submitlogin

I tried Nim, since it felt easier to use than C for low level stuff.

I don't really like the syntax though. Python barely does Python like syntax right.

Is Zig a good alternative. I vastly prefer higher level languages like C#. Have has a special place in my heart, but it's not supported outside of a few game engines.



If you like higher level languages like C#, you are not going to like Zig, except the surface similarity in syntax.

not liking syntax is not enough reason not to use a language. It takes a few days to get over the unfamiliarity in syntax. concepts are much harder to learn.


If I'm not getting paid to use it, why use a language I don't like.

Syntax is a big deal.

C# looks like Java because Microsoft wanted to court Java devs.

I will admit that I prefer higher level languages since I don't care much for memory management. I just want to build cool things.


What syntax are you looking for? If you want C syntax, D will be the closest (most valid C code is also valid D code). If you want Ruby syntax, there's Crystal. Zig feels more verbose to me. For example, there are no multiline comments and no operator overloading, which kind of got to me when I tried Zig. This is, of course, purely subjective. Some people like the Zig syntax.


D Lang did come up in my research. But it feels like it never took off.


True, but you mentioned Nim earlier, and this is a discussion of Zig, which hasn't even reached a stable release. D is an old, stable language that's still under heavy development. It's used by some companies and is able to support an in-person annual conference. I have no concerns about the code I write today working ten years from now.


There are more similarities in the lower level than you think. Once you start writing structs that use generics to specialize their allocator (as in, for really hands-on memory management), it starts looking similar, much like when you write portable SIMD code, which I should commend Zig for having the API for that is similar to .NET one.


What do you mean not enough reason? It's not your decision.


> I vastly prefer higher level languages like C#. Have has a special place in my heart, but it's not supported outside of a few game engines.

Where is C# not supported? It’s an incredibly versatile language. You even have a bunch of features to go “low-level” if needed (not as low-level as C of course, you still have the CLR): Span<T>, ref returns, ref struct, function pointer, unsafe keyword


Typo.

Have should be Haxe.


Oh, sorry, then forget my answer


I now use C# for high-level programming and Zig for low-level. Perfect combination for me.


Would you be ok sharing more details how you combine both? I’ve been experimenting with this for a personal project, but integrating zig in a .NET solution has been fairly messy. Would love to read others experiences doing so successfully


I should be more precise, I don't use them in same project. I am C# professional but using Zig for simple embedded programing projects and some tools that don't have requirment for complex runtime. If I would have to glue them together then I would probably compile Zig to webassembly component and use it in C# hosted env.


Using wasm for this sounds like a difficult and wasteful approach.

Is there a reason you are avoiding a simple compilation of Zig part of codebase into a dynamically or statically linked library and calling into it with P/Invoke? You only need a `Target` and maybe `None Include=...` items in .csproj to instrument MSBuild to hook the building process of Zig into dotnet build and co.


Yes, P/Invoke should work, especially when you are targeting a single platform. However, for multiple platforms, there might be some unexpected obstacles I am not aware of.


The answer to this is to map the RID to the argument passed to Zig. Or just build on a target platform as an alternative, if possible. WASM is not a solution and would not work properly. It is the last resort effort in language with inferior interop capabilities.

I'm just putting a disclaimer that using WASM is a very wrong kind of suggestion, would likely not work the way you expect it to (you would have to use WASM for .NET too which is in many places experimental and is a huge performance killer) and no one does it - there are appropriate ways to target multiple platforms in a solution that splits logic between .NET and C/C++/Rust/Zig/Swift/etc., especially that Zig offers nice cross-compilation toolchain. Mind you, the use case for this is accessing language-specific libraries and for performance the solution really is writing faster C# instead.


It depends on the integration use case. For example, if I were writing a plugin system for my C# app, safety would take precedence over performance, and using WASM modules would make more sense. If I had some performance-critical code in Zig, then P/Invoke would be the way to go. However, in most cases, it's better to avoid P/Invoke, as C# is already a very performant language.


IMHO the advantage of zig isn’t performance but generating a minimal library that exports C headers, making it simple to integrate in any language. My use case is a custom document editor in zig, with a “bring your own renderer” approach”. It integrates in a C# desktop app, as a base for something like a modern RichEditBox (just in spirit - not RTF based, with way more advanced features).

I want the editor to be usable in other GUI stacks, a C-compatible library is the only approach that makes sense here


How it will work if you don't know target platforms in advance? Will you compile zig module for every possible native target you know? Is sorce code public or only compiled library? WASM is universal solution, compile once run it everywhere. There is a reson why Microsoft Flight Simultor choosed WASM modules for plugin system.


Yeah, that’s what I personally do but maintaining the PInvoke interface during development adds a good amount of overhead as things are changing around. It’s also a lot of boilerplate to deal with, and you only notice at runtime that something is wrong. It doesn’t feel like a well integrated solution


If Zig can export C headers, you can easily generate the bindings out of them with CLangSharpPInvokeGenerator.

https://github.com/dotnet/ClangSharp

I strongly caution against WASM suggestions in a sibling comment - I’m not even sure if the author has actually done any C# at all, given how ridiculous it is.


Awesome, thanks for the link, that’s really useful!

WASM is definitely a strange suggestion here, I didn’t take it seriously. I’m already using a C-compatible zig library approach. Some details of the use case here: https://hackertimes.com/item?id=41729059


What is ridiculous in it?


Maybe I should write that tutorial on how to use C# for low-level.


Heh, I've been procrastinating on making a blog and writing a blog post on "C# for systems programming". Would be nice to read and provide feedback if someone beats me to it.


It will not work if you low-level target is rp2040 microcontroller board...


There was a port of the .NET Nano Framework for RP2040.

But I think the more interesting thing is that if you remove all features in C# that require heap allocations, the resulting subset is basically C with namespaces and generics, which is still useful, and certainly possible to compile efficiently even for very constrained platforms.


Yes, it's technically doable, but what’s the point of using it if you lose almost the entire standard library because it relies on the GC?


There is a practical answer to this question: https://github.com/bflattened/bflat specifically the --stdlib:zero target.

C# is quite a bit more than just enhanced C if you remove GC-reliant features as the generics and interface constraints enable a huge subset of features, alongside SIMD API, stack-allocated buffers and all sorts of memory wrappable in Span<T>s, which almost every method in the standard library that works on some sort of buffer accepts nowadays instead of plain arrays.

You can also manually allocate objects - there are multiple ways to go about it and even with the presence of GC, there is a "hidden" but supported API to register a NonGC heap that GC understands when scanning object references.

Though effective targeting is limited to much fewer count of platforms. Mono can target as low as ARMv6 but CoreCLR/NativeAOT mainly work with x86, x86_64, ARM and ARM64. For microcontrollers you are better off using Rust in my opinion. But for anything bigger .NET can be a surprisingly capable choice.


Yes please do!


It is a general purpose programming language that should be able to do anything you want, whether it works for you depends on what you want to do, the ecosystem might be lacking since it's a young language. Just try it out!




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: