[HN Gopher] Zinc, a systems programming language prototype
___________________________________________________________________
Zinc, a systems programming language prototype
Author : birdculture
Score : 129 points
Date : 2025-03-12 19:35 UTC (1 days ago)
(HTM) web link (sr.ht)
(TXT) w3m dump (sr.ht)
| 38 wrote:
| > No package manager to distract you
|
| What decade am I in? This is not optional any more. Hard pass.
| TimorousBestie wrote:
| One of the non-goals is "to be useful to anyone," after all.
|
| I like this language, it shares my aesthetics.
| philomath_mn wrote:
| It seems like the possible outcomes are:
|
| (a) nobody uses the language, so a package manager doesn't
| matter OR
|
| (b) people use the language, they will want to share
| packages, then a package manager will be bolted on (or many
| will, see python)
|
| Seems like first-class package manager support (a la Rust)
| makes the most sense to me.
| jezze wrote:
| I am on the complete opposite side here. I detest language
| specific package managers for many reasons.
| kreco wrote:
| Definitely a feature to me.
|
| I don't have to be worried that a 3rd party library without
| dependency begins to have 30 transitive dependencies which now
| can conflict with other diamond dependencies.
|
| I need my dependency tree to be small to avoid every single
| factor of friction.
|
| Language specific package manager is exactly what encourage the
| exponential explosion of packages leading to dependency hell
| (and lead to major security concerns).
| imtringued wrote:
| >Language specific package manager is exactly what encourage
| the exponential explosion of packages leading to dependency
| hell (and lead to major security concerns).
|
| Sounds like you're biased.
|
| https://archlinux.org/packages/extra/x86_64/gnome-shell/
|
| gnome-shell > accountsservice > shadow > pam > systemd-libs >
| xz > bash > readline > ncurses > gcc-libs > glibc
|
| and I didn't even try finding the longest chain...
| runevault wrote:
| Package managers are such an odd thing from a social
| perspective.
|
| You'll see cases like NPM and to a lesser degree Cargo where
| projects have hefty dependency graphs because it is so easy to
| just pull in one more dependency, but on the other side you
| have C++ that has conan and vcpkg but the opinions on them are
| so mixed people rely on other methods like cmake fetch package
| instead.
|
| I appreciate having tools that let me pull in what I need when
| I need it, but the dependency explosion is real and I dunno how
| to have one without the other.
| nyanpasu64 wrote:
| If you require end users (and possibly libraries? IDK) to
| manually specify every transitive dependency of a dependency
| (but not hard-code/vendor it), this should act as a forcing
| function to reduce transitive dependency explosion in
| libraries (because it would degrade user experience). I'm not
| sure if users should have to update every dependency by hand
| (this discourages updates which can cause security bugs to
| persist, but automatic updates makes supply-chain attacks
| easier; AUR helpers generally diff PKGBUILDs before
| committing them, which partly protects against PKGBUILD but
| not source attacks, and even _distros_ did not protect
| against the xz attack).
|
| Another factor is that updating C++ compilers/stdlib tends to
| break older libraries; I'm not sure if this is any less the
| case in Rust (unclear? I mostly get trouble with C
| dependencies) or Python (old Numpy does not supply wheels for
| newer Python, and ruamel.yaml has some errors on newer
| Python: https://sourceforge.net/p/ruamel-yaml/tickets/476/).
| runevault wrote:
| To the best of my knowledge (I only dabble in Rust) there
| aren't often too many breaks unless code accidentally
| relied on soundness bugs which Rust makes 0 promise of
| retaining to keep code working.
| rcxdude wrote:
| This is optimizing for the wrong metric, IMO. If I look at
| the dependency tree of a fairly hefty project in rust,
| mostly what I see is the same amount of code as an
| equivalent project in C/C++, just split into multiple
| packages instead of bundled up into one source tree. Which
| ironically means packages tend to be able to pull in the
| minimal amount of excess code through transitive
| dependencies. All that you'll do with this kind of
| incentive is push packages into effectively vendoring their
| dependencies again.
| SkiFire13 wrote:
| This reminds me of this article
| https://wiki.alopex.li/LetsBeRealAboutDependencies
|
| It's incredible how much stuff some C projects vendor
| __MatrixMan__ wrote:
| I'd rather have my languages focus on being a language and use
| something non-language-specific like nix or bazel to situate
| the dependencies.
|
| Sure, the language maintainers will need to provide some kind
| of api which can be called by the more general purpose tool,
| but why not have it be a first class citizen instead of some
| kind of foo2nix adapter maintained by a totally separate group
| of people?
|
| There's no need to have a cozy CLI and a bespoke lockfile
| format and a dedicated package server when I'll be using other
| tools to handle those things in a non-language-specific way
| anyhow.
| fc417fc802 wrote:
| A tool like Nix also makes for an end result that's far more
| auditable than the latest and greatest language specific
| package manager of the day.
| parliament32 wrote:
| Big feature for me. In frontend dev, 3k dependencies in a hello
| world app is considered normal. In systems, a free-for-all
| dependency graph is a terrible plan, especially if it's an open
| ecosystem. NPM, Cargo, etc are good examples.
|
| This is also why systems people will typically push back if you
| ask for non-official repos added to apt sources, etc.
| zifpanachr23 wrote:
| For recreational programming purposes (and sometimes
| professional depending on the domain), they really are a
| distraction.
|
| The existence of a package manager causes a social problem
| within the language community of excessive transitive
| dependencies. It makes it difficult to trust libraries and
| encourages bad habits.
|
| Much like Rust has memory safety benefits as a result of some
| choices that make it difficult to work with in some context,
| lack of a package manager can have benefits that make it
| difficult to work with in certain contexts.
|
| These are all just tradeoffs and I'm glad "no package manager"
| languages are still being created because I personally enjoy
| using them more.
| jezze wrote:
| I think you have something promising there.
|
| I like that everything starts with a keyword, it makes the
| language feel consistant and I assume the parser is simple to
| understand because of it.
|
| I like that you distinguish a procedure from a function in
| regards to side-effects and that you support both mutable and
| immutable types.
|
| I like that you dont have to put a semicolon after each line but
| instead just use newline.
|
| I like that you don't need parenthesis for ifs and whiles,
| however I am not sure I like the while syntax. Maybe I need to
| try it a bit before I can make up my mind.
|
| On the other hand I think the type system could be expanded to
| support more types of different sizes. Especially if you are
| going for a systems programming language you want to be able to
| control that.
|
| I think you could have a nil type because it is handy but it
| would be good if the language somehow made sure that any variable
| that could potentially be nil has to be explicitly checked before
| use.
| lpapez wrote:
| This looks lovely, it's so readable!
| marssaxman wrote:
| I like where you're going with this.
|
| If you haven't looked into Zig's 'comptime' system, you might
| find some relevant inspiration there.
| mamcx wrote:
| You have a lot of questions, so go to
| https://www.reddit.com/r/ProgrammingLanguages/
|
| Some possible answers:
|
| > . Unfortunately I also designed a language with top-level
| execution and nested functions - neither of which I could come up
| with a good compilation model for if I wanted to preserve the
| single-pass, no AST, no IR design of the compiler.
|
| - This is the major PITA of C: Is an actual terrible target for
| transpilers that have _aspirations_ and sophisticated features
| like Strings, some decent type system, or whatever. So, your
| option is to target something that is as close to semantics of
| your language (Basically, any other language that is not C), to
| the point where your target is MORE sophisticated than your own
| lang.
|
| - I think Zig (for speed/apparent simplicity) and Rust could be
| good targets instead of C (I wish Rust were way faster to
| compile!). Assuming Zig, it will simplify other aspects like
| cross compiling
|
| - I don't think is totally possible to avoid have a semi-
| interpreter for the transpiler, where you at most need a
| _prelude_ with some hand-crafted functions that do the lifting.
| With this I mean things like `fn int(I:Int):Int '` so your code
| output is like `plus(int(1), int(2))`. Langs like APL/J use this
| for great effects and basically side-step the need for a
| vm/opcode. (see also: Compiling with closures)
| artemonster wrote:
| this subreddit suffers from insufferable admins that purged any
| useful activity and sense of community from this sub
| Alupis wrote:
| Nearly all of reddit is presently political spam, and bot
| spam - often political bot spam. Every subreddit has to some
| degree been infiltrated by political spam - even subs that
| have absolutely nothing to do with politics.
|
| It's really unfortunate... reddit used to make me laugh - now
| it just makes me angry.
| DaiPlusPlus wrote:
| > Nearly all of reddit is presently political spam
|
| The good (or at least barely tolerable) sane politics/econ
| subs hide in plain sight. (Also, enn cee dee?)
| jbreckmckye wrote:
| How do you mean?
| alcover wrote:
| > where your target is MORE sophisticated than your own lang.
|
| I.. hadn't thought of this. I mean I wouldn't transpile to a
| slow lang like python but choosing Zig or C++ is tempting. Zig
| maybe not as it's unfinished. But C++ instead of C would make
| my life easier (for ex. implementing classes).
|
| > prelude with some hand-crafted functions that do the lifting.
| With this I mean things like `fn int(I:Int):Int'` so your code
| output is like `plus(int(1), int(2))`
|
| Curious what you mean here. Is it `1+2` -> ast Binop{'+', left,
| right} -> gen `plus(1,2)` ?? Sorry it's late here and I should
| sleep..
| travisgriggs wrote:
| > Zig maybe not as it's unfinished
|
| But, but, but...
|
| They share the same two start letters! They were clearly
| meant to cohabitate!
|
| Zinc on Zig, what a Zing!
|
| (Just a casual at-a-distance zig fan)
| unquietwiki wrote:
| Nim might be useful, either as a compiler or transpiler.
|
| https://hookrace.net/blog/introduction-to-metaprogramming-
| in...
|
| https://livebook.manning.com/book/nim-in-action/chapter-9/
| mamcx wrote:
| > Curious what you mean here. Is it `1+2` -> ast Binop{'+',
| left, right} -> gen `plus(1,2)` ?? Sorry it's late here and I
| should sleep..
|
| Yes, `plus(1,2)`. The problem will become more apparent when
| you find things like `plus` need some overloading
| support/macros/generics/etc, so thing like `print` too.
|
| So, eventually you need to think in macros, multiple versions
| of the same thing, or, if you craft things very carefully,
| only support things your target support so you can avoid it
| (but I wonder how much is feasible)
| rerdavies wrote:
| I've been down this path. Code generation is great; but the
| downside to this approach is that making the language debug-
| able is pretty much impossible. (An MPEG-SA structured audio
| compiler with a C++ back end).
| wk_end wrote:
| Since you need to use a `call` statement to invoke a function, is
| it possible to invoke a function inside of a function call? I.e.
| can you write `call f(g(x))` or `call f(call g(x))` or something
| like that?
| AlotOfReading wrote:
| One of the issues with systems programming languages is that the
| definitions programmers use for "well-understood" terms vary
| wildly in actual practice.
|
| For example, the term "side effects" has half a dozen different
| meanings in common use. A Haskell programmer wouldn't consider
| memory allocation to be a side effect. A realtime programmer
| might consider taking too long might be a side effect, hence
| tools like realtime sanitizer [0]. Cryptography developers often
| consider input-dependent timing variance a critical side effect
| [1]. Embedded developers often consider things like high stack
| usage to be a meaningful side-effect.
|
| This isn't to say that a systems language needs to support all of
| these different definitions, just a suggestion that any systems
| language should be extremely clear about the use cases it's
| intending to enable and the definitions it uses.
|
| [0] https://clang.llvm.org/docs/RealtimeSanitizer.html
|
| [1] https://www.bearssl.org/constanttime.html
| DeathArrow wrote:
| >One of the issues with systems programming languages is that
| the definitions programmers use for "well-understood" terms
| vary wildly in actual practice.
|
| I think he used side effect with a functional programming
| meaning. A pure function will just take immutable data and
| produce other immutable data without affecting state. A
| function which adds 1 to a number has no side effects, while a
| function that adds 1 to a number and prints to the console has
| side effects.
| Someone wrote:
| > A pure function will just take immutable data and produce
| other immutable data without affecting state
|
| But _state_ is open for interpretation. If I write (making up
| syntax, attempting to be language-agnostic)
| fnc foo uses scalar i produces scalar does
| return make scalar(i + 1) end fnc
|
| One could argue that is not pure, and one would have to write
| fnc foo takes heap h, uses scalar i produces heap, integer
| does (newHeap, result) := heap.makeScalar(i + 1)
| return (newHeap, result) end fnc
|
| That expresses the notion that this function destroys a heap
| and returns a new heap that stores an additional scalar (an
| implementation likely would optimize that to modify the heap
| that got passed in, but, to some, that's an implementation
| detail)
|
| > while a function that adds 1 to a number and prints to the
| console has side effects.
|
| Again, that's open for interpretation. If the program cannot
| read what's on the console, why would that be considered a
| side effect? That function also heats my apartment and
| contributes my electricity bill.
|
| Basic thing is: different programmers care about different
| things. Embedded programmers may care about minute details
| such as the number of cycles a function takes.
| jerf wrote:
| I'd also emphasize the point here is that if a systems-
| level programming language is going to call itself pure, it
| just needs a really, really careful definition of what
| exactly it means by _pure_. Purity is intrinsically
| relative [1]. That doesn 't make it a bad goal, or a bad
| thing, and there's definitely a significant difference
| between a language striving for any meaning of "purity"
| versus one that doesn't care at all, but whatever
| definition the language designer is using should be very
| carefully defined. Particularly for a systems language, if
| by "systems language" one means "the sort of language that
| allows poking at low level details", because having lots of
| "low level" access greatly expands the scope of "things my
| code may be able to witness the stack for".
|
| To give a degenerate-but-simple example of that, a low-
| level systems language striving for "purity" but that also
| allowed arbitrary memory reading for whatever reason ("deep
| low-level custom stack trace functionality") would
| technically be able to witness the effects of the stack
| changing due to function calls. You can just define that
| away as an effect (and honestly would probably have to),
| but I'd suggest being clear about it.
|
| A denegenerate-but-often-relevant example is that a "pure"
| function in a language that considers memory allocation
| "pure" can crash the entire OS process by running it out of
| memory. That's so impure that not only can the execution
| context (thread, async context, whatever) that is running
| the program out of memory witness it, so can every other
| execution context in the process, indeed, whether they want
| to or not they have to! We generally consider memory
| allocation "pure" for pragmatic reasons, because we really
| have no choice, the alternative is to create such a
| restrictive definition of "pure" as to be effectively
| useless, but that is almost the largest possible "effect"
| we're glossing over!
|
| [1]:
| https://jerf.org/iri/post/2025/fp_lessons_purity/#purity-
| is-...
| dontlaugh wrote:
| I've never seen anyone actually refer to time variance for
| either realtime or crypto as "side effects".
|
| It's true that these are all somewhat related concepts, but I'm
| pretty sure the term "side effect" is consistently used in the
| functional sense.
| SkiFire13 wrote:
| The "functional sense" is the one that's underspecified for
| system programming. For example it considers allocation a
| pure operation, but that's actually implemented by modifying
| a global variable so how is it pure? One might argue that
| it's not observable, but so is printing to the console, which
| is usually taken as an example of an impure operation.
| badmintonbaseba wrote:
| Even if you limit "side effects" to observable behavior in the
| abstract machine sense, it's not entirely clear what is meant
| by a function to be "pure".
|
| GCC has two attributes for marking functions, "pure" and
| "const" (not the language const qualifier). C23 introduced the
| [[reproducible]] and [[unsequenced]] attributes, that are
| mostly modeled by the GCC extensions, but with some subtle but
| important differences in their description.
|
| Turns out it's pretty hard to define these concepts if the
| language is not built around immutability and pure functions
| from the ground up.
| titzer wrote:
| As someone who has worked on a systems programming language for a
| long time, my strongest advice would be to avoid trying to make
| syntactic or semantic choices that are just _different_ unless
| they 're really motivated by making the systems aspect better, or
| to make the language more self-coherent. Having surprises and
| syntax to learn is a barrier to entry and probably won't impress
| anyone.
|
| That is to say, do focus on _systems problems_. Key ones I
| identified are efficient data representation, avoiding needless
| memory churn /bloat, and talking directly to lower-level
| software/hardware, like the kernel.
|
| Focus on systems programming and not on syntactic niceties or
| oddities.
| maxov wrote:
| Yes, I also found the description a little weird because of the
| emphasis on linear-time parsing. It is cool theoretically, and
| it could be understandable from a perspective of "make the
| compiler fast", but parsing is never the bottleneck in modern
| compilers. For a systems programming language this seems to be
| the wrong emphasis.
| muth02446 wrote:
| While working on my systems PL, Cwerg, I adopted a "syntax
| last" approach:
|
| For the longest time the syntax was just glorified s-exprs.
| This made it much easier to focus on the semantic choices and
| improved iteration times and willingness to experiment since
| the parser changes were always trivial.
|
| I highly recommend this approach for new PLs.
| dontlaugh wrote:
| The danger is you might decide to just keep the s-exprs.
| muth02446 wrote:
| I almost did ;-)
|
| I added a few improvements to help with legibility which
| made it bearable to program with sexpr.
|
| But arithmetic expressions and (chaining of) unary
| operators was just too painful, e.g.
|
| (= (. (^ ptr) file) ...)
|
| instead of
|
| ptr^.field = ...
| titzer wrote:
| Interesting.
|
| For Virgil, I started with mostly Java/C syntax, but with
| "variable: type" instead of "type variable", because it was
| both easier to parse and was more like standard ML and what
| you encounter in programming language theory. That syntax was
| already catching on, so I felt like I was swimming with the
| stream. I initially made silly changes like array indexing
| being "array(index)" instead of "array[index]", which turned
| out to be annoying to just take random code and change all
| the "[" to "(" and "]" to ")". Also, I had keywords "method"
| and "field", but eventually decided things looked better as
| "def" and "var", because they were easier to eyeball and
| readily understandable to people who write JavaScript (and
| Scala, as it turns out).
|
| Overall Virgil's syntax is a kind of an average of all the
| curly braced languages and where it differs at all, it's been
| to make things more composable and avoid cryptic line-noise-
| looking things. For example, to allocate an object of class
| C, one writes "C.new(args)", because that can be understood
| as "C.new" as a function applied to "(args)"--so one can
| easily write "C.new" and yes, indeed, that's a first class
| function. That works with delegates and so on. So I don't
| regret not exactly matching the "new C()" you'd find in Java
| or C++.
| muth02446 wrote:
| This reminded me of two other recommendations:
|
| 1) write a pretty printer early on (I had one for the
| s-expr based syntax and one for the concrete syntax I
| introduced later) This will allow you to automatically
| apply the syntax changes on the example code you have
| written in your PL with only very little programming
|
| 2) instead of parser generators use recursive descent +
| Pratt parsing Pratt parsing is a little bit magical at
| first but it is easy to develop a working intuition without
| understanding all the details of the algorithm.
| higherhalf wrote:
| What makes this a "systems programming language", especially
| since it has "no pointers or references"?
| fc417fc802 wrote:
| Indeed, that makes it not a systems language by any definition
| I am familiar with.
|
| > Reasonable C interop, and probably, initial compilation to C.
|
| How do you achieve "reasonable C interop" without pointers, I
| wonder?
| apgwoz wrote:
| You cast integers to pointers and play with fire, of course!
| fc417fc802 wrote:
| Void*? Int. Char**? Also an Int. I take it back. This is
| true systems programming - the same type safety that raw
| assembly is known for.
| pjmlp wrote:
| Ironically Assembly is safer than C and languages that
| descend from it, because although CPUs might have
| undefined behaviour when given undocumented opcodes, or
| operation modes, the CPU doesn't rewrite your code
| without telling you about it.
| AnimalMuppet wrote:
| That's "safer" only against a very specific and limited
| set of dangers. But it opens the door to other dangers.
| fithisux wrote:
| Yes it is. Great comment.
| pjmlp wrote:
| Naturally with PEEK and POKE.
| porridgeraisin wrote:
| int ptr
| GoblinSlayer wrote:
| The term was introduced so long ago, it's basically prehistoric
| now. Pointers are needed only for system programming language,
| they can be absent in systems programming language.
| DeathArrow wrote:
| I wonder the same, but aren't pointers just integers?
|
| So if you store a memory address in the integer variable X, you
| just need a way to access that memory.
|
| In assembly languages, usually, you have no pointers.
| tialaramex wrote:
| Interestingly although all of C's _other_ types are in fact
| just the machine integers wearing funny hats (e.g. char is
| just either a signed or unsigned byte depending on platform,
| float is just the 32-bit unsigned integers as binary
| fractions) the pointers are not actually just integers.
|
| They could be, but it's much worse from a performance
| perspective if you just have these raw machine addresses
| rather than the pointers in the C language so actual C
| compilers haven't done that for many years. ISO/IEC TS 6010
| describes the best current attempt to come up with coherent
| semantics for these pointers, or here's a Rustier perspective
| https://www.ralfj.de/blog/2020/12/14/provenance.html [today
| Rust specifically says its pointers have provenance and what
| that means, like that TS for the C language]
|
| Now, if you read Ralf's post and want to argue about _that_ I
| 'm afraid there are already lots of HN discussions and your
| point has probably already been made so:
| https://news.ycombinator.com/item?id=25419740 or
| https://news.ycombinator.com/item?id=42878450
| SkiFire13 wrote:
| > float is just the 32-bit unsigned integers as binary
| fractions
|
| Note that float and double are a bit particular because
| they can use different registers! But yeah, when stored in
| memory they are the same 32/63 bit integers.
| pjmlp wrote:
| Like we did in BASIC, with PEEK and POKE, just have to keep
| track what those numbers are for.
| keyle wrote:
| TIL. I learnt about the owl parser generator. Looks decent.
| Anyone's experience?
| boguscoder wrote:
| Is it called Zinc because zinc doesn't easily corrode ;)?
| DeathArrow wrote:
| I wish someone is inventing a systems programming language with a
| bit of safety but without a borrow checker. Is it even possible?
| Of course, having a garbage collector wouldn't qualify.
| slekker wrote:
| I think thats Zig in the future - there's already allocators
| you can use that will detect some memory safety crimes
| DeathArrow wrote:
| Sounds great!
| SkiFire13 wrote:
| C/C++ also have various sanitizers but they are generally not
| used in production. Is Zig's allocator usable in production
| or only while developing?
| imtringued wrote:
| Already exists: https://verdagon.dev/blog/generational-
| references
| Joker_vD wrote:
| > The language splits side-effects from non-side-effecting code.
| Or rather would once functions and subroutines are implemented.
| Subroutines can have side-effects, functions cannot. Expressions
| can only apply functions, not call subroutines. It's like Haskell
| but better.
|
| You mean, "worse". There is a reason why e.g. Pascal only had
| this misfeature in its very first version and gave up on it in
| the Revised Report, at which point having both functions and
| procedures arguably became an unnecessary distinction without
| difference.
|
| > And there's always the issue of what to do about side-effects
| on module load.
|
| You execute them. Just be sure to only run them once, and
| maintain proper traversal order (that being post-order): e.g. if
| your main program has "import A; import B", and A has "import B,
| import C", and B has "import D", you first run D's init, then
| B's, then C's, then main's.
| duped wrote:
| There's no meaningful order to shared dependencies or cyclic
| dependencies. You can pick one, but making it undefined is a
| lot more useful as the language implementer.
|
| As a language user, don't rely on order for your side effects.
| Actually, just don't have side effects on module load. You
| almost never need it. Lazily initialize your globals.
| Joker_vD wrote:
| > There's no meaningful order to shared dependencies or
| cyclic dependencies.
|
| Textual order. At least it's visible.
|
| > Lazily initialize your globals.
|
| What does that even mean? Something like that:
| size_t _fwrite__impl(const void* buffer, size_t size, size_t
| count, FILE* stream) { if (!__crt0_initialized) {
| _crt0(); } if (!__crt1_initialized) {
| _crt1(); } if (!__xfloat_initialized)
| { _xfloat(); } if
| (__stdio_initialized) { _init_stdio();
| } // Actual implementation that touches internal
| FILE-tables and maybe does float/double formatting. }
|
| ? But why?
|
| > Actually, just don't have side effects on module load. You
| almost never need it.
|
| See above. There is a surprising amount of invisibly
| initialized global state in e.g. C runtime library.
| duped wrote:
| > Textual order. At least it's visible.
|
| Is "textual order" breadth-first, depth-first, reverse
| breadth-first, or reverse depth-first? Whichever you pick
| there will be a case where some module can't initialize
| because of assumptions it makes about how other modules are
| initialized. And like I said, it totally breaks down for
| cyclical dependencies - which are so common in practice,
| you must consider it.
|
| > ? But why?
|
| To paraphrase what Rust does, "no life before main." The
| point is to force expressions to be evaluated as they're
| used instead of as they're declared. There's an additional
| benefit that global resources that are not used are not
| initialized, which in the cases above has global side
| effects.
|
| The glibc runtime is not something to be held up as a model
| for something particularly well designed. You can get all
| the benefits of hidden global initialization via laziness
| without all the problems placed on the programmer to care
| about their import declaration order, or undefined cases
| like cyclical imports.
|
| One place where this stuff really sucks is when using
| dynamic linking and shared libraries have constructor
| functions that modify global state. GCC had to rollback
| changes to --ffast-math a couple years ago because loading
| two libraries compiled with different flags could result in
| undefined behavior when the MXCSR register depended on the
| order of library initialization.
| Joker_vD wrote:
| Textual order is depth-first. When you encounter "import
| X", you switch to (recursively) import/load module X. I
| believe that's how Python works.
|
| As for the cyclical dependencies I'd argue they should be
| disallowed. Either their initialization order doesn't
| actually matter -- in which case it doesn't matter :) --
| or there is a way to break things into smaller pieces and
| reorder them to function properly -- in which case it's
| what should be done -- or there is no valid ordering at
| all, in which case it's a genuine bug which has been made
| possible only because cyclical dependencies were allowed.
|
| > There's an additional benefit that global resources
| that are not used are not initialized
|
| This, arguably, can be considered a downside. Consider
| the security implications (and introduced mitigations) of
| e.g. writeable GOT/PLT. But it's a design decision with
| both of the choices valid, just with different trade-
| offs.
|
| > You can get all the benefits of hidden global
| initialization via laziness without all the problems
| placed on the programmer to care about their import
| declaration order
|
| I'd be interested to read about _that_. To me, this
| sounds mostly the problem of not accurately specifying
| your actual dependencies.
| Cerium wrote:
| It's called zinc because you are avoiding rust?
| vram22 wrote:
| I wonder if there are PLs named after metals, or even other
| elements of the periodic table, other than Zinc, Carbon and
| Mercury? :)
| SkiFire13 wrote:
| Not a metal/element but there's Ruby
| moomin wrote:
| Is it just me or is this sounding quite like BCPL?
| fithisux wrote:
| Why not create an improved HLA - MASM?
|
| What You See is What Is Executed
|
| easy back and forth to assembly + inline assembly.
___________________________________________________________________
(page generated 2025-03-13 23:02 UTC)