1. 3

    I only read the beginning of the README, and I wish there was a more formal overview of the key innovations of the language. The premises are very interesting, but I couldn’t get the gist of what exactly is the impact on syntax and semantics of avoiding allocating data on the heap.

    1. 3

      I didn’t understand it either. Much more hype than information. Plus, the author claims a focus on doing better than C or LISP on things like GPU’s but ignores all the languages built for parallel programming. Some of those were extensions to or libraries for C that were used successfully on supercomputers. Author also obsesses about not doing everything on the heap when HPC-style languages mostly don’t that I’m aware.

      I’m keeping it since it looked like it might still have some useful ideas. I’m just skeptical the author’s developments should be trusted after having done no research on prior work except for a fork of Futhark.

      1. 2

        Glad I’m not the only one! I found Futhark very clearly presented, both on terms of features and actual code examples.

        I’d really like to see examples of things like tree traversal without heap allocated objects. Is that even possible/desirable? Most of the software I’ve written is more about transforming heterogeneous data than computing things on large homogeneous datasets. GPU programming, just like DSP programming evolved from signal processing to general programming – but is it really that generic? Is the high parallelization always a win?

        1.  

          I’d like to answer you but can’t. Too far out of my expertise. If not INFOSEC, algorithms on large amounts of data would’ve been the other I’d choose since the tradeoffs are endless. I do suggest looking at X10, Chapel, and ParaSail to see how some parallel languages were designed. I know ParaSail got rid of global heap. Cray is still pushing Chapel recently comparing it to some mainstream stuff in benchmarks.

    1.  

      I’d love to see a comparison between this and quorum.

      1.  

        I keep thinking about putting an evidence package from safe and verified systems to give them some language features to study. Especially like contracts or Ada’s built-in safety features.

      1. 1

        Nice, I was actually starting to look at centralising my cloud services on an openbsd computer at home, this could do quite nicely.

        1. 4

          Warning: every time I see self-hosted email posted to HN there’s piles of people showing up talking about how bad it went. Esp message delivery not being reliable due to both infrastructure issues and blacklisting. It’s often different people saying it, too, which indicates these problems hit lots of people.

          1. 5

            It’s not necessarily trivial, but a lot of the people posting on HN with that kind of comment, when you inquire further, turn out to have been doing mass emailing, things like sending out large-distribution newsletters or transactional emails for a webapp. Deliverability for that kind of email is a whole different ballgame than just running a private email account.

            For what it’s worth I’ve hosted my own email for about 5 years now and haven’t had any problems.

            1. 3

              There were also people that said it worked out fine for them. Just really hit and miss compared to self-hosting a web site or something. Email is often used for important stuff, too. I thought I should give a warning for that reason.

            2. 4

              This is a legitimate concern, to which I would like to add my anecdote.

              I did the following for my personal email address, while looking at what signals rspamd uses for classification. I noticed that replying to a message will lower the spam score, as well as whitelist that message type if configured so.

              Moreover, a similar mechanism exists in Protonmail’s Spamassassin configuration, as well as Gmail’s own Bayes classifier. This can be seen by inspecting X headers.

              For this reason, I asked real free-email users (from my address book, not create accounts on free-email just for this) to send me a test email, to which I replied. From then on, my emails have negative spam score on Gmail and Protonmail. I will test with Outlook soon.

              I don’t have any experience hosting multiple users, because it’s a different game involving privacy laws, tech support, and blacklist politics mentioned in other self-hosting email threads.

              Edit: spelling and coherence (sry)

              1.  

                I’m not sure yet whether I really want to do email yet, but I’ll definitely be moving http, git and a few other things. In the meantime I still have email with posteo and dismail.

            1. 1

              I sympathize, but is installing most common languages that hard?

              Python, Ruby, and Java are all a single search away, and the first result gets you to a download page rather quickly. If you’re learning a language or Bayesian Statistics…you probably should be able to install a programming environment.

              I’d recommend using homebrew or chocolatey as installers, that might help grease the wheels as well.

              1. 4

                There was a lot of unnecessary complexity when I tried to use Python or something similar to prove or disprove Monty Hall result in 30min-1hr after a head injury forgetting programming. That challenge time had to include setting up tools, learning the language, etc. The problem just takes basic I/O, some random numbers, and some calculations. When little issues added up around the runtime or a library (can’t recall what), I just decided to try a version of BASIC since I started on it with almost no effort long ago. FreeBASIC had an auto-install for Ubuntu. Manual was about a page or two with simple I/O commands plus usable examples. Programming was typing into text file (.bas) followed by one command to compile. So, so, simple. Competed the challenge with most time going to semi-formal specification as intended vs the code or compiles.

                Probably good idea to get something already set up with libraries and all in these more popular languages. Maybe even some premade libraries for common plumbing that require no thought. They can learn the real thing as they progress. I’m sure these exist at least in pieces but lots of newcomers never see them.

              1. 9

                I think “lisper” on the HN version of this article had a great summary:

                “What’s really going on is that, in Lisp, code is a particular kind of data, specifically, it’s a tree rather than a string. Therefore, some (but not all) of the program’s structure is represented directly in the data structure in which it is represented, and that makes certain kinds of manipulations on code easier, and it makes other kinds of manipulations harder or even impossible. But (and this is the key point) the kinds of manipulations that are easier are the kind you actually want to do in general, and the kind that are harder or impossible are less useful. The reason for this is that the tree organizes the program into pieces that are (mostly) semantically meaningful, whereas representing the program as a string doesn’t. It’s the exact same phenomenon that makes it easier to manipulate HTML correctly using a DOM rather than with regular expressions.”

                1. 3

                  I don’t think tree vs string is the difference. For all languages, it is a string of bytes on disk and a tree once parsed in memory. Lisp just has a closer correspondence between tree and string, which makes it cognitively easier. I don’t know where somebody would draw the line that they are considered “homo”, equal.

                  1. 5

                    Lisp just has a closer correspondence between tree and string, which makes it cognitively easier

                    Maybe not just cognitively but also in terms of programming. Many languages have complicated parsing and contexts where transformations aren’t as simple as an operation on a tree with regularity in its syntax and semantics.

                    1. 2

                      Right. Von Neumann machine code is homoiconic, but I don’t think it exhibits many of the purported advantages of Lisp?

                      1. 2

                        The one’s Ive seen are definitely harder than LISP’s to work. Now, might be different if we’re talking a Scheme CPU, esp if microcoded or PALcoded. With SHard, it can even be built in Scheme. :)

                    2. 5

                      I think at the point that the tree-literal syntax is the same as the language-proper syntax is a pretty good point to consider it equal. You can’t express arbitrary javascript programs in JSON, or any other C-family languages code in data-literal syntax. The lisp family however uses the same syntax for representing data as it does for representing its program.

                  1. 4

                    This should probably have a date on it – the last update for the code was 2005; I’m not sure about the paper, but it looks like it formed part of Toshiyuki Maeda’s thesis (2006), and the article was written about in 2008 here: http://lambda-the-ultimate.org/node/2717

                    1. 1

                      I didn’t have a date on it probably cuz I found it on mobile. Thanks for the dates. I’ll put 2006.

                    1. 4

                      REBOL did this better than most. All functions were just blocks, all functions were of fixed arity (with refinements to allow the arity to be changed), and had a rich syntax for literals of many different types…all of which means you could write powerful CL-style macros/reader macros with much richer syntax much more simply. Defining DSLs was dead simple.

                      Ah, REBOL. You were too beautiful for this world.

                      1. 4

                        I also liked how small the reblets were when I looked at REBOL and the IOS that came before iOS. If you love REBOL, what do you think of Red? If you tried it out, did you find anything better or worse?

                        Also, note that Red/System (see docs) supposedly lets one do system programming in REBOL/Red style. Figure you might like that concept given you like REBOL and apparently code in C language at work. Some could make it extract to C like PreScheme did and Ivory does to get benefits of HLL for low-level programs. Last I checked, it produces machine code directly using tooling implemented in REBOL.

                        1. 3

                          I’ve looked at Red and it’s awesome, but I fear it makes a few of the same mistakes that REBOL did.

                          The main mistake is that the set of datatypes is closed and there’s a distinction between “types” like blocks and words, and objects that are user-defined.

                          Objects are not first-class types and types are not first-class objects. For example, at least the last time I looked, it was not possible to pass an arbitrary object to print and have it come out with your custom format.

                          The object system in REBOL was dying for a Common Lisp-style multiple dispatch object system. Then you could define a new print multimethod for objects of your class, for example.

                          So you have a closed datatype system and the best way to extend it, objects, aren’t integrated as well with the system as I’d hoped.

                          (The last time I wrote any REBOL code was probably almost ten years ago, though, so…Don’t hold me to any incorrect statements. :)

                          1. 2

                            I don’t consider the datatype design a mistake, just a different choice. Objects are first class types, though they don’t (yet) have a literal lexical form. Construction syntax, as in Rebol, has been considered, but that feature hasn’t been needed yet, so it’s not locked down. And while we will learn from other languages, including CL, it doesn’t mean we can incorporate their every feature and still maintain a consistent design. We have someone who has built some really cool CL feature examples to experiment with*, but deep design changes need solid work done to show that they can integrate well with Red’s design and goals. They should be a step forward, not just in a different direction.

                            *examples

                            That said, if you want to play with new ideas, it’s easy. And we’ll see what features user defined types come with. If you want to influence that design, now is a great time to get involved.

                            name: object [
                                f-name: "John"
                                l-name: "Public"
                                formed: is [rejoin [f-name " " l-name]]
                            ]
                            eqn: object [
                                n-1: 10
                                n-2: 2
                                fn: :add
                                formed: is [form fn n-1 n-2]
                            ]
                            print+: func [val][
                                either object? :val [
                                    print either in val 'formed [val/formed][mold val]
                                ][print :val]
                            ]
                            print+ name
                            print+ eqn
                            
                      1. 7

                        That chip aging breaks the properties of the chip is another reason I’ve advocated using older, simpler nodes for high-security systems. The less you fight with physics, the more often you’re chip will do exactly what you want it to.

                        1. 2

                          @spinda originally suggested this here: Tag Suggestion: Tag Suggestion. That was extra funny because it looked like a joke that also could bring real value to some users. One of best kinds. :)

                          1. 4

                            Empirical Software Engineering: I followed a course at my university on this. It was an eye opener. I can publish some of my reviews and summaries sometime. Let me already give you some basic ideas:

                            1. Use sensible data. Not just SLOC to measure “productivity,” but also budget estimates, man-hours per month, commit logs, bug reports, as much stuff you can find.
                            2. Use basic research tools. Check whether your data makes sense and filter outliers. Gather groups of similar projects and compare them.
                            3. Use known benchmarks in your advantage. What are known failure rates, how can these be influenced? When is a project even considered a success?
                            4. Know about “time compression” and “operational cost tsunamis”: these are phenomena such as an increase in the total cost by “death march” projects, and how operational costs are incurred already during development.
                            5. Know about quality of estimates, and estimates of quality and how these can improve over time. Estimates of the kind “this is what my boss wants to hear” are harmful. Being honest about total costs allows you to manage expectations: some ideas (lets build a fault-tolerant and distributed, scalable and adaptable X) are more expensive than others (use PHP and MySQL to build simple prototype for X).
                            6. Work together with others in business. Why does another department need X? What is the reason for deadline X? What can we deliver and how to decrease cost, so we can develop oportunity X or research Y instead?
                            7. Optimize on the portfolio level. Why does my organization have eight different cloud providers? Why does every department build its own tools to do X? What are strategic decisions and what are operational decisions? How can I convince others of doing X instead? What is organizational knowledge? What are the risks involved when merging projects?

                            Finally, I became convinced that for most organizations software development is a huge liability. But, as a famous theoretical computer scientist said back in the days: we have to overcome this huge barrier, because without software some things are simply impossible to do. So keep making the trade off: how much are you willing to lose, with the slight chance of high rewards?

                            1. 2

                              Any books you want to recommend?

                              1. 1

                                I’m also interested in that but online articles instead of books. The very nature of empiricism is to keep looking for more resources or angles as new work might catch what others miss. Might as well apply it to itself in terms of what methods/practices to use for empirical investigation. Let get meta with it. :)

                            1. 1

                              Oh yeah, @hwayne, the other thing I was going to tell you in support of empirical investigation is we already have a group doing it with over a hundred million in funding. That’s the Software Engineering Institute. Hard to say how much high-impact work they’ve done, truth they’ve discovered, or brilliant methods they’ve invented. There was so much BS coming out of them that I mostly stopped following. They do good stuff, too, though. If anything, they seem to ride waves of real innovators or on verification/testing be behind groups with less funding. Might say something about using empirical investigation alone if that’s what they’re doing. I know there would be argument about that.

                              However, that organization would be a good start on trying to get empirical projects done or funded if their politics don’t get in the way. Attention to those projects over others might increase funding for it over time. The money is not a problem for sure. :)

                              1. 5

                                It seems odd to spend so much space discussing the complexities of software development, only to conclude that the answer is empiricism. Surely the number of variables and their non-linear effects make experimentation difficult. I think $10M is an extremely tiny fraction of what a reproducible experiment would cost, and it would take a long time to run. You need a huge scale in number of projects and also lengthy longitudinal studies of their long-term impacts. And after you did all that the gigantic experiment would be practically certain to perturb what it’s trying to measure: programmer behavior. Because no two projects I’m on get the same me. I change, mostly by accumulating scar tissue.

                                Empiricism works in a tiny subset of situations where the variables have been first cleaned up into orthogonal components. I think in this case we have to wait for the right perspective to find us. We can’t just throw money at the problem.

                                1. 5

                                  What else can we do? Our reason is fallible, our experiences are deceitful, and we can’t just throw our hands up and say “we’ll never know”. Empiricism is hard and expensive, but at least we know it works. It’s gotten us results about things like n-version programming and COCOMO and TDD and formal methods. What would you propose we do instead?

                                  1. 4

                                    Empiricism is by no means the only thing that works. Other things that work: case studies, taxonomies, trial and error with motivation and perseverance. Other things, I’m sure. All of these things work some of the time – including empiricism. It’s not like there’s some excluded middle between alchemy and science. Seriously, check out that link in my comment above.

                                    I’m skeptical that we have empirically sound results about any of the things you mentioned, particularly TDD and formal methods. Pointers? For formal methods I find some of @nickpsecurity’s links kinda persuasive. On some mornings. But those are usually case studies.

                                    Questions like “static or dynamic typing” are deep in not-even-wrong territory. Using empiricism to try to answer them is like a blind man in a dark room looking for a black cat that isn’t there.

                                    Even “programming” as a field of endeavor strikes me as a false category. Try to understand that domain you’re interested in well enough to automate it. Try a few times and you’ll get better at it – in this one domain. Leave the task of generalization across domains to future generations. Maybe we’ll eventually find that some orthogonal axis of generalization works much better. Programming in domain X is like ___ in domain X more than it is like programming in domain Y.

                                    You ask “what else is there?” I respond in the spirit of Sherlock Holmes: “when you have excluded the impossible, whatever is left, however unlikely, is closer to the answer.” So focus on your core idea that the number of variables is huge, and loosen your grip on empiricism. See where that leads you.

                                    1. 5

                                      I think we’re actually on the same page here. I consider taxonomies, ethnographies, case studies, histories, and even surveys as empirical. It’s not just double blind clinical studies: as Making Software put it, qualitative findings are just as important.

                                      I reject the idea that these kinds of questions are “not even wrong”, though. There’s no reason to think programming is any more special than the rest of human knowledge.

                                      1. 2

                                        Ah ok. If by empiricism you mean, “try to observe what works and do more of that”, sure. But does that really seem worth saying?

                                        It can be hard psychologically to describe a problem well in an article and then not suggest a solution. But sometimes that may be the best we can do.

                                        I agree that programming is not any more special than the rest of human knowledge. That’s why I claim these questions are not even wrong. Future generations will say, “sure static typing is better than dynamic typing by about 0.0001% on average, but why did the ancients spend so much time on that?” Consider how we consider ancient philosophers who worried at silly questions like whether truth comes from reason or the senses.

                                        Basically no field of human endeavor had discovered the important questions to ask in its first century of existence. We should spend more time doing and finding new questions to ask, and less time trying to generalize the narrow answers we discover.

                                        1. 3

                                          Ah ok. If by empiricism you mean, “try to observe what works and do more of that”, sure. But does that really seem worth saying?

                                          It’s not quite that. It’s all about learning the values and limitations of all the forms of knowledge-collection. What it means to do a case study and how that differs from a controlled study, where ethnographies are useful, etc. It’s not “observe what works and do more of that”, it’s “systematically collect information on what works and understand how we collect and interpret it.”

                                          Critically in that is that the information we collect by using “reason” alone is minimal and often faulty, but it’s how almost everybody interprets software. That and appealing to authority, really.

                                          Basically no field of human endeavor had discovered the important questions to ask in its first century of existence. We should spend more time doing and finding new questions to ask, and less time trying to generalize the narrow answers we discover.

                                          The difference is that we’ve already given software control over the whole world. Everything is managed with software. It guides our flights and runs our power grid. Algorithms decide whether people go to jail or go free. Sure, maybe code will look radically different in a hundred years, but right now it’s here and present and we have to understand it.

                                          1. 2

                                            It is fascinating that we care about the same long-term problem but prioritize sub-goals so differently. Can you give an example of a more important question than static vs dynamic typing that you want to help answer by systematically collecting more information?

                                            Yes, we have to deal with the code that’s here and present. My answer is to reduce scale rather than increase it. Don’t try to get better at running large software projects. Run more small projects; those are non-linearly more tractable. Gradually reduce the amount of code we rely on, and encourage more people to understand the code that’s left. A great example is the OpenBSD team’s response to Heartbleed. That seems far more direct an attack on existing problems than any experiments I can think of. Experiments seem insufficiently urgent, because they grow non-linearly more intractable with scale, while small-scale experiments don’t buy you much: if you don’t control for all variables you’re still stuck using “reason”.

                                            1. 2

                                              Can you give an example of a more important question than static vs dynamic typing that you want to help answer by systematically collecting more information?

                                              Sure. Just off the top of my head:

                                              • How much does planning ahead improve error rate? What impacts, if any, does agile have?
                                              • What are the main causes of cascading critical failures in systems, and what can we do about them?
                                              • When it comes to maximizing correctness, how much do intrinsic language features matter vs processes?
                                              • I don’t like pair programming. Should I be doing it anyway?
                                              • How do we audit ML code?
                                              • How much do comments help? How much does documentation help?
                                              • Is goto actually harmful?

                                              Obviously each of these have ambiguity and plenty of subquestions in them. The important thing is to consider them things we can investigate, and that investigating them is important.

                                              1. 0

                                                Faced with Cthulhu, you’re trying to measure how the tips of His tentacles move. But sometimes you’re conflating multiple tentacles! Fthagn!

                                                1. 1

                                                  As if you can measure tentacles in non-Euclidean space without going mad…

                                                  1. 1

                                                    Now you’re just being rude. I made a good faith effort to answer all of your questions and you keep condescending to me and insulting me. I respect that you disagree with me, but you don’t have to be an asshole about it.

                                                    1. 2

                                                      Not my intention at all! I’ll have to think about why this allegory came across as rude. (I was more worried about skirting the edge when I said, “is that really worth talking about?”) I think you’re misguided, but I’m also aware that I’m pushing the less likely theory. It’s been fun chatting with you precisely because you’re trying to steelman conventional wisdom (relative to my more outre idea), and I find a lot to agree with. Under it all I’ve been hoping that somebody will convince me to return to the herd so I can stop wasting my life. Anyway, I’ll stop bothering you. Thanks for the post and the stimulating conversation.

                                            2. 2

                                              “try to observe what works and do more of that”

                                              That is worth saying, because it can easily get lost when you’re in the trenches at your job, and can be easy to forget.

                                        2. 2

                                          What else can we do?

                                          If describing in terms of philosophies, then there’s also reductionism and logic. The hardware field turning analog into digital lego’s and Oberon/Forth/Simula for software come to mind for that. Maybe model-driven engineering. They break software into fundamental primitives that are well-understood which then compose into more complex things. This knocks out tons of problems but not all.

                                          Then, there’s logical school that I’m always posting about as akkartik said where you encode what you want, the success/failure conditions, how you’re achieving them, and prove you are. Memory safety, basic forms of concurrency safety, and type systems in general can be done this way. Two of those have eliminated entire classes of defects in enterprise and FOSS software using such languages. CVE list indicates the trial-and-error approach didn’t works as well. ;) Failure detection/recovery algorithms, done as protocols, can be used to maintain reliability in all kinds of problematic systems. Model-checking and proof has been most cost-effective in finding protocol errors, esp deep ones. Everything being done with formal methods also falls into this category. Just highlighting high impact stuff. Meyer’s Eiffel Method might be said to combine reductionism (language design/style) and logic (contracts). Cleanroom, too. Experimental evidence from case studies showed Cleanroom was very low defect, even on first use by amateurs.

                                          Googled a list of philosophies. Let’s see. There’s the capitalism school that says the bugs are OK if profitable. The existentialists say it only matters if you think it does. The phenomenologists say it’s more about how you perceived the failure from the color of the screen to the smell of the fire in the datacenter. The emergentists say throw college grads at the problem until something comes out of it. The theologists might say God blessed their OS to be perfect with criticism not allowed. The skeptics are increasingly skeptical of the value of this comment. The… I wonder if it’s useful to look at it in light of philosophy at all given where this is going so far. ;)

                                          I look at it like this. We have most of what we want out of a combo of intuition, trial-and-error, logic, and peer review. This is a combo of individuals’ irrational activities with rational activity on generating and review side of ideas. I say apply it all with empirical techniques used to basically just catch nonsense from errors, bias, deception, etc. The important thing for me is whether something is working for what problems at what effort. If it works, I don’t care at all whether there’s studies about it with enough statistical algorithms or jargon used in them. However, at least how they’re tested and vetted… the evidence they work… should have rigor of some kind. I also prefer ideological diversity and financial independence in reviewers to reduce collusion problem science doesn’t address enough. A perfectly-empirical study with 100,000+ data points refusing my logic that Windows is insecure is less trustworthy when the people who wrote it are Microsoft employees wanting a NDA for the data they used, eh?

                                          I’ll throw out another example that illustrates it nicely: CompCert. That compiler is an outlier where it proves little to nothing about formal verification in general most empiricists might tell you. Partly true. Skepticism’s followers might add we can’t prove that this problem and only this problem was the one they could express correctly with logic if they weren’t misguided or lying to begin with. ;) Well, they use logical school of specifying stuff they prove is true. We know from testing vs formal verification analysis that testing or trial-and-error can’t ensure the invariants due to state space exploration. Even that is a mathematical/logical claim because otherwise you gotta test it haha. The prior work with many formal methods indicate they reduce defects a lot in a wide range of software at high cost with simplicity of software required. Those generalizations have evidence. The logical methods seem to work within some constraints. CompCert pushes those methods into new territory in specification but reuses logical system that worked before. Can we trust claim? Csmith throws CPU years of testing against it and other compilers. Its defect rate bottoms out, mainly spec errors, unlike about any compiler ever tested that I’ve seen in the literature. That matches prediction of logical side where errors in proven components about what’s proven should be rare to nonexistent.

                                          So, the empirical methods prove certain logical systems work in specific ways like ensuring proof is at least as good as the specs. We should be able to reuse logical systems proven to work to do what they’re proven to be good at. We can put less testing into components developed that way when resources are constrained. Each time something truly new is done like that we review and test the heck out of it. Otherwise, we leverage it since things that logically work for all inputs to do specific things will work for the next input with high confidence since we vetted the logical system itself already. Logically or empirically, we can therefore trust methods ground in logic as another tool. Composable, black boxes connected in logical ways plus rigorous testing/analysis of the box and composition methods are main ways I advocate doing both programming and verification. You can keep applying those concepts over and over regardless of tools or paradigms you’re using. Well, so far in what I’ve seen anyway…

                                          @derek-jones, tag you’re it! Or, I figure you might have some input on this topic as a devout empiricist. :)

                                          1. 2

                                            Googled a list of philosophies. Let’s see. There’s the capitalism school that says the bugs are OK if profitable. The existentialists say it only matters if you think it does. The phenomenologists say it’s more about how you perceived the failure from the color of the screen to the smell of the fire in the datacenter. The emergentists say throw college grads at the problem until something comes out of it. The theologists might say God blessed their OS to be perfect with criticism not allowed. The skeptics are increasingly skeptical of the value of this comment. The… I wonder if it’s useful to look at it in light of philosophy at all given where this is going so far. ;)

                                            Awesome, hilarious paragraph.

                                            We have most of what we want out of a combo of intuition, trial-and-error, logic, and peer review. This is a combo of individuals’ irrational activities with rational activity on generating and review side of ideas. I say apply it all with empirical techniques used to basically just catch nonsense from errors, bias, deception, etc. The important thing for me is whether something is working for what problems at what effort. If it works, I don’t care at all whether there’s studies about it with enough statistical algorithms or jargon used in them.

                                            Yes, totally agreed.

                                          2. 2

                                            What else can we do? Our reason is fallible, our experiences are deceitful, and we can’t just throw our hands up and say “we’ll never know”.

                                            Why not? The only place these arguments are questioned or really matter is when it comes to making money and software has ridiculous margins, so maybe it’s just fine not knowing. I know high-risk activities like writing airplane and spaceship code matter, but those folks seem to not really have much contention about about if their methods work. It’s us folks writing irrelevant web services that get all uppity about these things.

                                        1. 1

                                          My Brute-Force Assurance concept relies on combining meta transformations with piles of checks, tests, etc. I just found and skimmed this work which was an interesting outlier in methods used. I thought it was impressive their first project with the technique hit that number of bugs with so little effort. This is 2000. I wonder if any more research was done on this. I go through so much research that I probably won’t remember even if I’ve already seen it. I didn’t see the MC term in combo with results, though. It’s new to me.

                                          1. 3

                                            A while back, @mbrock told me to check out this trio that might be used in combination: QuickCheck, QuickSpec, and HipSpec. HipSpec Github is here. I still have some stashed submissions on invariants and automated formal methods I’ll be posting, too, over next few weeks.

                                            1. 4

                                              https://hackage.haskell.org/package/fitspec is also really cool. It’s mutation testing of properties. Ensures you have minimal properties!

                                              1. 1

                                                Thanks for the link. Sounds good.

                                            1. 1

                                              It’s problems in the code that build up over time which slow development pace, reduce flexibility, increase costs, and can negatively impact reliability/performance/security. So, what phrase do we call that if replacing technical debt?

                                                1. 2

                                                  Oh yeah, that simplifies the heck out of it, doesnt it? Was more accurate.

                                              1. 22

                                                This article is great except for No 3: learning how hardware works. C will teach you how PDP-11 hardware works with some extensions, but not modern hardware. They have different models. The article then mentions computer architecture and assembly are things they teach students. Those plus online articles with examples on specific topics will teach the hardware. So, they’re already doing the right thing even if maybe saying the wrong thing in No. 3.

                                                Maybe one other modification. There’s quite a lot of tools, esp reimplementations or clones, written in non-C languages. Trend started getting big with Java and .NET with things like Rust and Go making some more waves. There’s also a tendency to write things in themselves. I bring it up because even the Python example isn’t true if you use a Python written in Python, recent interpreter tutorials in Go language, or something like that. You can benefit from understanding the implementation language and/or debugger of whatever you’re using in some situations. That’s not always C, though.

                                                1. 14

                                                  Agreed. I’ll add that even C’s status as a lingua franca is largely due to the omnipresence of unix, unix-derived, and posix-influenced operating systems. That is, understanding C is still necessary to, for example, link non-ruby extensions to ruby code. That wouldn’t be the case if VMS had ended up dominant, or lisp machines.

                                                  In that way, C is important to study for historical context. Personally, I’d try to find a series of exercises to demonstrate how much different current computer architecture is from what C assumes, and use that as a jumping point to discuss how relevant C’s semantic model is today, and what tradeoffs were made. That could spin out either to designing a language which maps to today’s hardware more completely and correctly, or to discussions of modern optimizing compilers and how far abstracted a language can become and still compile to efficient code.

                                                  A final note: no language “helps you think like a computer”. Our rich history shows that we teach computers how to think, and there’s remarkable flexibility there. Even at the low levels of memory, we’ve seen binary, ternary, binary-coded-decimal, and I’m sure other approaches, all within the first couple decades of computers’ existence. Phrasing it as the original author did implies a limited understanding of what computers can do.

                                                  1. 8

                                                    C will teach you how PDP-11 hardware works with some extensions, but not modern hardware. They have different models.

                                                    I keep hearing this meme, but pdp11 hardware is similar enough to modern hardware in every way that C exposes. Except, arguably, with the exception of NUMA and inter-processor effects.

                                                    1. 10

                                                      You just countered it yourself even with that given prevalence of multicores and multiprocessors. Then there’s cache hierarchies, SIMD, maybe alignment differences (memory is fuzzy), effects of security features, and so on.

                                                      They’d be better of just reading on modern, computer hardware and ways of using it properly.

                                                      1. 6

                                                        Given that none of these are represented directly in assembly, would you also say that the assembly model is a poor fit for modeling modern assembly?

                                                        I mean, it’s a good argument to make, but the attempts to make assembly model the hardware more closely seem to be vaporware so far.

                                                        1. 6

                                                          Hmm. They’re represented more directly than with C given there’s no translation to be done to the ISA. Some like SIMD, atomics, etc will be actual instructions on specific architectures. So, Id say learning hardware and ASM is still better than learning C if wanting to know what resulting ASM is doing on that hardware. Im leaning toward yes.

                                                          There is some discrepency between assembly and hardware on highly-complex architectures, though. The RISC’s and microcontrollers will have less, though.

                                                      2. 1

                                                        Not helped by the C/Unix paradigm switching us from “feature-rich interconnected systems” like in the 1960s to “fast, dumb, and cheap” CPUs of today.

                                                      3. 2

                                                        I really don’t see how C is supposed to teach me how PDP-11 hardware works. C is my primary programming language and I have nearly no knowledge about PDP-11, so I don’t see what you mean. The way I see it is that the C standard is just a contract between language implementors and language users; it has no assumptions about the hardware. The C abstract machine is sufficiently abstract to implement it as a software-level interpreter.

                                                        1. 1

                                                          As in this video of its history, the C language was designed specifically for the hardware it ran on due to its extremely-limited resources. It was based heavily on BCPL, which invented “programmer is in control,” that was what features of ALGOL could compile on another limited machine called an EDSAC. Even being byte-oriented versus word-oriented was due to PDP-7 being byte-oriented vs EDSAC that allowed word-oriented. After a lot of software was written in it, two things happened:

                                                          (a) Specific hardware implementations tried to be compatible to it in stack or memory models so that program’s written for C’s abstract machine would go fast. Although possibly good for PDP-11 hardware, this compatibility would mean many missed opportunities for both safety/security and optimization as hardware improved. These things, though, are what you might learn about hardware studying C.

                                                          (b) Hardware vendors competing with each other on performance, concurrency, energy usage, and security both extended their architectures and made them more heterogenous than before. The C model didn’t just diverge from these: new languages were invented (esp in HPC) so programmers could easily use them via something that gives a mental model closer to what hardware does. The default was hand-coded assembly that got called in C or Fortran apps, though. Yes, HPC often used Fortran since it’s model gave them better performance than C’s on numerical applications even on hardware designed for C’s abstract machine. Even though easy on hardware, the C model introduced too much uncertainty about programmers’ intent for compilers to optimize those routines.

                                                          For this reason, it’s better to just study hardware to learn hardware. Plus, the various languages either designed for max use of that hardware or that the hardware itself is designed for. C language is an option for the latter.

                                                          “ it has no assumptions about the hardware”

                                                          It assumes the hardware will give people direct control over pointers and memory in ways that can break programs. Recent work tries to fix the damage that came from keeping the PDP-11 model all this time. There were also languages that handled them safely by default unless told otherwise using overflow or bounds checks. SPARK eliminated them for most of its code with compiler substituting pointers in where it’s safe to do so. It’s also harder in general to make C programs enforce POLA with hardware or OS mechanisms versus a language with that generated for you or having true macros to hide boilerplate.

                                                          “ The C abstract machine is sufficiently abstract to implement it as a software-level interpreter.”

                                                          You can implement any piece of hardware as a software-level interpreter. It’s just slower. Simulation is also a standard part of hardware development. I don’t think whether it can be interpreted matters. Question is: how much does it match what people are doing with hardware vs just studying hardware, assembly for that hardware, or other languages designed for that hardware?

                                                          1. 3

                                                            I admit that the history of C and also history of implementations of C do give some insight into computers and how they’ve evolved into what we have now. I do agree that hardware, operating systems and the language have been all evolving at the same time and have made impact on each other. That’s not what I’m disagreeing with.

                                                            I don’t see a hint of proof that knowledge about the C programming language (as defined by its current standard) gives you any knowledge about any kind of hardware. In other words, I don’t believe you can learn anything practical about hardware just from learning C.

                                                            To extend what I’ve already said, the C abstract machine is sufficiently abstract to implement it as a software interpreter and it matters since it proves that C draws clear boundaries between expected behavior and implementation details, which include how a certain piece of hardware might behave. It does impose constraints on all compliant implementations, but that tells you nothing about what “runs under the hood” when you run things on your computer; an implementation might be a typical, bare-bones PC, or a simulated piece of hardware, or a human brain. So the fact that one can simulate hardware is not relevant to the fact, that you still can’t draw practical assumptions about its behavior just from knowing C. The C abstract machine is neither hardware nor software.

                                                            Question is: how much does it match what people are doing with hardware vs just studying hardware, assembly for that hardware, or other languages designed for that hardware?

                                                            What people do with hardware is directly related to knowledge about that particular piece of hardware, the language implementation they’re using, and so on. That doesn’t prove that C helps you understand that or any other piece of hardware. For example, people do study assembly generated by their gcc running on Linux to think about what their Intel CPU will do, but that kind of knowledge doesn’t come from knowing C - it comes from observing and analyzing behavior of that particular implementation directly and behavior of that particular piece of hardware indirectly (since modern compilers have to have knowledge about it, to some extent). The most you can do is try and determine whether the generated code is in accordance with the chosen standard.

                                                            1. 1

                                                              In that case, it seems we mostly agree about its connection to learning hardware. Thanjs for elaborating.

                                                      1. 16

                                                        The click-bait title is not really backed up in any way in the content. The conclusion doesn’t even bring up company death. All-in-all, a rehash of the existing knowledge and statements around technical debt.

                                                        1. 3

                                                          Moreover, the fact that almost all of the most successful, rich companies have a pile of technical debt… some maybe inescapable… refutes the title so thoroughly that it almost seems more natural to ask if technical debt is a positive sign of success.

                                                          Im not saying it is so much as looking only at correlations between companies that last and amount of technical debt would make it look positive by default.

                                                          1. 4

                                                            I tend to view that as “Stagger onwards despite the mountain of technical debt, because the prime drivers in our current economy are not efficiency or competence of engineering”.

                                                          2. 1

                                                            I’m sorry if the content of my post wasn’t explicit enough. The 4 areas of technical debt I analyse give my idea of how they lead to the corrosion of the engineering organization and the company:

                                                            • Lack of shared understanding on the functionality of the product (leading to waste of effort and disruption of service)
                                                            • Inability to scale and loss of agility in respect to the competing organizations
                                                            • Inability to react to failures and learn from how the product is used by your clients
                                                            • Inability to scale your engineering team

                                                            My bad if the above points haven’t been clear enough from my post. Thanks for your feedback, really appreciated!

                                                            1. 2

                                                              No, I got those points out of it, but you didn’t link that to company death in anyway. I’ve not done a study but of the successful companies I’ve worked at, tech debt is pervasive, depending on the area.

                                                              Also, and this point as more to do with me than you so I don’t hold it against you, I’m sick of these articles that of the form:

                                                              Observation -> Logical Assumptions Based On Observation -> Conclusion

                                                              There is no empiricism in there at all. So does tech debt make it harder to scale your engineering team? Maybe! But you’ve just presented some nice sounding arguments rather than any concrete evidence. It’s easy to say “here’s a a bad thing and here are the bad things I would assume happen because of it” but that’s a long ways away from “here’s a bad thing and here is the concrete evidence of outputs because of it”.

                                                          1. 1

                                                            Highlight worth quoting in the future:

                                                            “The value of a language that strongly enforces a paradigm is that it immerses you in that approach to solving problems. The more it enforces the paradigm, the more you are forced to attempt solutions using that paradigm. The more functional your language, the more training you get in approaching problems in a functional way. The same goes for OOP and Procedural. In essence, you get more practice because you can’t rely on the other paradigms you already know.”

                                                            Emphasis added. The precedent for this is immersion training for learning languages versus learning specific features one by one. The latter would be like an English-speaking person learning Spanish who just tries new words or grammar rules on a Spanish-speaking friend who is fluent. Certainly that person could learn more use of Spanish over time. The fluent speaker, though, probably got that way through an immersive learning experience that surrounded them with the language, forced them to use it to get basic things done, and gave many more opportunities for optional use. This gave them a level of understanding and utility that the piecemeal, opportunistic approach could [probably] never match.

                                                            When I last looked, most of the old arguments and newer research suggested our brains handle programming much like they handle language comprehension in general. Combined with positive results from immersion training, that corroborates the author’s claim that immersion in different programming paradigms is the best way to learn to read, write, and speak them. Almost all anecdotal evidence I read from people learning other paradigms confirms this: they say it changed how they thought about solving programming problems regardless of whether they’d adopt the paradigm-focused language in practice. They almost always believed it had value for them with many producing code examples showing how certain problems were expressed in objectively-better ways in some paradigms than others.

                                                            1. 6

                                                              we don’t hire junior developers because we can’t afford to have our senior developers mentor them

                                                              That’s not why we don’t do it: our issue is that junior developers simply aren’t productive enough to warrant the expense.

                                                              1. 16

                                                                The other consideration is; expend resources (ie seniors time) training entry level, only to see them leave in a year or two for large pay raises. It’s nearly impossible for business leaders to understand that 100% pay increases are required after a couple of years in this field.

                                                                1. 4

                                                                  So how does one break the cycle? Junior developers will have to learn somewhere. Are we in a situation similar to the video game industry, where we actually have too many programmers on the market?

                                                                  You can certainly learn a lot outside of work, but there are a lot of things that are best learned on a job.

                                                                  1. 4

                                                                    where we actually have too many programmers on the market?

                                                                    Yes. Absolutely. And every programmer is a special snowflake which makes it impossible for anyone except another programmer to read their CV.

                                                                    1. 0

                                                                      The fact that pay is high is probably an indicator that that isn’t true.

                                                                      1. 2

                                                                        Pay is high in some areas. It’s crap in others. It’s mediocre in others. I think it says more about the practices of businesses in a given industry and geographical area than anything else.

                                                                        1. 2

                                                                          Adjusted for that it’s nearly double the median wage. I would say there are not too many developers.

                                                                          1. 2

                                                                            Depends on the area. In the Mid-South, there’s plenty of IT people, including programmers, making $12-15 an hour. Minimum wage is just over $7. We obviously have many move from this area but steady stream to fill those positions from colleges. Things that vary this much by area I usually talk about in terms of the area. Otherwise, the generalizations can be meaningless.

                                                                            Except for when you say there aren’t too many developers. I agree with that if we factor in skill or tech they know about. There’s just not so many companies wanting to invest in junior ones or pay senior ones well.

                                                                            1. 5

                                                                              As a southerner I can anecdotally say that’s caused by a lack of labor organization and not a glut of programmers. Low willingness to pay is because they’re hoping to pick up someone who is willing to work for peanuts, not because there are too many developers. In fact they frequently take on business impact because of unfilled positions.

                                                                              1. 1

                                                                                That makes sense to me as well (having worked in those sorts of jobs during college in the south and southeast)

                                                                                1. 1

                                                                                  That sounds about right. You bet I call them out for it, too, if they get high and mighty with the politics. ;)

                                                                  1. 2

                                                                    The funny thing for me is that I dont even use the one that awed me most: LISP with unprecedented flexibility, incremental compilation per function, and live updates. It’s like one could do regular coding about as fast as they think with resultimg code runnimg way faster than scripting languages. Too weird to fully embrace with the BASIC and Pascal-style languages compiling super-fast, too. So I just used their implementations where possible.

                                                                    I still plan to have another go at trying to fully get the LISP’s or FP. Probably Racket for the DSL’s.

                                                                    1. 1

                                                                      Do Lisps try to only load the functions that have changed? I wondered how they managed to be a step beyond typical REPL workflows.

                                                                      1. 3

                                                                        Not in the way I think you mean, as an incremental-compilation system. That should be possible to build, but none of the commonly used ones that I can think of are actually built that way.

                                                                        There is at least more attention to being explicit about the relationship between the currently running image and the (possibly changed) source code though. As a very simple example, there are two Common Lisp forms that introduce global variables: defvar introduces a variable and assigns a default value to it only if it was not already introduced, while defparameter is the same but initializes it unconditionally. So if you reload a file with a defvar it will just silently note the declaration of an existing variable but not clobber it, while a defparameter will deliberately clobber it.

                                                                        As another example, the Common Lisp equivalent of exceptions, the condition system, is entirely designed around the idea that you might want to fix an exception by reloading or redefining something, but only lazily once you’ve noticed it failed. That allows for all kinds of workflows that are odd by the standards of other languages, based around what ‘restart’ you choose from a condition (either manually or automatically). The differences are substantial, but the first difference a programmer will normally notice is telling in itself: when a Java program throws an uncaught exception, it terminates with a stacktrace, but when Common Lisp raises an uncaught condition, it pauses and displays a multiple-choice menu asking the user which restart to take.

                                                                        1. 1

                                                                          The environment I had came with a REPL to interpret functions, a total compile, and an incremental compile. The first two worked about like you’d expect I guess. The REPL skipped compile step but maybe ran slower. Been a while so I can’t remember. That’s usually the case for REPL’s, though. The compiler took longer but the resulting code ran really fast. The cool part was incremental compile where I could change the definition of one function, hit a particular key combo, it would compile just that one function, and it would load it into live image for immediate testing.

                                                                          The incremental compiles took a fraction of a second. The first compile might take longer, esp if you’ve been REPLing or are adding optional types. From there, it’s a quick compile per new module or function change that takes no time at all. That let me no need to use REPL for iterations given I could get highly-optimized code without a long wait that would break my flow. From then on, both incremental compiles and live image are features I’d request for any language.

                                                                          Being able to save the running state of one was cool, too, for when you trusted it up to a certain point with certain data/state in it but then wanted to test a lot of behaviors. It was to exploratory testing what a NES emulator with save/reload is to speedruns. ;) I bet it could be even more useful in mocking up and testing algorithms for distributed systems.