Metamath Zero, a bootstrapping theorem prover - <AUTHOR> https://arxiv.org/abs/1910.10703 <comment><USER2> This is really interesting work.

I like this quote: "sometimes, performance is about more than just getting work done a little faster. When something takes a lot less time, it changes the way you interact with the computer. A process that takes hours goes on the nightly build server; a process that takes minutes might be a compile that runs on your local machine; a process that takes seconds is a progress bar; and a process that takes milliseconds might happen in an editor between keystrokes."

Most verification systems work in terms of hours or days. Changing the order of magnitude means that verification can happen constantly.

The paper mentions that it verifies Metamath set.mm, one of the largest bodies of formalized mathematics, in less than 1 second. Here's some more info for the curious:

* My Gource visualization of the development of set.mm over time: [https://www.youtube.com/watch?v=XC1g8FmFcUU](https://www.youtube.com/watch?v=XC1g8FmFcUU)

* My video "Metamath Proof Explorer: A Modern Principia Mathematica" (which gives overall background/context of Metamath): [https://www.youtube.com/watch?v=8WH4Rd4UKGE](https://www.youtube.com/watch?v=8WH4Rd4UKGE)

* Metamath Proof Explorer (MPE) aka "set.mm" \- the home page for this body of formalized mathematics: [http://us.metamath.org/mpeuni/mmset.html](http://us.metamath.org/mpeuni/mmset.html)

<comment><USER3> > Most verification systems work in terms of hours or days.

What kind of verification does usually take hours? Just checked how long it takes to verify Raft using Coq and Verdi (pretty sizeable proof), and complete pipeline takes around 25 minutes (with Docker container creation, fetching dependencies, and what not). Verification of proof terms is a relatively easy task for a computer, as easy as type checking. Coming up with the proofs, on the other hand, that is hard.

<comment><USER2> The 25 minute value is only the time to verify a single Coq proof. I'm measuring the time to verify ALL proofs of an entire system.

The Metamath Rust verifier normally verifies 23,000+ proofs at a time. The actual verification time is just less than 1 second for the entire set. When you include the time for container creation, fetching dependencies, and so on, it typically takes ~48 seconds for it to verify the entirety of set.mm (which includes _thousands_ of proofs). Here's an example: [https://travis- ci.org/metamath/set.mm/builds/602369640](https://travis- ci.org/metamath/set.mm/builds/602369640)

You could run 23,000 Coq jobs in parallel. I wouldn't want to pay for it :-). And it would complete verification of all the proofs in 25 minutes, vs. the 200msec of Metamath Zero or the ~1 second of the Metamath Rust implementation.

That's not to say that Coq is a terrible system. Coq is really interesting! But verification time is not something it's prioritized.

<comment><USER3> > The 25 minute value is only the time to verify a single Coq proof.

Logically it is a singe proof, but technically it consists of quite a few theorems and lemmas, so this is not a valid comparison. Also proofs in Coq are typically structured and pretty high-level because of all the automation, while metamath proofs look like core dumps :)

      ${
        $d A a b v w x y $.  $d B a b v w x y $.  $d F a b v w x y $.
        $( The ` 2nd ` (second member of an ordered pair) function restricted to a
           one-to-one function ` F ` is a one-to-one function of ` F ` onto the
           range of ` F ` .  (Contributed by Alexander van der Vekens,
           4-Feb-2018.) $)
        f1o2ndf1 $p |- ( F : A -1-1-> B -> ( 2nd |` F ) : F -1-1-onto-> ran F ) $=
          ( vx vy va vv vb vw c2nd syl cv cfv wceq wi wcel wa wrex ex com23 wf1 crn
          cres wfo ccnv wfun wf1o f1f fo2ndf weq wral f2ndf cxp wss fssxp cop ssel2
          elxp2 sylib anim12dan fvres adantr ad2antlr eqeq12d op2nd eqeq12i funopfv
          wf vex f1fun anim12d eqcom biimpi eqeqan12d simpl anim12i f1veqaeq sylan2
          opeq12 syl6 com14 syl6bi pm2.43i syld impcom syl5bi sylbid adantl adantlr
          com13 com12 wb eleq1 bi2anan9 anbi2d fveq2 simpllr imbi12d imbi2d 3imtr4d
          simpr rexlimdvva rexlimivv imp mpcom ralrimivv dff13 df-f1 simprbi dff1o3
          sylanbrc ) ABCUAZCCUBZJCUCZUDZXNUEUFZCXMXNUGXLABCVHZXOABCUHZABCUIKXLCBXNU
          AZXPXLCBXNVHZDLZXNMZELZXNMZNZDEUJZOZECUKDCUKXSXLXQXTXRABCULKXLYGDECCCABUM
          ZUNZXLYACPZYCCPZQZYGOXLXQYIXRABCUOKYIYLXLYGYIYLXLYGOZYAFLZGLZUPZNZGBRFARZ
          YCHLZILZUPZNZIBRHARZQYIYLQZYMYIYJYRYKUUCYIYJQYAYHPYRCYHYAUQFGYAABURUSYIYK
          QYCYHPUUCCYHYCUQHIYCABURUSUTYRUUCUUDYMOZYQUUCUUEOZFGABYNAPZYOBPZQZYQUUFUU
          IYQQZUUBUUEHIABUUJYSAPZYTBPZQZQZUUBUUEUUNUUBQZYIYPCPZUUACPZQZQZXLYPXNMZUU
          AXNMZNZYPUUANZOZOZUUDYMUUNUUSUVEOZUUBUUIUUMUVFYQUUSUUIUUMQZUVEUURUVGUVEOY
          IUURUVGUVEUURUVGQZUVBXLUVCUVHUVBYPJMZUUAJMZNZXLUVCOZUVHUUTUVIUVAUVJUURUUT
          UVINZUVGUUPUVMUUQYPCJVAVBVBUUQUVAUVJNUUPUVGUUACJVAVCVDUVKGIUJZUVHUVLUVIYO
          UVJYTYNYOFVIGVIVEYSYTHVIIVIVEVFUVHXLUVNUVCUVGUURXLUVNUVCOZOXLUURUVGUVOXLU
          URYNCMZYONZYSCMZYTNZQZUVGUVOOXLCUFZUURUVTOABCVJUWAUUPUVQUUQUVSYNYOCVGYSYT
          CVGVKKXLUVGUVTUVOUVNUVGUVTXLUVCUVNUVGUVTUVLOOUVTUVNUVGUVNUVLUVTUVNUVPUVRN
          ZUVGUVNUVLOOUVQUVSYOUVPYTUVRUVQYOUVPNUVPYOVLVMUVSYTUVRNUVRYTVLVMVNXLUVGUV
          NUWBUVCXLUVGUVNUWBUVCOOXLUVGQZUWBUVNUVCUWCUWBFHUJZUVOUVGXLUUGUUKQUWBUWDOU
          UIUUGUUMUUKUUGUUHVOUUKUULVOVPABYNYSCVQVRUWDUVNUVCYNYOYSYTVSSVTTSWAWBWAWCW
          ATWDWJWETWFWGTSWHWKWIVBUUOYLUURYIUUNYJUUPUUBYKUUQYQYJUUPWLUUIUUMYAYPCWMVC
          YCUUACWMWNWOUUOYGUVDXLUUOYEUVBYFUVCUUNUUBYBUUTYDUVAYQYBUUTNUUIUUMYAYPXNWP
          VCYCUUAXNWPVNUUOYAYPYCUUAUUIYQUUMUUBWQUUNUUBXAVDWRWSWTSXBSXCXDXESTXEXFDEC
          BXNXGXKXSXTXPCBXNXHXIKCXMXNXJXK $.
      $}

...

<comment><USER4> It goes without saying that metamath is not designed to be read from the source directly. To be perfectly fair, Coq isn't either; you can kind of get the gist but to really understand what's going on you have to start up Coq and look at proof states. Metamath as it's meant to be seen looks like this: [http://metamath.tirix.org/f1o2ndf1.html](http://metamath.tirix.org/f1o2ndf1.html) .

I agree that calling it "one proof" is a mischaracterization, but comparing all of Raft to all of set.mm is probably about right. I would guess set.mm is 10-100 times larger than Raft in terms of number and complexity of actual proof content, but it checks in a fraction of the time, in part because of that "core dump". You might think it ugly, but have you ever looked at a .vo file? The difference is metamath checks its 'cache' in to version control.

<comment><USER3> > The difference is metamath checks its 'cache' in to version control.

As I said in the initial post, there is an entire world of difference between checking the proof term and, well, proving. Coq can dump proof terms that can also be verified relatively quickly, but typically people prefer to run proof scripts in CI. And proof scripts actually search for the proof, rather than simply describe it. So, travis run time is not a terribly precise metric.

As for comparing the number of lemmas... In Coq one has "magical" tactics such as `omega' or `lattice'. Metamath doesn't have tactics (?), so I presume that's the reason they need so many lemmas in standard library; just like you need 100x time more code in asm than in Haskell.

<comment><USER4> Metamath has tactics, but they aren't part of metamath per se; they are part of the tools that you use to write proofs. You don't make the rest of the world run the same proof search you did hundreds of times, finding the same proof every time, when you could just write down the proof.

I'm aware this is an entirely unfair comparison. Coq and Metamath aren't doing anywhere near the same amount of stuff, so _of course_ Metamath will be faster. But the question is: are you doing what is _necessary_? Is running omega all the time a requirement for large scale proof checking, or is it just the way Coq does things? I think you will find that it's not necessary in the abstract, but it's also pretty hard to write Coq any other way. (To be absolutely clear, I don't mean don't use omega, I mean use omega _once_ and generate a proof, and don't make the rest of the world have to re-run your proof script.)

The sizes of things are actually hard to gauge in Metamath if you want to compare LOC to amount of human work, because what you see in a Metamath file are actually the output of some honest to goodness "tactic" or high level user interface. No one is writing asm here.

If you are not writing lemmas, and are relying on Coq tactics to rediscover the proof all the time, well, that's just demonstrably slow and redundant. In Metamath we use a combination of tactics to find proofs and optimizers to extract common lemmas and use the library of existing lemmas effectively; the Coq model leaves no space for the optimizer, so you get something... suboptimal.

</comment></comment></comment></comment></comment></comment></comment><comment><USER5> The author, Mario Carniero, is both one of the top three smartest and nicest people I know (and many other Ohio State students where he did his undergrad would agree). Glad to see his research getting Hacker News recognition.

<comment><USER6> I went to high school with Logan and with Mario. Mario was in my AP Comp Sci class with Mrs. White. I remember being proud of my forays into encryption, concurrency, and network programming.

And then I looked over and Mario had implemented a graphing calculator (as in, take "y = x^2 + 4x -10" and emit a graph) in the windows command prompt. Then, when that was boring, he started researching and implementing the graphics algorithms for drawing lines at various slopes with minimal distortion. And then, when that was boring, he made his graphing calculator support polar coordinates (something I understood only as "oops, my graphing calculator is misconfigured").

Also, he was ~12 years old (IIRC) having skipped a few grades.

I've met a lot of smart people between Carnegie Mellon, Facebook Infrastructure, and the Linux Kernel community, but Mario's one of two or maybe three at the absolute top in terms of intellectual horsepower.

</comment></comment><comment><USER4> For those who are more into watching talks on YouTube than reading papers, and are interested in the low level hardware formalization aspect of this project, there is a recording of the ITP 2019 presentation here: "x86 verification from scratch" [https://www.youtube.com/watch?v=7hAShC6K_vA](https://www.youtube.com/watch?v=7hAShC6K_vA)

</comment><comment><USER7> I recently learned about some limitations in both Coq and Lean theorem prover after watching the video by Kevin Buzzard on formalization of math in Lean. He did some claims about quotient support in Coq, so I just asked[1] Coq developers straightly. I recommend to read their discussion and explanations.

[1] [https://github.com/coq/coq/issues/10871](https://github.com/coq/coq/issues/10871)

</comment><comment><USER8> This is very cool work, and I'm happy to see it. I've been fascinated with Metamath for a very long time, finding its simplicity extremely appealing, and have also made a number of attempts (under the Ghilbert name) to fix the problems Mario so eloquently identifies. But I never quite got it to gel. It's clear Mario has the technical chops, and I hope this publication gets the MM family a little more academic respectability and notice.

</comment><comment><USER9> For those who don't know much about computer-verified proofs, the way I'd sum it up is that there's a complexity crisis going on (similar to the "software crisis" which might not be completely solved but which has seen significant progress). And that Metamath Zero is one of the more promising projects out there aimed at this problem.

<comment><USER10> Would you mind elaborating? I'd love to hear more.

<comment><USER4> Software gets more complicated, and so bugs become more common. Hardware gets faster, so speed pressures are reduced on software, so it gets more layered and hence slower; and also more complicated. More layers of abstraction means more things to get wrong, so correctness becomes a serious problem. The world is increasingly reliant on software, so correctness becomes a serious concern.

That sums up the "software crisis" as it relates to correctness. Most theorem provers have been swept up in this. They are written in high level languages and frameworks made by people who paid no thought to verification and only slightly more than most to correctness. What's more, _even some theorem prover languages_ have dubious correctness or semantics; Rust and Dafny are both languages that make a big deal about formal correctness but have no formal spec. (Rust is working on it.) Coq is not known to be consistent (the literature is full of "here is a proof that some subsystem of Coq has this and that property" but no one can handle the whole thing), not to mention that it has had a few soundness bugs in its history, one of which (Reals violate EM) wasn't even clearly a bug because no one knew what the model was supposed to be.

Agda is a free for all as far as I can tell, and Isabelle has some strange thing with axiomatic typeclasses that takes them out of the HOL world. HOL Light is pretty decent metatheory-wise, and the logic at least was formalized inside itself, but the implementation has not, and OCaml's Obj.magic is still there, ready to cause inconsistency if you feel like using it.

Lean has not had any soundness bugs to date, and the theory is well understood, but it is a massive C++ application and there are doubtless dozens of implementation bugs in there waiting to be found.

None of the big theorem provers are really appropriate for trying to prove correct, because either it is not known what this even means or it's trivially false and we all try to pretend otherwise, or it's an intractable open question.

These are the paragons of correctness in our world.

Can we do better? What does it even mean to do better? This paper aims to find out.

<comment><USER11> Do we even know if it's _possible_ to prove correctness of a theorem-prover, in a very general sense? At some point, that would imply that some theorem- prover would have to prove its own correctness (either by proving itself directly or by proving itself through a loop of theorem-provers). This seems intuitively like it start to run up against Gödel-style incompleteness problems.

<comment><USER4> It does, but only if you state the theorem in a particular way. Let's say that you have a verifier A, that checks theorems in Peano Arithmetic (PA). Inside that logic, you can define what a computer is, how it executes, what PA is, what a verifier is, and what it means for a program to verify theorems of PA. Then you can have a sequence of bytes (verifier B), and prove that they represent a program that verifies theorems of PA.

What have you proven? Well, verifier A (using PA) proves that "verifier B proves theorems of PA". That means that "if B says phi is true, PA |- phi". We would have a hard time actually running verifier B inside the logic of verifier A (that entails running all the steps of the computation B does as theorem applications inside verifier A), but even if we did, we would obtain a proof of "PA |- phi". If we assume A correctly implements PA, then that means PA |- "PA |- phi". In general, this is the best we can do. If we assume further that PA is a sound axiom system, i.e. when it proves facts about numbers then we won't find concrete counterexamples, then this strengthens to PA |- phi and then to phi itself, so we've learned that phi is true.

The plan is to prove inside verifier A (that is, MM0) the statement "Here is a sequence of bytes. It is an executable that when executed has the property that if it succeeds on input "T |- phi", then T |- phi." The bootstrapping part is that the sequence of bytes in question is in fact the code of verifier A. In order to support statements of the form "here is a sequence of bytes", the verifier also has the ability to output bytes as part of its operation (it's not just a yes/no oracle), and assert facts about the encoding of those bytes in the logic.

</comment></comment></comment></comment></comment><comment><USER2> If you're interested in the main book on Metamath, it is "Metamath: A Computer Language for Mathematical Proofs" by Norman Megill & David A. Wheeler. You can get the hardcover here: [http://www.lulu.com/shop/norman-megill-and-david-a- wheeler/m...](http://www.lulu.com/shop/norman-megill-and-david-a- wheeler/metamath-a-computer-language-for-mathematical- proofs/hardcover/product-24129769.html)

Full disclosure: I'm one of the co-authors.

</comment><comment><USER2> FYI, the current publicly-available code for Metamath Zero is here: [https://github.com/digama0/mm0](https://github.com/digama0/mm0)

</comment><comment><USER12> There is something about the process of getting optimal performance in a system that tells you whether you are moving in the right direction.

The universe speaks to you directly, in the count of cycles consumed, albeit somewhat garbled by incidentals of the CPU implementation and, particularly, caching. But the implementers of the CPU are chasing correctness and optimal performance too, so are always working toward the same goal, at their level. Even the caching, when you get down to counting cycles, reveals truths about your computation.

So, a proof system that is several orders of magnitude faster than another is that much closer to ultimate truth, because there is simply less room for significant errors of comprehension to hide in.

This is the reason that efficient languages and runtime systems are, and will always be, important. Garbage collection is an evil because it muddies the water, corrupting the connection between what your program says and what actually happens in the machine.

</comment><comment><USER13> It seems that metamath's representation is a basic _primitive_ for encoding maths at a syntactic level. It uses simple rules to recursively apply syntactical substitution transformations in order to build up a kind of complete, ostensibly true _statement_. A statement that is encoded in a way that a small proven-true statement checker can ~linearly (!) follow along the statement of the proof and find it logically sound. It seems weird to me that it's even possible to cross the boundary from syntactic representation to semantic meaning so seamlessly.</comment>


A Nix terminology primer by a newcomer - <AUTHOR> https://stephank.nl/p/2020-06-01-a-nix-primer-by-a-newcomer.html <comment><USER2> I'm a longtime Ubuntu user and recently gave NixOS a try as most of our team use it. I have to admit I was highly skeptical as it all looks very complicated. The learning curve was a bit steep due to the documentation and odd terminology. But after you get going it solves so many problems. The fact you can declare you're entire desired set up in a single configuration.nix then "nixos-rebuild switch" and you're done saves so much time.

<comment><USER3> I tried to fully switch my work environment to NixOS 2 or 3 years ago. I really like the concept and I think it's a very good approach to reproducible build environments, in theory it's much cleaner than the massive data replication you get with e.g. Docker.

I only lasted for a month or two though, for a couple of reasons. The main one was that I had a lot of trouble with Python packages - Nix suggests a certain approach for dealing with them which didn't work very well for me and I didn't manage to set up an alternative that I liked. (For Haskell I loved working with Nix though!) A lot of software I use also wasn't available in the repositories and I tried to build some packages but found the Nix language a bit obtuse. The basic syntax and logic are not too hard but I still found many of the packages I used as examples very confusing.

In the end I'm back to Ubuntu using Docker whenever I need reproducible environments.

</comment></comment><comment><USER4> I've been trying to get a nix file running today, and the terminology definitely gets arcane very fast.

I also have the feeling that the tutorials start with the details, instead of starting with an overview so you can understand what is what.

This is guide us already very helpful and I think one should read it before the official tutorial. Thank you!

<comment><USER5> _I also have the feeling that the tutorials start with the details, instead of starting with an overview so you can understand what is what._

When you are trying to be as different from everything else as wide-reachingly as Nix is, it seems to work better to build an understanding _up_ rather than _down_. This seems to frustrate a lot of people because it does not give much payoff for the first few hours of learning (and that's a lot to invest to even understand what something is). The truth is that Nix is really really complicated (expect a year-long learning curve to truly "get" everything), but it's also really hard to take the more-standard approaches to building packages and managing machines seriously once all the pieces finally do all connect. Unfortunately, it kind of makes one feel like being an early adopter of git in a world where no one else uses version control. It's like, "Yes, this is way better, but I'm not going to be able to get anyone else to use it."

<comment><USER6> This is well described. Nix is fundamentally a different way to manage an OS compared to almost anything out there. While I think the ideas behind it are revolutionary and is the right way to build infra, the UX and organic growth of it makes it fairly difficult to get into - so there is unfortunately a steep learning curve. I think I sunk a solid 40 hours into building a declarative config for my own dev machine before I had a decent (but far from complete) understanding. But once you grasp it, it is quite mind blowing, and you wonder how anyone could cope with traditional mutable systems and the associated temperamental config management.

I think Guix might be the answer as a more approachable implementation of the Nix ideas, using Scheme for its config language. I haven't spent much time with it but I got going a lot quicker initially compared to Nix.

<comment><USER7> > I think Guix might be the answer as a more approachable implementation of > the Nix ideas, using Scheme for its config language. I haven't spent much > time with it but I got going a lot quicker initially compared to Nix.

Out of curiosity, did you tried Guix before trying Nix or vice versa?

When looking at Guix myself, all I see is that the derivations are just wrapped in parentheses otherwise they do look similar. So I'm wondering if scheme actually brings anything here, especially for someone not familiar with a functional language.

IMO Nix language isn't actually that hard, I believe the most complexity comes from nixpkgs and still not adequate documentation of it, so one needs to study its source code.

<comment><USER6> I'm probably biased in that I primarily use Emacs and like lisps. So I find guix more approachable right out the box. Learning a new language just to use an OS is quite a big ask and part of the learning hurdle of Nix.

It's too bad that guix uses old style mailing lists for development though. I just can't be bothered setting up myself for that mode of contribution, so I'll continue to use NixOS for the indefinite future.

</comment></comment></comment></comment></comment><comment><USER8> I wish I understood how to bring new things to Nix. Like, if I have some language or framework with a bunch of plugins and modules, and I have the freedom to bend the framework a bit in order to get it working with Nix, then what is the best path for doing that? All of the documentation I've read seems like it's been written by folks who deeply understand not just each different language, but also some sort of central Nix philosophy.

<comment><USER9> I think one way to look at nix is that it want to act(in good way) the central source of truth for deterministic package, and one way it goes about it is by doing the step for both system level packages, and language level packages(for example, if you approach a nodejs app, you will lock both the nodejs version, the underlying openssl or other headers lib used by node-gyp, and the node_module packages itself in nix) and that is one of the main flow of nix, take a existing project/app/software, and convert it to usable nix packages, and that work even in edge cases like:

\- app that is binary , so you can't build it from source, but is using dynamic libraries, then you can use autoPatchelfHook to tell nix to patch the binary to swap out the libraries to nix's version

\- app that uses a lot of hard coded file system path that you would prefer not to patch them all out, then you can use buildFHSUserEnv to package/run the application/package in full FHS-compatible scenario

but the main point is that, nix is extreme in its approach, and the best approach in my opinion, is to do swapping step by step, ex:

you want to convert a existing project to nix, lets say nodejs

\- you add the main deps in the default.nix (nodejs, yarn, high level utility needed to build)

\- use sandBox false to allow building the app with yarn/npm in internet accessible(by default nix uses sandBox which disallow internet inside build step, which causes issue like npm install not working, etc)

\- confirm working, then start using tool likes yarn2nix, other similar, and convert the packages itself to a usable set of nix packages

though I do agree that nix have the knowledge bias issue, and alot of my learning of nix involve me looking at the nixpkg sources itself and sometime even the nix's code

<comment><USER10> The trouble is that it's not just that nix is opinionated, it's that much of the complexity is in patterns and conventions that are implemented in nix. Learning everything about everything about the Nix toolchain is only one third of the battle; the rest is learning all of the conventions and patterns for writing Nix expressions, and these conventions and patterns are subject to variance between target languages. This is made terribly difficult because the language is dynamically typed and it's almost impossible to know about the "shape" of any given parameter because there is no way to know where it is defined in the enormous nixpkgs repo except to grep around and try to find the place where the caller is invoked, what is passed into it, and trace that back to an original import statement (and from there to a file on disk and the corresponding definition). That long tedious process is the hot path for developing in Nix.

<comment> yjftsjthsd-h Very much agreed; nix is its own world, which makes it really hard to get into. I wish someone had written "nix but in python" (or bash, or whatever) that still used a nix-store equivalent, kept the overall design and the immutable and reproducible packaging, still connected everything by hash, did all the hydra-style build infrastructure.. but didn't use nix-the-language, and made an explicit effort to use more conventional language wherever reasonably possible. Ideally, it'd even let you write expressions in arbitrary languages; it should be perfectly possible to say, "here is a directory containing 'inputs' and 'output' subdirectories based on your declared dependencies; place any build steps you want in build.sh, so long as they deterministically populate 'output' from the package directories in 'inputs'" (and then run the build a few times, without network access, to make sure). I don't _see_ anything in nix that actually needs nix-the-language, or even a functional language at all, and I think nix-the-package-manager would be far more accessible if they'd not tied nix-the-language to everything.

<comment><USER11> I think functional languages are a good fit for the problem though. Given some input, compute a static build plan. It's very rare that you need to do imperative-style computation for that. What I think Nix really needs is some kind of static typing, because right now if you make a type error the error might appear in a completely random location, making it difficult to debug.

<comment><USER12> Take this example build file in Mozilla's custom, Python-based build system: [https://searchfox.org/mozilla- central/source/gfx/skia/moz.bu...](https://searchfox.org/mozilla- central/source/gfx/skia/moz.build)

The language is imperative, and the result is fully declarative. A pure functional description of this logic would worsen understanding instead of improving it, I believe, because when your conditionals affect multiple output variables, you have to duplicate the condition in multiple places.

<comment><USER7> Looking at the code, I don't see any advantage of using imperative language here. All the conditions used there are already available and don't change during the execution of that code. So the conditionals would be nearly identical in functional language.

Nix advantage here would be that is lazily evaluated, so there would be an additional benefit that only conditionals that are used are evaluated.

Functional benefit of Nix would be that Nix would know that a package doesn't need to be rebuilt if no inputs changed.

Side note Mozilla actually uses Nix internally, it appears that it is used for Rust and Firefox and most likely other things[1][2]

[1] [https://github.com/mozilla/nixpkgs- mozilla](https://github.com/mozilla/nixpkgs-mozilla)

[2] [https://github.com/mozilla/release- services](https://github.com/mozilla/release-services)

<comment> yjftsjthsd-h > Looking at the code, I don't see any advantage of using imperative language > here. All the conditions used there are already available and don't change > during the execution of that code. So the conditionals would be nearly > identical in functional language.

Yes, except that I can read this and I can't read nix. That's probably based on background, but more people are familiar with imperative than functional languages.

> Nix advantage here would be that is lazily evaluated, so there would be an > additional benefit that only conditionals that are used are evaluated.

Agreed, although that's unlikely to be unique to nix?

> Functional benefit of Nix would be that Nix would know that a package > doesn't need to be rebuilt if no inputs changed.

As would anything that can compare hashes. Or heck, make(1) can do as much.

<comment><USER7> > As would anything that can compare hashes. Or heck, make(1) can do as much.

Of course, language like Python is Turing Complete so you could implement the same functionality . You could also add functions that behave and perform operations lazily.

But you're missing the point though, those are properties that Nix provides natively that are tuned to what is required for this domain. Because the only side effect in nix is a derivation, and because language is lazily evaluated it is made for this purpose.

If you would use for example Python, you would need to write wrappers that would provide that behavior and it no longer would be Python, it would be some kind of DSL written in Python at that point and the risk then would be that it would be very easy to introduce iterative code that's not functional and not lazily evaluated (kind of like it happens with Chef recipes).

The Nix Language actually is not the problem here, the language is fairly simple, the biggest difficulty is actually nixpkgs which is huge and poorly documented. You often have to look at its code to understand what's going on. If it was written in Python you would have the same issues.

There is one thing that Nix Language could do better, a lot of people wish it was a typed language, because if it was typed it would be much easier to find a definitions, and wouldn't require as much of greping the code. But python again wouldn't help here.

<comment><USER10> Nix is also Turing complete, and Python (to my knowledge) can also run in a side-effect-free context through various methods (it's easy enough to enforce during code review but there are technical solutions as well). There's also Starlark which is a sealed, embedded Python-like which is _NOT_ Turing complete and which can also avoid side effects (evaluating to a derivation, if you like).

Nix may be simple but it's unfamiliar, and you're already asking people to understand a novel package management system and everything about everything about their entire dependency tree, and these unknowns are collectively more confounding than the sum of their parts.

Python would help because it is familiar and gradually typed. That said, I'm open to any language that satisfies those properties (maybe also "composes nearly from expressions").

<comment><USER7> I don't believe Nix is Turing complete, unless you include ability of running python or bash script.

Regarding the rest of your first paragraph, that's essentially what I said, you can write side effect free code in python, but it's so easy to introduce side effects if you're not paying attention.

I'm saying though that nix language isn't the hard part about nix, but perhaps you're right and it is one extra difficulty that just makes things harder.

But take a look at most o Nix derivations, majority of them end up being just an attribute set (aka dictionary, map etc in other languages)

Take look at [https://nixos.org](https://nixos.org) page (they changed it after this submission was posted, and it is better than the old page at showing what Nix can do)

</comment></comment></comment></comment></comment></comment></comment></comment></comment></comment></comment><comment><USER13> I've started writing tutorials at [https://nix.dev/](https://nix.dev/) to help people set up their development environment and get up and running quickly.

Disclaimer: the owner of [https://cachix.org](https://cachix.org)

<comment><USER13> Feel free to request a tutorial at[https://github.com/domenkozar/nix.dev/issues](https://github.com/domenkozar/nix.dev/issues)

</comment></comment><comment><USER14> I guess the ideal, for me, would be to have a service where I could upload a Nix file, and then have it generate a server from that. Darklang may be working with the general idea, but I'd like to see it for Nix too.

<comment><USER7> People mentioned NixOps (I personally think it is weaker part of Nix, but it is still good for specific use cases)

There's also another option, nixpkgs actually has a functionality to generate ec2 image, basd on your configuration.nix[1]

You can also generate other images[2]

[1] [https://github.com/NixOS/nixpkgs/blob/master/nixos/maintaine...](https://github.com/NixOS/nixpkgs/blob/master/nixos/maintainers/scripts/ec2/amazon- image.nix)

[2] [https://github.com/nix-community/nixos- generators](https://github.com/nix-community/nixos-generators)

edit: I believe you can use [2] even for AWS images, the raw and qcow2 should work on EC2 as well, the [1] is including some additional settings that make NixOS work better there, although there's nothing stopping you from adding these to your own configuration.nix

Also, this is not really a fault of Nix, but in EC2 if you import image it has to go through their conversion mechansim, which takes about 10 minutes :( A kind of workaround around it is to have another instance with attached extra EBS drive, use dd to write raw image on that disk. Then disconnect the EBS, create a snapshot of it and convert the snapshot to an AMI.

<comment><USER15> I tried to use nixos-generators recently and the experience wa frustrating. For example, I tried to generate an image in the `do` format (DigitalOcean) and a few other formats. Every time, the script (`nixos-generate`) finished running and didn't produce any output.

<comment><USER7> Hmm frankly I did not use nixos-generator before writing this post, and only generated EC2 images.

But I just tried, and it did work for me. The generated image was provided as the last line of the output.

It looked like this:

        Making image hybrid...
        /nix/store/ra02s6nmhfklmsrmhkd960xdqpwghgak-nixos.iso/iso/nixos.iso

What OS you run it on? I run this on NixOS 20.03 on VirtualBox, I needed to have "Enable Nested VT-x/AMD-V" since the process spins a qemu to finalize the image.

<comment><USER15> When I didn't get any output, I ran it in Ubuntu 18 on a Linode VPS. But I tried to generate different formats: do, qcow, vmware.

<comment><USER7> Strange that there was no output or even errors.

BTW: I believe NixOS image generation can be run only on NixOS machine, because it needs to run a VM and that requires some kernel modules to be loaded. At least I never was able to made it work on OS X.

The nixos-infect code though will turn your Ubuntu installation into NixOS, so you might try to boot to your Ubuntu machine, convert it to NixOS and I'm hoping then nixos-generate might start working.

Note though that "do" didn't work either for me, and I didn't look to investigate why, I figured out that maybe it was because I was running it on machine on VirtualBox and not DO.

</comment></comment></comment></comment></comment></comment><comment><USER16> Just a minor footnote. My interest in Nix is not high and what there is motivated mostly by the existence of NixOS. Why do I have any interest in NixOS?

We build and distribute Ardour (a cross-platform open source DAW) in a single package that runs on every Linux distribution that has libc, libstdc++, and some version of Xlib.

Every Linux distribution that is, except NixOS. They decided to patch the runtime linker so that the approach usable on every other Linux distro breaks there.

This says something about NixOS, and presumably Nix too, though I'm not sure what.

<comment><USER17> Hi Paul, thanks for Ardour.

For anyone curious, this wiki page describes how to package and run some precompiled binaries on NixOS, particularly the section "The Dynamic Loader": [https://nixos.wiki/wiki/Packaging/Binaries](https://nixos.wiki/wiki/Packaging/Binaries)

NixOS tries to insist that programs reference only other paths within the nix store (e.g. /nix/store/9rabxvqbv0vgjmydiv59wkz768b5fmbc-glibc-2.30/lib64/ld- linux-x86-64.so.2 which is a specific version built by a specific compiler, rather than /lib64/ld-linux-x86-64.so.2). This is the source of the per- program isolation that enables all the nifty features of NixOS.

NixOS _does_ make exceptions to that though, for example providing both /bin/sh and /usr/bin/env at those paths.

<comment><USER16> The key point here is that we want to package things in a distro-independent way. In our distro-independent package there is no store and hence on nixOS it won't run.

Note that the way we do things is not unique - Firefox has been packaged this way by the Mozilla Foundation for years. We consider ourselves closer to a "traditional ISV" than merely the provider of source code to the open source community (though obviously, we play the latter roll too).

We don't have the resources to spend on a nixOS-specific package, nor the desire. Fortunately, of course, nixOS users can create suitable packages for nixOS, and I think they are.

It just says something that out of the myriad flavors of Linux, nixOS is the _only_ one that has broken this rather old concept for packaging software from ISVs.

But please, carry on! Seems interesting enough.

</comment></comment></comment><comment><USER18> I like the idea of NixOS. It's somewhat hurt by the fact that it's not a first-class OS at most VPS providers. It also doesn't seem to be quite as capable as Ansible yet for configuration. If there isn't a provided variable for the setting you want, there's not a generic way to add a line to a configuration file, for example. (I might be wrong about this!)

<comment><USER19> Both of these are true, but I find that the second, at least, isn't as much of a problem as you'd expect. Most modules that configure services give you the ability to specify complete config files, which you can build whatever higher level structure you like on top of.

For example, the built-in firewall is fairly basic (at least for running on a router; it does nearly everything you'd need for most desktop and server applications). I run NixOS on my router, so I needed something more. So, I wrote [https://github.com/thequux/nix-zone- firewall](https://github.com/thequux/nix-zone-firewall) (note: the readme is slightly out of date, but it does give you the gist of it). First, I built a way to declaratively put rules in different chains (core.nix), and then I built a zone-based firewall on top of that. I then have another layer of configuration options in my router's config (not that repo) to be able to spread configuration across multiple files.

Even though this was the first significant bit of Nix that I wrote, I still was able to put the entire thing together in a single evening after work.

</comment></comment><comment><USER20> Thanks. I also found this Cheatsheet from the NixOS Wiki with comparisons to apt-get to be useful: [https://nixos.wiki/index.php?title=Cheatsheet&useskin=vector](https://nixos.wiki/index.php?title=Cheatsheet&useskin=vector)

I would also love to see a tutorial for beginners on Linux that covers common tasks like viewing changelogs, creating a simple package, and pinning multiple dependencies in an environment.

<comment><USER21> I'm actually aiming to do that in a series of post in the upcoming month(s)... I've started with a noob-friendly (written by a noob!) introduction and plan to continue with installer, basic package creation, module creation, discussing how to do rollback, what are generations etc. etc. ... I did some presentations on NixOS and these topics so I'd like to distill that into a short and easy to grasp blog posts @ [https://nixos.online](https://nixos.online) \- feedback is more than welcome! Maybe I could also include my own cheatsheet, which is refurbished version of the "official" one, but just for the basic commands in direct comparison to Debian-like distros.

<comment><USER22> A straight-up cheatsheet would be useful.

I didn't find the direct comparison to apt to be useful before installing nixos, to be honest, but as primarily a `nix-shell --pure` user who just got nixos installed on my server, I suppose I might revisit it...</comment></comment></comment>


Rejection by Palantir - <AUTHOR> https://www.reddit.com/r/cscareerquestions/comments/9mvjqz/rejected_by_palantir_30_seconds_after_i_filled/ <comment><USER2> There is absolutely zero chance that he was rejected in 30s based on ethnicity. No matter how unethical you might think a corporation might be, none would be stupid enough to implement a policy so obviously illegal.

<comment><USER3> And yet, Harvard and all the Ivys do it all the time.

<comment><USER2> Not in 30s.

Having some undesirable demographics myself, I'm quite aware that corporations discriminate illegally. It's so easy to hide, though, and so costly not to do so, that imagining this as an example seems a bit silly.

</comment></comment></comment><comment><USER4> I am guessing he was already in the queue to be rejected, but they wanted to capture the demographic data first.

</comment><comment><USER5> I have zero sympathy for people applying to a company known for doing shady things for Governments.

<comment><USER6> Really? Palantir is a real time geoanalytics platform. Among their customers are police departments, municipal governments, emergency response agencies, and, well, intelligence agencies. None of these are intrinsically bad.

</comment></comment><comment><USER7> No. The demo survey is the last piece of the application process. Once completed your application was finalized, processed, and the rejection email is sent.

If they ask the demo questions before interview it is likely to lead into accusations of bias.

Now, if pushed to court, they will have paper to backup that you were rejected at stage X, before the demo survey was sent.

</comment><comment><USER8> I'm sure Palantir wasn't explicitly doing this - the blowback would be far too severe.

Although, I am hugely cynical and always "decline to identify" whenever I'm asked.

</comment><comment><USER9> Consider yourself very lucky. They dragged me through a month worth of interviews and wasted so much of my time. I wish they would have rejected me aftet 30 seconds.

</comment><comment><USER10> How is this excusable again? My only consolation is that this will eventually backfire due to them not hiring based on skill.

<comment><USER11> Seems pretty obvious to me that they were rejected earlier in the day. The rejection triggered 2 batch jobs: One to gather applicant demographics and one to notify of their status. The timing was unfortunate, but almost certainly a pure coincidence.

Cue lazy "shill" accusations in 3... 2...

<comment><USER12> Or the application was rejected but they only send rejections to completed applications. There's a lot of reasonable explanations.

</comment></comment></comment><comment><USER13> Doubt anything associated with Thiel is rejecting based on "male", especially for technical positions.</comment>


The Case for D - <AUTHOR> http://www.ddj.com/article/printableArticle.jhtml;jsessionid=B3NCDIGAOTCJ1QE1GHPSKH4ATMY32JVN?articleID=217801225&dept_url=/hpc-high-performance-computing/ <comment><USER4> D1 + Tango == yes! Excellent combo, but serious lack in the toolchain department. DMD and OPTLINK especially is a failboat currently. LDC is based on LLVM and is "the future", but lacks windows support (exceptions! and this is inherently LLVM's problem now). DDBG is a good debugger, but is unmaintained. GDC is D on GCC, but is unmaintained.

D2 on the other hand doesn't feel like D anymore at all. Sure, there are a couple of nice things in it like ranges, but on the general perspective I could make this comparison: D1 is like C with C++ made right. D2 is D++, what C++ is to C - bloat and inconsistency.

There is also a huuuge problem with D2 and leadership/drama, which split the community. There is also problem with Phobos vs Tango - where Tango is clearly and measurably better, but that thread of issues leads to leadership drama.

Let me be clear on this (I use D every day for my projects - I am into graphics/gamedev with it). Do yourself a favor and learn D1/Tango - <USER2> is bearable and there is a book about it from Apress. Community is responsive (#d, #d.tango on freenode if you demand prompt resolutions). Use Tango from SVN, use LDC or DMD if you are on Windows.

Also, check out <http://www.team0xf.com:1024> \- especially dog (OpenGL platform agnostic binding) and hybrid (gui on top of it). Check out <http://www.dsource.org> .

There are some movements within the community that will resolve by themselves soon enough - it's too good to fall apart. In the mean time you should really do yourself a favor and give it a go.

</comment><comment><USER5> There are two big problems with D.

1) Everyone treats D2 as being the current stable version of the language, when it isn't. 2) Tango vs Phobos when it comes to D1.

But trust me, the D community is aware of those things. [1] There are a lot of tensions over the developments of D2, how they're going, etc. If and when D2 ever actually comes out, it should address lots of the issues.

But you may see something sooner than that.

[1] : <http://www.jfbillingsley.com/blog/?p=53>

<comment><USER6> A top quality, supported, opensource compiler would help. The LLVM front-end looks promising but I half expect it to be abandoned. It's kind of odd, it definitely seems like there is a desire for a compiled machine code producing language to compete with C and C++.

I kind of remember this argument with Ada over the years, particularly when the GNAT front-end to GCC was mainlined. Having tools available is a big noticeable percentage of the problem; maybe 30-45%. Tooling is becoming more than just a compiler though, an eclipse IDE for D would be nice too and it's probably required for serious consideration by the masses. Supported and live are important for this stuff.

Another aspect of adoption seems to be adoption. It's a snowballing kind of thing. In the GNAT/Ada days there were a lot more advocates of its use than there were users. If you really want D to start getting more attention, then start doing some successful D software, particularly packages that get attention seem to be good (see Mono and Tomboy) Ada has a good complaint compiler that is supported and still doesn't have many users. Some free/open software that shows some of the benefits and advantages of D would help.

<comment><USER5> Yes. This is actually is one of the main points of contention... that the dmd frontend is 'source available.' The community is doing some things to address this, but that's all I'll say.

LDC is a really great project. It's not being abandoned anytime soon, trust me. Those guys are working hard, and they answer bug reports really, really fast. Though I'm admittedly slightly biased, since they use my kernel as a test case.

There are several IDEs that support D, though I can't think of them off of the top of my head, since I use vim. Posiedon?

There have been several intersting D projects, but you're right, more would certainly help. The blog post I linked to's author wrote a little language called MiniD that's pretty interesting, I (and several others) are writing a kernel, etc... but dsource.org can look like a graveyard sometimes...

<comment><USER7> The dmd front end is GPL'd.

<comment><USER5> Thanks for the correction, Walter. As Wikipedia says:

The Digital Mars D compiler is the official D compiler by Walter Bright. The compiler front-end is licensed under both the Artistic License and the GNU GPL; the source code for the front-end is distributed along with the compiler binaries. The compiler back-end source code is available but not under an open source license.

</comment></comment></comment></comment></comment><comment><USER8> D is well-designed and has many wonderful features, but its documentation is so bad as to make it unusable for serious work. This article is the _best reference work_ on D2 that I have yet seen, which should not be the case.

Also, this guy has been working on the book for over two years now. Even when it's done, it's going to be just like Grails is now: you can read the online docs, but you don't really get it until you read a certain book.

<comment><USER9> > you can read the online docs, but you don't really get it until you read a > certain book.

Isn't that expected and normal for anything that involves thinking about things a different way? D has language features that most programmers aren't familiar with, so to use the effectively involves a shift of thinking. Same with Grails.

<comment><USER8> It's not that books are bad, it's that there is _only one book._ If it's not in The Book, you essentially can't find it anywhere, unless your mailing list spelunking skills are particularly good.

<comment><USER10> I never read The Book, instead learning the language entirely by the spec. It's honestly not that hard.

</comment></comment></comment></comment><comment><USER11> The question is, is D better enough than C++ to make us switch?

When taking over you must not just be better, you must be a hell better to justify the cost of the switch.

<comment><USER4> D might not be better from the glance over it, but it's little things in it that REALLY add up. I strongly recommend anyone who ever wrote C++ code to give it a go for at least a couple of months and see for themselves. That is the best way to measure - I can only give you my sincere recommendation to try it out.

<comment><USER11> It looks great, I agree. I like the range approach for the standard library. I also like the end of the include nightmare.

Is the output binary as good as a C++ one? That would be my first purely technical concern.

Other concerns would be related to the building tool chain and the quality of IDEs.

But the real concern is business oriented.

For pet projects I'd be inclined to give a green light. It's always nice to play with new technologies as it opens your mind and give you new ideas.

For full fledged commercial products you expect to live several years, that's going to be a solid red light. I wouldn't take the risk of using an unsupported language.

<comment><USER4> "I like the range approach for the standard library"

This is D2 - I don't use D2 and wouldn't use it. I was talking about D1/Tango combination. I don't think I'll make a switch to D2.

"Is the output binary as good as a C++ one? That would be my first purely technical concern."

That depends on the compiler/linker, of course. In short - dmd good enough, ldc great (llvm as the backend after all).

"Other concerns would be related to the building tool chain and the quality of IDEs."

You can download DMD/Tango package from their Trac page and you're ready to go, however I would strongly advise you to use SVN tango version - <USER3> implies you need MSYS(on Windows) to build it. Ask for help on forum there (dsource.org/projects/tango) or on irc d.tango (freenode). As for IDE, you can use Descent for Eclipse, as some people do. I use Emacs for everything though, same applies for D - there is a module for it.

"But the real concern is business oriented."

There is no concern here, since basics of risk management should tell you not to use it. Same applies for other emerging or obscure technologies as well (I'm looking at you Lisp). Short answer, don't use it for business critical things yet, though some have done that with success.

<comment><USER11> I'm curious, why don't you want to do the switch to D2? Is it because it's not mature enough?

<comment><USER4> There are several reasons. I'll try to list them, but it might not be complete:

\- D2 looks and feels foreign to me as a somewhat D1 experienced user

\- Templates maelstrom and strong emphasis on them

\- D1 grew organically, D2 looks like an academic exercise where stuff is put in just for the sake of it by the people that don't write programs in D at all (Andrei)

\- D2 book and Andrei are a filibuster for D2

\- Walter Bright listens to Andrei (ok, a smart guy) but he doesn't write D programs, I doubt even Walter writes them (seriously). If you look at his code, it is more of a C in D than D code.

\- I have little to no trust in DMD/OPTLINK, LDC/LLVM is what I'm after and that front is D1 only, and looks like it will be

\- Lots of people smarter than I am are on D1 also (Tango, namely) - and I don't want to go against the trend since it would isolate me from little support I can get

these are just of top of my head, there are more. General summation could lead to "It just doesn't feel right" - at least for me as a heavy D1 user.

<comment><USER12> >> ...the people that don't write programs in D at all (Andrei)

>> Walter Bright listens to Andrei (ok, a smart guy) but he doesn't write D programs

You stated twice that he doesn't write D programs. Well since you are mentioning Tango, it's unfair because he writes code for a _standard_library_. And he is writing a good code.

<comment><USER13> I also don't think it's true. In addition to writing code for the std.* Phobos library, I think Andrei has been using D for data processing stuff related to his recently finished dissertation. He would make comments from time to time about this or that not performing well enough in std.*, and then go fix it.

</comment></comment></comment></comment></comment></comment></comment></comment><comment><USER14> Okay, I'm totally going to bite on the "find something you don't like in 30 seconds" and it's the hello world example.

void main() { writeln("about to do something important"); doSomethingImportant(); }

is this really not going to run doSomethingImportant() if the writeln fails? I find that to be a poor default for a systems language.

This may just be a personal preference, but I strongly want a _systems_ language to do one of 2 things:

1) Require me to explicitly state when I care about an operation failing 2) At compile time ensure that my code explicitly states when it's not going to handle an exception. (Java with this, like so many things, gets it 90% right and then falls on its face)

Silently passing exceptions out to the system is a bad default for something that is supposed to be able to be used to build the system!

Note that this preference does not apply for a large swath of applications programming. For a webapp, it may be reasonable to log any uncaught error conditions to a log file, since we can just signal the client to try again.

<comment><USER7> Uncaught exceptions are caught by the D runtime code, and the appropriate message is printed.

You can declare functions as "nothrow", in which case the compiler will complain about any uncaught exceptions in the function body.

</comment></comment><comment><USER15> I've tried several times to write a project in it, and every time I found some horrible bug, something missing, broken (OSX support is poor) or libraries turned out to be useless/outdated (dsource is a graveyard), or that I've chosen the wrong set (D1 vs D2, Phobos vs Tango).

I'd really like to use D, it's the non-sucky C++ I've been waiting for, but it's just far from being usable and reliable yet.

</comment><comment><USER16> Kenta Cho, sole member of ABA Games, uses D to write his (excellent, open source, freeware) shmups. Go for the code, stay for the games:

<http://www.asahi-net.or.jp/~cs8k-cyu/index_e.html>

<comment><USER17> It doesn't seem like he uses D anymore. His last two games were written with C# and XNA.

</comment></comment><comment><USER18> `[...] the classic "hello, world" for other languages such as Java (code omitted due to space limitations [...]'</comment>


Apply HN: Wevest – Replicate Trades Experts Make to Increase Success in Stocks - <AUTHOR> Wevest connects people to invest together and smarter. It allows you to replicate trades made by experts so people can skip the whole trial and error in the stock market. Once you attach your assets to an expert, it is all automated from there. When the trader you follow sells, you sell, all in real time. Unlike betterment, where they focus on long - term growth and competes with banks and mutual funds, our competitive edge goes by giving tools for a more aggressive investing approach by leveraging expertise of others. <comment><USER2> Modern online brokers already have the option to "mirror" another trader's trades (i.e. I say "I want to copy this person" and I make every trade they do, at the same time). How will you compete with these?

<comment><USER3> Doesn't Instavest (YC funded) do the exact same thing?

<comment><USER2> Yeah, I believe so.

</comment></comment></comment><comment><USER4> What prevents Wevest from being used by trade experts as a way to scam people? It would be like giving these pump and dump people access to your Ameritrade account. They will have 2 accounts. Their real account and their Wevest account. Buy a stock for $1 with real account then use their we vest account to but the same stock. The price will go up. Then sell the stock in the real account.

</comment><comment><USER5> I can see that there might be demand for this, although I would not recommend this app to my friends so that's a bad sign. I fear that casual people trade stocks for certain reasons - only one of which is to make money. In particular, I think a lot of people trade stocks because they have certain hypotheses about the world / markets and they want to test them out or be able to talk about them. Even people who invest in index funds have strong beliefs about which index funds are best. I guess you can tap into the "which managers are best", kind of, but it doesn't seem as appealing for some reason.

</comment><comment><USER6> This is an interesting idea - a few questions that come to mind:

How do you plan to acquire your trading data? Public filings? Experts voluntarily sharing their portfolios?

What type of experts do you envision being on your platform? Jim Cramer type CNBC personalities? Hedge fund managers?

<comment><AUTHOR> We plan on using Tradier brokerage with the Tradier api.

In terms of envisioning, it would be more Jim Cramer type that would be more interested in this over Hedge Fund Managers, in an honest opinion.

</comment></comment><comment><USER7> etoro?

<comment><AUTHOR> Etoro you are able to see other portfolios, through payment. We are also mobile first and we use machine learning to develop a system that eases mirror trading and creates a better experience for these novice traders</comment></comment>


The top bug predictor is not technical, it's organizational complexity - <AUTHOR> https://augustl.com/blog/2019/best_bug_predictor_is_organizational_complexity/ <comment><USER2> This is a no-brainer.

As a development manager for a quarter-century, and an active software developer for a lot longer than that, I can definitely say that every place there's a "meeting of the minds" is a place for bugs.

In the software itself, the more complex the design, the more of these "trouble nodes" (what I call them) there are. Each interface, each class, each data interface, is a bug farm.

That's why I'm a skeptic of a number of modern development practices that deliberately increase the complexity of software. I won't name them, because I will then get a bunch of pithy responses.

These practices are often a response to the need to do Big Stuff.

In order to do Big Stuff, you need a Big Team.

In order to work with a Big Team, you need a Big Plan.

That Big Plan needs to have delegation to all the team members; usually by giving each one a specific domain, and specifying how they will interact with each other in a Big Integration Plan.

Problem is, you need this "Big" stuff. It's crazy to do without it.

The way that I have found works for me, is to have an aggregate of much more sequestered small parts, each treated as a separate full product. It's a lot more work, and takes a lot more time, with a lot more overhead, but it results in a really high-quality product, and also has a great deal of resiliency and flexibility.

There is no magic bullet.

Software development is hard.

<comment><USER3> So, just a day ago, I got dragged into a meeting where many people were involved in a discussion about the new Cloud Enterprise Application Architecture Template. Or whatever.

It had a 3-tier architecture.

I asked: Why?

And they answered: Why not?

I answered: Because layers must only be introduced if needed. Is there a need?

They answered: The standard design is the need.

I clarified: Is there a _technical requirement?_ Or perhaps an organisation one, such as disparate teams working on the two components?

They answered: No! Of course not! It's a unified codebase for a single app written by a single person! But it is not Enterprise enough! It must be split into layers! And then, you see, it will will match our pattern and belong.

I verified the insanity: Are you saying that this finished, working application isn't currently split into layers, but you want it split into layers simply so that it can have layers?

They chorused: Yes.

<comment><USER4> The 3 tier architecture was a reaction to VB and RAD-like tools, where things like data validation and database I/O were coupled directly to the input component. It was common for these frameworks to not even have an object for data transfer sitting between UI and DB.

This was the timeframe where more and more manual work was automated. Hence it was a common situation where input used to be given by a human, but now comes from another application. The simplest way to do that kind of retrofit was to drive the UI from the application: The application fills in its own gui fields which triggers the validation, then simulates a click on OK.

This caused al kinds of ungodly messes. You need a gui for background processes, reliability was low, etc.. 3 tier architecture were a way to say 'never again' to this style of programming. Forcing people in to it was necessary.

But that was another time. Mindlessly applying an architecture without understanding why is of course dumb. But not applying an architecture without understanding it's pros and contras is just as dumb. It all depends on the quality of the architects in question.

Not that I want to call you dumb, of course. IT today is different from 20 years ago.

<comment><USER5> n-tiered architectures were born during the transition from "workgroup" to "client/server". This upheaval caused an industry-wide loss of programming lore.

It wouldn't have been too bad, except the ODBC interface inadvertently led to abandoning schema-aware programming models like VB's ADO, Paradox, FoxPro, etc.

At the same time, object oriented became fashionable.

So we ended up with ORMs, ActiveRecord, and various offshoots.

Mostly because no one remembers life before client/server.

<comment><USER6> I was always a bit hazy on what these terms actually meant, and what we lost. It does seem like there was a brief golden age of easy "rapid application development" tools like FoxPro where you could wire some UI fields to a database without too much trouble. Now we have people trying to do the same in the web, badly.

<comment><USER5> I also had no idea what client/server meant (at the time). My current oversimplified distinction:

Workgroup: I/O thru file system, clients responsible for locking, concurrency, etc.

Client/Server: I/O thru DB's protocol (eg TDS), server responsible for locking, concurrency, etc.

\--

As for what was lost, I spent way too long (10+ years) trying to figure that out, trying to fulfill the desire to recover the ADO (Access Data Objects) programming paradigm. I think I succeeded, more or less, and am currently reorienting my life to work on it full-time.

</comment></comment></comment></comment></comment></comment><comment><USER7> This rings true for anyone who has ever worked at a big tech company (I work at Google).

At Google when your project begins to scale up you can ask for more money, more people, or both. Most teams ask for both.

What you can't ask for is _different_ people. You can't solve your distributed systems problems by adding 5 more mid-level software engineers to your team who have not worked in the domain. Yet due to how hiring works, this is what's offered to you unless you want to do the recruiting yourself. Google views all software engineers as interchangeable at their level. I have seen people being sent to work on an Android app with hundreds of millions of users despite never having done mobile development before. That normally goes about as well as you'd expect.

So you end up with teams of 20 people slowly doing work that could be done quickly by 5 experts. In some cases all you lose is speed. In other cases this is fatal. Some things simply cannot be done without the right team.

<comment><USER8> I see the same thing, and the only way I can reconcile this is that the benefit to sr leadership in terms of treating SDEs as fungible is so massive that it is still worth the massive productivity loss from assuming exchangability.

<comment><USER9> What are the benefits to treating SDEs as fungible?

At Amazon, Sr. Leadership and HR love to pretend all SDEs at a given level are interchangeable, level actually indicates competence, and leetcoding external hires with zero domain knowledge have far more worth than internal promos. All of the above assumptions seem completely insane to me and have resulted in the destruction of many projects.

<comment><USER8> Yeah me too. Also at amazon. And yet amazon is obscenely successful, as are other big tech companies which take similar strategies. It seems that matching expertise to projects is so fucking hard that just giving up at the start and accepting it's impossible is the optimal strategy.

Honestly I don't know. I agree it's weird. But these companies keep succeeding doing it this way, so I'm not sure what to make of it.

<comment><USER9> > But these companies keep succeeding doing it this way, so I'm not sure what > to make of it.

That doesn't necessarily mean anything. The fact that a system might be working, doesn't mean it's anywhere near optimal. I think these companies are successful in spite of these types of policies, not because of them.

</comment></comment></comment></comment></comment><comment><USER10> Looking at the metrics used in the publication[0], it seems most of them focus on the absolute number of engineers working on a given component. This makes sense — more engineers touching a component introduces more opportunities for bugs. (Edit: as other commenters have pointed out, total lines of code, highly correlated to number of engineers, is likely the best first-order predictor of bugginess.)

I bet we can improve predictive power by considering the degree of _overengineering_ , i.e., the number of engineers working on a task (edit: or lines of code) relative to the complexity of the task they're working on. 100 people working on a task that could be accomplished by a single person will result in a much buggier product than 100 people working on a task that actually requires 100 people. The complexity of code expands to fill available engineering capacity, regardless of how simple the underlying task is; put 100 people to work on FizzBuzz and you'll get a FizzBuzz with the complexity of a 100 person project[1]. Unnecessary complexity results in buggier code than necessary complexity because unnecessary components have inherently unclear roles.

Edit: substitute "100 people" with "10 million lines of code" and "1 person" with "1000 lines of code" and my statement should still hold true.

[0] [https://www.microsoft.com/en-us/research/wp- content/uploads/...](https://www.microsoft.com/en-us/research/wp- content/uploads/2016/02/tr-2008-11.pdf)

[1] [https://github.com/EnterpriseQualityCoding/FizzBuzzEnterpris...](https://github.com/EnterpriseQualityCoding/FizzBuzzEnterpriseEdition)

<comment><USER11> My own (current) personal hell is essentially the inverse of this assumption. I work in an area that was essentially ran by 1 extremely overworked developer. The result? Now there are 40 people (including management, PMs, Scrumlords, QA and devs) doing the work originally done by a single person. The tech-debt and cruft is unbelievable (considering the domain is also quite complex). Every decision made before the 40 people were hired was made just to check off 1 of 1000 things on this person's plate... I could probably write a book about this if we are ever able to turn things around, which requires explaining to management why the things that have been 'working' for over a decade are longer working.

The sad part is, it would seem like all the engineers we have are overkill, but in my little silo, we could easily split our work into even more sub- teams, hire 12 more people, and still keep churning just to stay afloat. Sorry for the rant, I'm not sure exactly what I'm driving at. I guess I'm just trying to give a cautionary example of how not to manage large-scale software projects.

<comment><USER12> Often times, I've found situations that you describe (ones where you need to throw infinite developers at to fix) to be a smell that what your "product" does isn't something that isn't line with how your business delivers value. Such things are almost always candidates to be replaced by third party software of some kind.

Maybe I'm wrong though. When you are charting new ground, building new shit that has never been build before--which is what your product teams _should_ be doing--you don't have years long backlogs because you can't see that far out. Good, productive feature work is iterative.

If you can see with a high degree of clarity what you will be working on 5 years from now, it probably means it's been done before and you are better off cutting a check for it.

Hopefully this makes sense :-)

<comment><USER11> I agree. I've even suggested to my manager that we'd be better off utilizing a 3rd party. Problem is, this is a corporate gig. We don't have a 'product', we're just a cost center for the business. Even if we outsourced to a 3rd party, that would likely take years to coordinate.

</comment></comment></comment></comment><comment><USER13> Isn't this aligned with Conway's law? I mean, a complex business model requires, most likely or eventually, a complex solution? If not, the two systems are at odds, and the computer system is even more complex/buggy since it doesn't follow the organization's complexity, it doesn't do what the organization need it to do.

That at least is my experience anyway.

<comment><USER14> I was surprised that Conway's law was not mentioned.

<comment><USER10> In the original publication that's the subject of the article, it was: [https://www.microsoft.com/en-us/research/wp- content/uploads/...](https://www.microsoft.com/en-us/research/wp- content/uploads/2016/02/tr-2008-11.pdf)

</comment></comment></comment><comment><USER15> Just skimmed over the post, so it's possible they pointed this out and I didn't notice - but I think this is misleading. The title makes it sound like organizational complexity _causes_ bugs, but in reality I think both are simply effects of a more underlying cause.

Larger and more complicated software both requires a bigger team (therefore more organizational complexity) and is more likely to contain bugs.

<comment><USER16> Steve McConnell identified it as the number of lines of communication in the team or dept creating the module, incl dependents and dependers.

It's why Conway's Law exists, and points towards the importance of well- designed and -specified APIs.

<comment><USER17> If you consider people on a team as nodes in a graph, and lines of communication as edges, then a team of _n_ people has potentially _(n(n-1)) /2_ potential lines of communication. I try to express to people that the more potential lines of communication you have, the greater the chance of miscommunication. I think this is also called out in Brooks' _The Mythical Man Month_.

<comment><USER16> Indeed. It's even a law named after him:

[https://en.wikipedia.org/wiki/Brooks%27s_law](https://en.wikipedia.org/wiki/Brooks%27s_law)

</comment></comment></comment></comment><comment><USER18> >Organizational Complexity. Measures number of developers workong on the module, number of ex-developers that used to work on the module but no longer does, how big a fraction of the organization as a whole that works or has worked on the module, the distance in the organization between the developer and the decision maker, etc.

After one of the early big software project failures (maybe Multics?) there was a quote about software projects going around (maybe John R Pierce?) that "If it can't be done by two people in six months, it can't be done."

One of the functions of good software design is to break the system down into pieces that a couple of people can complete in a reasonable length of time.

</comment><comment><USER19> Herbert Simon is who you read first when you thinking about orgs - [https://en.m.wikipedia.org/wiki/Satisficing](https://en.m.wikipedia.org/wiki/Satisficing)

That will take to you to healthy and productive places.

</comment><comment><USER20> The article examines this through the lens of Windows Vista. Am I the only person who actually did like Vista and didn't have any problems with it? I gathered that most of the issues people had with it was caused by third party incompatible software and hardware.

<comment><USER21> I also had little trouble with Vista and liked it well enough. But I had plenty of RAM, I believe it performed badly with 1 GB or less. And of course people got hung up on UAC.

<comment><USER22> That's kind of crazy. Firefox and libreoffice don't do well in 1 Gig of ram but at least they're _doing something._ You can run a decent DE and few decent apps in 1gig just fine with most Linux distros.

<comment><USER23> And Microsoft Word ran perfectly well on 16MB of RAM in Windows 95, back in the day; and even better on NT with 32 or 64MB, productive and more than comfy.

I guess my point is that running decent software on what today would be considered very little hardware is a solved problem, but it's not what the economy is optimized for.

<comment><USER22> The difference here is that LibreOffice is still maintained (in fact, the math typesetting in Microsoft office is practically unmaintained at this point and is just miserable to use.) Old windows (and old Linux) have serious problems that modern OSes don't have. You can run _modern_ _good_ and _compatible_ software in very little ram and the only reason not to is because someone else is forcing you or you're just not aware.

</comment></comment></comment></comment></comment><comment><USER24> I guess this is why startups exist because it it almost impossible for larger firms to execute good ideas even if they think of the idea themselves

<comment><USER25> What is the underlying reason goliaths don't execute ideas well? Too many chefs in the kitchen?

<comment><USER26> Lots of freeloaders and incompetent power trippers in the middle layers and above. Small orgs. and startups cannot afford this kind of workers.

In my current project (big co.) we have a technical PM, a non-technical PM, a non programmer dev lead, an scrum master and a lead business analyst, all involved in managing the work of a team of 2 and a half (a sr ba/qa guy, a part-time ssr dev and me). Waste work is probably in the 90%.

<comment><USER12> > Lots of freeloaders and incompetent power trippers in the middle layers and > above.

Not just middle layers and up. Freeloaders and gatekeepers everywhere.

</comment></comment></comment></comment><comment><USER27> I think all current and ex Microsoftees can agree (and probably other workers in Big Tech Corp) that this is not only obvious but ongoing and dastardly resilient to getting solved! At some level this must be a sociological thing because humans seem to be hardwired into repeating this mistake.

This happens at smaller companies in smaller ways but the effect is the same.

It's worse than the "Mythical Man Month" in that production is not simply slowed down but it is slowly made rotten until it gets burned, buried, or passed off to out-sourced maintenance.

</comment><comment><USER28> The article ends with a mention of the book 'Accellerate'. Accellerate is your typical management book, based on some surveys with bad statistics and worse conclusions. Weird he mentions this book after talking about what a proper, replicated study Microsoft Research did.

</comment><comment><USER29> Previous discussion (which got flagged):

[https://news.ycombinator.com/item?id=21795462](https://news.ycombinator.com/item?id=21795462)

<comment><USER30> I can't quickly tell why it was flagged. Was the study highly flawed? Or promoted in a dishonest way? Or was it really the comments as a whole that got it flagged?

<comment><USER31> Probably because the title was originally extremely linkbait-y.

</comment></comment></comment><comment><USER32> ...which is likely proxy for complexity of the task - the more difficult the task, the more likely it'll have bugs - not an exciting revelation.

Their "code complexity" means nothing. If you compare simple "todo web app" it'll have orders of magnitude more "code complexity" than, for example, sha256 hash implementation.

<comment><USER33> And rightly so. It is much easier to write a bug-free sha256 implementation than try to write a bug-free To-Do app.

</comment></comment><comment><USER34> Conway's law strikes again.

</comment><comment><USER35> Does this mean that a solo developer working on a SaaS product can avoid bugs?

<comment><USER36> surely this solo developer will avoid bugs regarding "communication misunderstanding" between the team elements.

<comment><USER37> I'm not totally sure about that. "Me, yesterday" has to communicate with "me, today", and communication misunderstandings can absolutely happen.

Now, sure, such things happen _less_ when it's me talking to me than when it's me talking to you. They still happen, though.

</comment></comment></comment><comment><USER38> The use of the term 'p-value' seems off, it looks like he is referring to a different concept but using an overloaded term.

</comment><comment><USER39> I have a Microsoft keyboard that has a dedicated Calculator button. In older versions of Windows, I used to press that button and start entering numbers right away. But in newer updates of Windows 10, I now have to press the Calculator button, WAIT FOR THE CALCULATOR TO LOAD, and then start typing my digits. I think this is ridiculous.

<comment><USER40> I don't share this experience. I think you have an underlying issue.

<comment><USER39> This started happening when default calculator changed from a classic native app to the new "modern" app.

</comment></comment></comment><comment><USER41> Code/technology is nothing more than a tool. A toolbox is only as good as the person/peoples who pick it up. That is a great tool will not save a disorganized organization. The great tool will not make a crap product better.

Blaming the means for the ends is a classic n00b mistake. A mistake that's being made over and over and over again.

</comment><comment><USER42> From the article:

> In the replicated study the predictive value of organizational structure is > not as high. Out of 4 measured models, it gets the 2nd highest precision and > the 3rd highest recall.</comment>


Due to a programming error, the results of the 2012 DV lottery were rescinded - <AUTHOR> http://en.wikipedia.org/wiki/Diversity_Immigrant_Visa#2012_results_rescinded

<comment><USER2> Why do people program this stuff themselves?

        shuf -n22000 < list.all | sort > list.lucky

See also [http://www.robweir.com/blog/2010/02/microsoft-random- browser...](http://www.robweir.com/blog/2010/02/microsoft-random-browser- ballot.html)

</comment><comment><USER3> I am interested to know why they have the problem only this year? They are not using the same algorithm before? Or they just discovered the problem now but can't do anything to the previous lottery winners?

<comment><AUTHOR> One article says that it was a new program. Apparently they chose to rewrite it, for some reason.

I wonder what the bug was though - They mention that 90% of those selected are from the first two days of registration.</comment></comment>