Micrashell – A suit that allows you to safely socialize - <AUTHOR> https://production.club/micrashell <comment> jim-jim-jim Posted this the other day. Didn't generate any discussion then, but it's perfectly relevant to this thread:

[https://mcmansionhell.com/post/618938984050147328/coronagrif...](https://mcmansionhell.com/post/618938984050147328/coronagrifting- a-design-phenomenon)

<comment><AUTHOR> oh, hm - searched before i posted ¯\\_(ツ)_/¯

not far off this one i posted too - [https://news.ycombinator.com/item?id=23221343](https://news.ycombinator.com/item?id=23221343)

</comment></comment><comment><AUTHOR> _Specifically designed to satisfy the needs of nightlife, live events and entertainment industries, Micrashell is a virus-shielded, easy to control, fun to wear, disinfectable, fast to deploy personal protective equipment (PPE) that allows socializing without distancing._

 _Air-tight top suit + hybrid soft+hard helmet made of tactical, high performance cut resistant fabric and developed for durability, endurance and easy disinfecting procedures. Main materials based on UHMWPE fabrics and lightweight film composite, including sealed sewed patterns and ornaments as well as cordura inserts. This offshoot of a hazmat suit contains two lithium- ion cell battery systems for uninterrupted active operation and are easy charge and swap when discharged (18650 type batteries)._

What this needs is a hardwired telecom connection with noise-canceling earpiece and mic. You complete the circuit by physical contact, hand on shoulder, arm, literal handshake, etc.</comment>


Freelancer giving free hours for good ideas - <AUTHOR> http://blog.samuellevy.com/post/36-i-will-give-you-25-hours-of-free-work.htm Whoops! proper link is http://blog.samuellevy.com/post/36-i-will-give-you-25-hours-of-free-work.html<p>I missed the "l" :( <comment><AUTHOR> Whoops! proper link is [http://blog.samuellevy.com/post/36-i-will-give- you-25-hours-...](http://blog.samuellevy.com/post/36-i-will-give-you-25-hours- of-free-work.html)

I missed the "l" :(

Could a mod update it?

<comment><USER2> Hiya, this is my site. I noticed the spike in traffic (I tend to watch analytics when I'm bored. I don't have a problem)

I updated the code so it will respond to both htm and html.</comment></comment>


40K Ferrite core for sale (auction closed) - <AUTHOR> http://cgi.ebay.com/Vintage-40K-FERRITE-COMPUTER-MEMORY-CORE-20-Plane-Stack_W0QQitemZ330282554507QQcmdZViewItem

<comment><USER2> We've got a 64K-word TX-2 core memory on display at the MIT Museum. [update - here's a link <http://tinyurl.com/5mve8b>]

Back in 1975/6 I was using a DEC LSI-11 that had core memory. I forget how much but it was enough to run FORTRAN.

</comment><comment><USER3> Nerd porn!

Interesting side note: the term "core dump" came from this sort of memory: <http://en.wikipedia.org/wiki/Core_dump></comment>


What are potential disadvantages of functional programming? - <AUTHOR> https://www.reddit.com/r/compsci/comments/6pnq7e/what_are_potential_disadvantages_of_functional/ <comment><USER2> Biggest disadvantage for me comes when trying to implement a complex algorithm where the paper uses pseudocode that's imperative (which is almost always). In the best case you can implement parts of it functionally but when it comes time to put these together you will likely use some kind of loop, but that's not possible in "purely" functional languages.

Otherwise -- and in particular when coming up with algorithms -- I find it preferable for languages to be efficient with functional idioms (recursion, map, filter, etc.).

Edit: I understand that anything's possible in a functional language that's possible in other languages. My point is that conversion from imperative to functional can be complex and might not be worth the trouble, and that doing it purely functionally might defeat the purpose: it will be nearly impossible to read or incredibly inefficient.

<comment><USER3> If what you care about is "everything is a beautifully curried function that actually doesn't do anything", the concern about loops is definitely a thing (but any loop can be turned into a recursive function so long as your stack is big enough, even if they're usually hideous). But pretty much everybody I've ever worked with considers functional purity in the logic layer to be "functional programming" at its most useful (Gary Berhardt's functional-core, imperative-shell talk is a good one). Is it easier to write with a loop? _Then use a loop!_ If that loop is contained in a pure function that has no side effects and encapsulates something that isn't the most beautiful crystalline code formation anybody ever did see, _nobody cares_.

It's the mindset, not the implementation, that actually makes functional programming so valuable a tool.

<comment><USER2> > Is it easier to write with a loop? Then use a loop!

Yes, but, say, in Haskell, that's not an option.

It's useful to note that Haskell is usually touted as efficient, and lack of efficiency is a #1 concern around functional programming. That concern I personally find revolting: Haskell is slower than C, yes, but orders of magnitude faster than many widely used languages.

<comment><USER4> > Yes, but, say, in Haskell, that's not an option.

        forM_ [1, 2, 3, 4] $ \n ->
            print n

</comment></comment></comment></comment><comment><USER5> One of my professors used to say that functional programming makes all problems equally hard. There's some truth to that. For example, for I/O, most functional languages fall back on imperative idioms. Those that don't (Haskell, mainly) basically tell beginners to pretend that this weird thing (I/O monad) is just an imperative code block. You can figure out how it works once you're more familiar with the language.

Since doing I/O is a pretty common task, functional languages generally include imperative constructs to fix this, but these constructs generally feel tacked on.

The main drawback I see in practice is that functional programming can encourage people to be more clever than they ought to be. In the worst case, you can get some of the worst Java-like issues, where there's a function that returns a function that returns another function that actually does what you want, even if it's only used in two places anyway. In a more typical case, you'll get someone who likes to unnecessarily write everything in continuation-passing style, or jumps through hoops to move recursive calls into tail position even though the recursive depth never exceeds 5.

If the team has the discipline to just avoid that kind of thing, the only real downside I see is being farther from the hardware.

<comment><USER6> People can shoot themselves in the foot with practically any language and framework. I'd be hard-pressed to call that a FP-specific problem.

When I am writing Elixir, all the lessons I learned from Martin Fowler and Kent Beck on refactoring became 50x more useful; I don't go 5 levels deep into making my code uber clever. I recognize these 5 levels but I only do 1 level and stop there.

It's very important to get clever only when there is a valid reason to do so. Many colleagues very easily forget that this is a job and you shouldn't get carried away; do what you must, do it very well so that your future self doesn't hate you -- but don't try to do it as if your code is gonna persist for a millennia on a space probe.

</comment></comment><comment><USER7> Inability to practice hardware sympathy is the biggest drawback for me. With imperative code, my intuition can be useful in estimating what instructions the compiler is likely to generate (what loops get unrolled, how registers get packed, etc). It's still not easy mind you, but with functional languages, the generated code goes through another battery of passes and abstractions that obscure this even more.

<comment><USER8> If you go deeper, then we start to see a lot of similarities. Functional programming strongly resembles circuit logic. Maybe a strange loop?

See also [http://www.clash-lang.org/](http://www.clash-lang.org/)

<comment><USER7> I've coded in vhdl and verilog. Working at the gate level is definitely more functional in nature and has the same problem (it's not obvious intuitive how the code you write maps to gate logic). Hence, why novices introduces accidental latches and metastability. I've actually used clash for one non- trivial project, and there's something interesting there for sure.

</comment></comment></comment><comment><USER9> I personally much prefer functional programming, however it has some downsides.

The biggest practical hindrances I have found are:

1\. Performance due to things like allocations due to immutability thrashing cache, or a language that allocates on calling into closures, or fails to inline them properly, can be significantly worse depending on the environment you are writing your code in.

2\. It's less common therefore there is a higher chance other programmers are going to struggle with your code, or that libraries aren't going to be as well supported.

Take lodash/fp for example. Vanilla lodash has really good @types support in something like Typescript. lodash/fp it's an open ticket (last I checked). This type of stuff happens a lot there just isn't the same number of folks writing code in fp style so you don't have the same level of long tail support.

3\. This is maybe a less common view but in an object oriented style with code-complete, usually discover-ability is better. Typically the IDE has a better context of what you could be doing when chain method calls with a . rather than having the whole world of methods at your disposal when going for a code complete. For example when writing "abc".r<TAB> compared to r<TAB> the IDE is going to have significantly narrowed down scope to suggest in (methods that are legal on string). This can be very useful and I suspect narrows the breadth of the space the programmer must conceptually keep in there head from token to token. It's big reason why things like extension methods, which really don't have to exist (they could easily just be static helper methods) are frequently a highly requested addition to a language.

4\. Somewhat related, and there are ways around this, I prefer a threaded / piping style as opposed to composing methods together. e.g. `(1 + 1) / 2` or `(->> 1, (+ 1), (/ 2))` as opposed to `(/ (+ 1 1) 2)` To me I feel the code reads better from left to right as opposed to inside-out. But that is possibly (probably?) a result of being an imperative programmer for so long before switching to functional programming. Also I feel like I am playing around with a lot more parens matching and jumping backwards for something like f(g(h(x))) as opposed to h(x).g().f(). Again this could be my imperative programming upbringing leaking through though.

<comment><USER10> Very much agree with your point 3. It's really a namespace issue with classes providing a natural division of the namespace. Also OO best practices over time have encouraged more modularization and encapsulation with heavier use of restricted visibility. At least in my experience functional code tends to pollute the global namespace with a bunch of not so obvious functions.

<comment><USER11> It depends on the language but you often have the option of grouping functions accepting a specific input type in a dedicated module, and using them qualified.

</comment></comment></comment><comment><USER12> It's surprising to me to see how few discussions of Functional and/or Object Oriented programming end up even mentioning the Expression Problem: [http://wiki.c2.com/?ExpressionProblem](http://wiki.c2.com/?ExpressionProblem)

        The expression problem is a new name for an old problem.
        The goal is to define a datatype by cases, where one can
        add new cases to the datatype and new functions over the
        datatype, without recompiling existing code, and while
        retaining static type safety (e.g., no casts).

FP and OOP are two axes in a space of problems around building and extending programs. To be "purely functional" or "strictly OO" is basically painting yourself into a corner that you will eventually learn to regret.

Eli Bendersky wrote an excellent piece on it: [http://eli.thegreenplace.net/2016/the-expression-problem- and...](http://eli.thegreenplace.net/2016/the-expression-problem-and-its- solutions/)

<comment><USER13> I was planning on mentioning it as soon as I saw this post as well. I think most people who try using a functional programming language that encourages you to use sum types (at least when you're beginning) run into this in some way, but most people probably aren't aware that it has an actual name.

Here's a post on solving it using type classes in Haskell, if people are curious! [http://koerbitz.me/posts/Solving-the-Expression-Problem- in-H...](http://koerbitz.me/posts/Solving-the-Expression-Problem-in-Haskell- and-Java.html)

<comment><USER14> I was going to link the same article!

I think the interesting part is the similarity between haskell and clojure. Essetially programming to very small classes/protocols. The linked article is cool, because i think the java approach would generalize to the OP's C++ solution, and be able to eliminate that gross dynamic cast.

</comment></comment></comment><comment><USER15> _Immutability: The property of functional programmers that prevents them from shutting up about pure functional programming._ \- @raganwald

 _Computation is not just about functions. If computation were about functions then quicksort and bubble-sort were the same because they 're computing the same function. As I said a computing device is something that goes through a sequence of states and what an assignment statement is doing is it is telling you here is a new state, and also there's the notion of it's non-determinism, so the new state is not a function of the old state. So functional programming in a sense - functions - don't solve the problem of programming._ \- Leslie Lamport

Perhaps functional programming is best for S-Programs and P-Programs...

 _S-Programs are programs whose function is formally defined by and derivable from a specification. P-Programs [are problems] that can be precisely formulated but whose solution must inevitably reflect an approximation of the real world. E-Programs are inherently even more change prone. They are programs that mechanize a human or societal activity._ \- Meir M. Lehman, Proceedings of the IEEE, Vol. 68, No. 9, September 1980.

... from my fortune clone @ [http://github.com/globalcitizen/taoup](http://github.com/globalcitizen/taoup)

<comment><USER16> In the same spirit:

 _The nice thing about declarative programming is that you can write a specification and run it as a program. The nasty thing about declarative programming is that some clear specifications make incredibly bad programs. The hope of declarative programming is that you can move a specification to a reasonable program without leaving the language._ \- _The Craft of Prolog_ , Richard O'Keefe (1990) (copied from CTM)

</comment></comment><comment><USER17> The main disadvantage is that the next guy/gal will have to rewrite it all in Java - the language he/she actually can read.

<comment><USER18> And then the next person will re write it in python. It would faster and less costly to just learn the language...

<comment><USER17> Rewriting a large codebase in Python (or any dynamically typed language) would be a mistake.

<comment><USER18> Thats true, if you wanted a _large_ codebase you should stick with Java.

Only half joking.

I like to think the goal is to create a working system. I haven't seen sufficient evidence that Static Typed languages as a category are more likely to produce working systems then Dynamically Typed ones. Feel free to link anything you have on the subject. I would take the time to read meta studies on the subject though, many of which seem to conclude their isn't much evidence either way.

I do believe that "Discovered" languages are more capable then "Invented" ones. Phillip talks a bit about the difference here: [https://www.youtube.com/watch?v=V10hzjgoklA&t=2176s](https://www.youtube.com/watch?v=V10hzjgoklA&t=2176s)

</comment></comment></comment></comment><comment><USER19> Optimizing runtime performance can be a little tricky and nonintuitive. Debugging can similarly be tricky-- inspecting internal return values is not super fun.

</comment><comment><USER20> For me one of the biggest hurdles is using immutable data structures all the time. In the real world you want to add to a list or change a map's value. Typically functional programming languages use linked lists to make h::t efficient but if you need performance characteristics of arrays and good performance/low GC you are going to have a lot impedance mismatch with the typical functional programming patterns based on built in lists.

<comment><USER21> > In the real world you want to add to a list or change a map's value.

Having spent a good amount of time doing production FP, and then taking what I learned into imperative work, I rarely find myself doing this. In the real world, what we usually want is the _result_ of adding to a list or changing a value in a map. But also in the real world, we rarely want to consider whether we've affected other things that supplied that list or map (which they generally would prefer we did not do).

> Typically functional programming languages use linked lists to make h::t > efficient but if you need performance characteristics of arrays and good > performance/low GC you are going to have a lot impedance mismatch with the > typical functional programming patterns based on built in lists.

I can't speak for the wide variety of FP languages out there, but it sounds like you've been exposed to languages with a poor set of data structures. Clojure, for example, provides a wealth of great immutable/persistent data structures that provide the semantics you'd want and perform really well.

<comment><USER20> I've done a bit of functional programming too and don't get me wrong, I love the FP cultural victory of Java/C# etc. getting immensely useful functions like map, reduce, filter, lambdas and higher order functions. But if you are going to use purely immutable data structures you're going to make trade offs. In the kind of work that I do generating excess garbage or using extra memory can be unacceptable so I think I'd struggle with that but I can still apply a good % of FP principles with mutable structures of course.

If you read introductory functional programming material, you will agree they are full of h::t style pattern matching and default list types in ocaml, haskell and scala are simple linked lists (I sadly haven't tried Clojure yet). I'm open to the possibility of advanced patterns with other data structures overcoming some of these problems that I'm not very familiar with but that's what I mean with impedance mismatch, you will need to step away a bit from the clean elegant patterns of "everything is recursion+pattern matching on lists" of typical FP teaching.

<comment><USER22> And if you do any serious functional programming, you will quickly learn that using these lists as a data structure is almost always a mistake. A mistake that happens to be encouraged by the language, but that is largely a historic wart of languages that are decades old at this point.

<comment><USER20> Sure, agreed, but even if you use more sophisticated immutable structures you either accept the performance/memory trade offs or you have to fall back on mutable structures.

<comment><USER23> But that's quite a different claim from your original one!

<comment><USER20> Maybe it helps if I explain better. I find it difficult to use immutable structures if I want certain performance characteristics. It's possible I need more training in certain techniques, but I think that's why I find it difficult, the default data structures and introductory literature seems to be too naive. And in the end, no matter what I use, there will be certain trade offs for purely immutable structures, and some stuff I just think it's easier to think about in mutable terms.

<comment><USER23> OK, that's a reasonable position. It is easy to read your original claim as "All real world programming requires mutable values", and that is certainly not a reasonable position.

</comment></comment></comment></comment></comment></comment></comment></comment><comment><USER24> Functional languages give powerful expressions for proving code correctness. Imperative languages provide good semantics for reasoning about performance. I don't see them as rivals, rather as two paradigms operating on different domains.

Object-oriented languages on the other hand....

</comment><comment><USER25> Immutability can have performance issues I believe...not sure you'd use it to write a game engine for a modern FPS.

<comment><USER21> Persistent data structures can generally overcome a lot of the performance issues with immutability, but generally at the cost of memory.

<comment><USER19> Ehhhhhh hard ass real time stuff like heavy dsp or a game engine, you're on the metal and you're pitching your code to the CPU, not to humans. And the CPU thinks (kind of) imperatively. And the GPU does its own thing which is basically neither, haha.

Stuff like web apps, or honestly, the vast, vast majority of programming, functional is just fine. The deep stuff is gonna stay imperative, but that's a small fraction of the work that needs doing out there.

<comment><USER25> That sums up my thoughts better.

</comment></comment></comment></comment><comment><USER26> I feel that Haskell's learning curve comes with the benefit that the curve actually goes in a hyper-productive direction. I have ~3 years of professional experience but with Haskell I've been able to create robust and extensible systems in deterministic amounts of time on a consistent basis, often working alone or with other "junior" devs. I think this is because I've spent the last ~6 years constantly learning FP/Haskell, and while it's been hard, every new thing I learn pushes me to be a more self-sufficient, capable engineer. If I weren't so lucky and didn't get the opportunity to __only __work in pure FP in Haskell /Scala from my first job out of college onwards, I don't think I would be as capable as I am now.

</comment><comment><USER27> Well I have one: next to no one can read/understand functional programming stuff, much less write.

Yeah it might be hyped in academia and in high performance/scaled systems but the average non-academic coder will never interact with FP code.

<comment><USER28> That's because you've learned imperative coding first. If you learned functional coding first you'd probably find imperative coding complex. I'd certainly rather code in OCaml than C.

</comment></comment><comment><USER29> Thinking that any variant of "functional programming" stands for all variants?

For me, moving to F# from C#, and then trying to get my team to do likewise, it's far more like "this encourages good CS101 practices" than anything else. The only disadvantage is the occasional CPU burp (usually easily resolved).

To reddit commentor, I'll agree a lot of OO ideals are baked into GUI, and are actually quite good for it (decorator pattern, etc). Though a lot of GUI (winforms binding, wpf mvvm (sorry)) conventions paint you into a bit of a corner.

</comment><comment><USER30> Is there any example of a usable Graphical UI written in a functional language?

I've seen something very minimal in erlang, but it was so resource intensive it barely functioned at all.

<comment><USER31> How about xmonad? [http://xmonad.org](http://xmonad.org)

<comment><USER32> A colleague of mine who wants to play with haskell tried it out and threw it in the too-hard basket - apparently to configure it you write haskell in the config files; not where he wanted to be trying his hand at the language.

</comment></comment></comment><comment> a-saleh It depends how deep you want to go. I would say that 'functional' can mean different thing to different people, but usually I see it as methodical use of certain programming features over others.

1\. Language supports functions as values, anonymous functions, has higher order functions, and ability for functions to access scope in closure. At this base level there are no disadvantages to prefer using these, because they allow some nice abstractions (as evidenced by many functional libs in js.)

2\. using recursion over loops, can be a good fit for expressing some algorithms. Often requires some support for optimisation in language (i.e. tco, so that your stack doesn't explode. In my experience you'd use higher order functions like map, fold/reduce most of the time anyway, instead of dealing with loops/recursion directly.

3\. pure functions. This is the first interesting trade-of in functional programming, how much should you use functions that only depend on its inputs to provide its output (and for the same input output would stay the same). There are clear advantages, you can test these well, understand them in isolation, refactor them easier, memoization is almost for free.

On the other hand, only using pure functions would limit the usefulness of the language (it is said that first version of haskell was only able to do a transformation from stdin to stdout, because they had just pure functions) Languages that are big on being 'pure' usually allow you to make impure functions, but then track their usage in the type-system. This was one of those things, that I often think is more trouble than is worth.

4\. immutable data-structures, which come in handy when you want to create pure functions that would rather return a copy with modifications, than modify in-place (because that might have unintended consequences elsewhere) It takes some time to get used to these, but their performance is on par with regular datastructures nowdays.

5\. lazyness, where you compute only when necessary. Can make certain programs more efficient and easier to comprehend, others harder, i.m.o

6\. no global state.

7\. comprehensive type system is sometimes viewed as necessary for real functional language (how else would you check you don't do side-effects in wrong places)

For me, 1., 3., 4. and 6. are those I consider important and with little drawbacks to try to use them 80-90% of time.

</comment><comment><USER28> The big one for me is a practical one: the current ecosystems around them. I'd love to code mobile apps and web apps in OCaml but it would just be going against the grain too much for it to be worth it in the vast majority of cases I think. Can you easily deploy on most cloud services? Are there good libraries you can use? Is there a community that can help you when you get stuck?

It's not a fault of functional languages but that is the issue, it's that the vast majority of coders and ecosystems are entrenched in imperative languages still.

I'll use strong static typing where I can though e.g. TypeScript is decent in terms of practicality.

<comment><USER19> I believe clojure's made a lot of progress porting to android's JVM. Last I heard the clojure runtime took a couple seconds to boot, which is shitty if you're real serious about your apps, but not a dealbreaker. And the last time I messed with it was a couple years ago, I would hope to see improvements in that amount of time.

<comment><USER33> For Clojure it seems React Native + ClojureScript is the more popular option. It has good startup performance and works also on iOS: [http://cljsrn.org/](http://cljsrn.org/)

</comment></comment></comment><comment><USER34> Functional Programming is a big tent, too big to be very useful. All good programming provides some proof of correctness, through test coverage, the type system, or a bit of reasoning done to the side (worst case). Ease of reasoning from FP in the large is not very valuable but does eliminate some cognitive overhead. There are no disadvantages to higher order functions and referential transparency except those we impose on ourselves with our choice of hardware. Type systems are where the meat is at, and a good type system clearly states the advantages and disadvantages in its design.

<comment><USER35> Higher-order functions and indirection in general can lead to increased cognitive overhead. Try reading or debugging a deep points free functional expression and it's obvious there are limits.

<comment><USER36> In my own (limited) experience, I'd much rather debug a nasty pointfree expression than debug a deep nest of loops keeping state in mind.

Perhaps it is just different kinds of cognitive overhead.

<comment><USER35> How would you even go about stepping through a pointsfree expression though? Have Haskell/scala debuggers improved significantly in this regard?

<comment><USER36> I wasn't aware these debuggers existed. I'll have to check them out.

The purpose of writing point-free functions is to encourage thinking about chaining functions together instead of considering what really happens to low- level values. It's like using pipelines. This means that for debugging, "stepping through" wouldn't help you much IMO even if you could do it![0] (A whiteboard might help, though.)

I'll try to give an example: if you're looking at an unnecessarily point-free expression like "mapReduce = (. map) . (.) . foldr1", the logic is difficult to read. I'm not an expert in point-free-fu yet, so in that case I'd recommend pointful[1], which deobfuscates that expression to "mapReduce x x0 x2 = foldr1 x (map x0 x2)", a map followed by a fold. So the problem is again reduced to looking how functions are being chained together. For larger examples of point-free expressions I'd try to isolate individual functions as where clauses.

[0] As mentioned by cgmg, the Writer monad is useful if you need to know the values going in and out of functions. [1] [http://github.com/23Skidoo/pointful](http://github.com/23Skidoo/pointful)

</comment></comment></comment></comment></comment><comment><USER37> Massive hype squeezing functional programming into all kinds of imperatively shaped holes, code that's going to remind you of your dad's 80's pictures someday.

</comment><comment><USER38> Disadvantages: Sometimes it takes more work. Quick and dirty can be easier to read, if the function is short.

Advantages: You can mix and match. Pure functions are more composable and easier to test because you don't have to worry about side effects.

</comment><comment><USER39> Difficult to write a good compiler.

Optimizing the code generated by the frontend for a function language is a nightmare.

There are several theoretical reasons why that is the case, so do not expect significant breakthroughs for general purpose functional programming.

<comment><USER40> Care to go into any detail?

</comment></comment><comment><USER41> well i love fp, but the reality is that fp is not even an afterthought in the libraries that underlie numerical computation--most significantly, BLAS, LAPACK. Those libraries rely entirely on _mutable_ data structures.

it has very little to do with their age--fact is these libraries are continuously updated (last major re-write for LAPACK was 2008; what's more, fp is not new, it was a well-known paradigm when, say MKL was conceived (2003), but apparently even the most cleverly designed persistent data structures (eg, Scala's vector) aren't enough.

</comment><comment><USER42> No disadvantage. Learn your FP, it's good for you. ;)

</comment><comment><USER43> It's fine as long as you use spaces not tabs.

</comment><comment><USER44> one disadvantage is all of the people telling you to rewrite it in Rust. Seriously, why are you such a bad person?

*just kidding. mean no offense.

</comment><comment><USER16> I am currently studying the excellent [https://www.amazon.com/Concepts- Techniques-Models-Computer-P...](https://www.amazon.com/Concepts-Techniques- Models-Computer-Programming/dp/0262220695), and I believe that this book answers the questions in the OP very clearly, and although maybe you find it too theoretical, it does in fact provide loads of practical advice, and is very readable; not for the faint of heart though ;)

Anyway, just to practice what I've learned so far I will try to answer some of your questions from the top of my head; apologies in advance for my verbosity:

First of all, let's define functional (in fact, to be strict, declarative; more on this below):

An operation (i.e. a code fragment with a clearly defined input and output) is functional if for a given input it always gives the same output, regardless of all other execution state. It behaves just like a mathematical function, hence the name.

This gives a declarative operation the following properties:

1) Independence: nothing going on in the rest of the world will ever affect it.

2) Statelessness (same as immutability): there is no observable internal state; the output is the same every single time it is invoked with the same input.

3) Determinism: the output depends exclusively on the input and is always the same for a given input.

So what is the difference between functional and declarative? Functional is just a subset of declarative = declarative - dataflow variables

These properties give a functional program the following key benefits:

1) It is easier to design, implement and test. This is because of the above properties. For instance, because the output will never vary between different invocations, each input only needs to be tested once.

2) Easier to reason about (to prove correct). Algebraic reasoning (applying referential transparency for instance: if f(a)=a^2 then all occurences of f(a) can be replaced with a^2) and logical reasoning can be applied.

To further explore the practical implications of all this lets say that, given that all functional programs consist of a hierarchy of components (clearly defined program fragments connected exclusively to other components through their inputs and outputs) to understand a functional program it suffices to understand each of its components in isolation.

Basically, despite other programming models having more mindshare (but, as far as I can tell, aren't really better known, and this includes me ;), because of the above properties functional programming is fundamentally simpler than more expressive models, like OO and other models with explicit state.

Another very important point is that it is perfectly acceptable and feasible to write functional programs in non strictly functional languages like Java of C++ (although not in C, I won't explain why, it's complicated but basically the core reason has to do with how memory management is done in C).

This is because functional programming is not restricted to functional languages (where the program will be functional by definition no matter how much you mess up).

A program is functional if it is observably functional, if it behaves in the way specified above.

This can be achieved in, say, Java, with some discipline and if you know what you are doing; the Interpreter and Visitor design patterns are exactly for this, and one of the key operations to implement higher order programming, procedural abstraction, can easily be done using objects (see the excellent MIT OCW course [https://ocw.mit.edu/courses/electrical-engineering-and- compu...](https://ocw.mit.edu/courses/electrical-engineering-and-computer- science/6-005-elements-of-software-construction-fall-2008/index.htm) for more on this).

Because of its limitations, it is often impossible to write a purely functional program. This is because the real world is statefull and concurrent. For instance, it is impossible to write a purely functional client-server application. How about IO or a GUI? Nope. I don't know Haskell yet, it seems they somehow pull it off with monads, but this approach, although impressive, is certainly not natural.

Garbage collection is a good thing. It's main benefit to functional languages is that it totally avoids dangling references by design. This is key to making determinism possible. Of course, automatically managing inactive memory to avoid most leaks is nice too (but not all leaks, like, say, references to unused variables inside a data structure, or any external resources).

However, functional programs can indeed result in higher memory consumption (bytes allocated per second, as opposed to memory usage, which is the minimum amount of memory for the program to run), which can be an issue in simulators, in which case a good garbage collector is required.

Certain specialised domains, like hard real time where lives are at stake, require specialised hardware and software anyway, never mind whether the language is functional or not.

So, for me, for the reasons above, the take home lesson so far is:

Program in the functional style wherever possible, it is in fact easier to get right due to its higher simplicity, and restrict and encapsulate statefulness (and concurrency) in an abstraction wherever possible (this common technique is called impedance matching).

Each programming problem, or component, etc, involves some degree of design first, or modelling, or a description, whichever word you prefer, it is all the same. There are some decisions you must make before coding, TDD or no TDD.

What paradigm you choose should depend first on the nature of the problem, not on the language. Certain problems are more easily (same as naturally) described in a functional way, as recursive functions on data structures. That part of the program should be implemented in a functional way if your language of choice allows that .

Other programs are more easily modelled as an object graph, or as a state diagram (awesome for IO among other things), and this is the way they should be designed and implemented if possible. But even in this case, some components can be designed in a functional way, and they should be wherever possible.

There is no one superior way, no silver bullet, it all depends on the context. It is better to know multiple programming paradigms without preferring one over the other, and apply the right one to the right problem.

</comment><comment><USER45> Higher order functions (taking/returning functions) in practice can lead to code that is very convoluted.

</comment><comment><USER46> The article describes functional programming in its purist form: 0 side effects. In practice that simply doesn't exist in any language except Haskell and maybe variants of LISP. Next is the simple fact that a pattern or functional idiom has never and will never save your project, so adopting it for those reasons is simply not practical. Also it is not practical to reduce your hiring pool by one or more orders of magnitude. No profitable company you've worked with this week relies completely on functional programming. All of the most profitable companies in the world have side effects in their code. Deviate from the path at your own risk.

<comment><USER47> > The article describes functional programming in its purist form: 0 side > effects.

Incorrect, reread the first two paragraphs:

> Of course one can define functional programming so that no local mutable > state and no side effects are possible, and then point out the obvious > disadvantages. But that's perhaps a "no true Scotsman" kind of argument. If > you would define object-oriented programming with the same strictness, > everything that is not an object and uses mutable values would be forbidden. > Even something such as y = sin(x), copy-on-write or returning constant > objects or containers from a function would be off-limits. That is, I am > asking with a very pragmatic definition of FP in mind!

> What I am wondering is rather, do you observe pragmatic functional > programming as John Carmack described it here as valuable? And of course > this question goes also to people who have tried it to some extend, as a > purely theoretical discussion would be boring. I am interested in good > examples!

<comment><USER35> Pragmatically speaking, most non trivial programs consist of functional and, yes, even object-oriented styled code. Doing functional programming over those nounish state-indexed things doesn't make them non objects even if you prefer to call them "entities" instead, while most OOP programmers use lambdas freely without any feelings of regret.

<comment><USER21> The thing about OOP that is avoided in FP isn't calling an entity an "object", it's the fact that the same object changes over time. It's hard to reason about "I let this so-called function change a thing and I can't know how or why". It's much easier to reason about "I gave this function a piece of data and it gave me the change back".

<comment><USER35> Entities externalize state that can vary over time. So it isn't f(g) but f(g(t)). Time (and hence mutation) really does exist, whether it is implicit or explicit.

It is only easier to reason about when the data you give the function is limited. You can always pass the world into the function and take it as an output, then it no longers matter. Effect systems are also possible with objects as well, they just aren't a feature of functional languages.

</comment></comment></comment></comment></comment><comment><USER48> I am genuinely convinced, that all such topics have nothing to do with science. Such question is more philosophical or religious. Many people will try to explain their ideologies and believes about how things should work. Each side may try to say what is correct, while nobody has a proof.

Discussing such topics has no scientific meaning, it is a waste of time and it should be considered a clickbait :)

<comment><USER47> OP didn't mention science at all. They were asking for real-world experiences, actually.

So, you're meaninglessly correct. Such questions do not have to do with science, which is why science was not featured in the question.

<comment><USER48> The subject is scientific, so it sounds like e.g. "what are disadvantages of complex numbers". I am not talking just about science. I mean the whole purpose.

Such discussion will have no effect on people, who truly know what functional programming is. It also may have incorrect or misleading effects on people, who don't fully understand, what functional programming is.

<comment><USER49> To expand on Ranger's point, the OP's question is specifically requesting people's anecdotal experiences and opinions concerning applied knowledge. Science is the repeatable process of discovering and accurately modeling nature (for varying definitions of "nature").</comment></comment></comment></comment>


SysAdmins who track inventory: Try using a visual map - <AUTHOR> https://www.cyberstockroom.com/ <comment><USER2> Why do you keep submitting essentially the same exact thing?</comment>


Why Is There Philosophy of Mathematics at All [pdf] - <AUTHOR> https://core.ac.uk/download/pdf/24065753.pdf <comment><USER2> Given that the philosophy of mathematics (Boole, Peano, Russell) led directly to computers, it's a bit ironic as a title appearing on this site!

</comment><comment><USER3> Philosophy is trying to answer questions that do not have answers. Mathematics studies that which does not exist (in the real world).

Yet, they are both useful.</comment>


An Atheist's Glimpse of God - <AUTHOR> http://blog.deobald.ca/2013/02/an-atheists-glimpse-of-god.html <comment><USER2> Disclaimers. I am also an atheist. I took this exact meditation course 20+ years ago and know people who have followed it for decades. I am not so enthralled.

The meditation itself is fine. However the problem is in the tapes. Goenka is not just trying to teach people to meditate, he's trying to teach a particular religious philosophy. He doesn't want you to just be aware of your body, he wants you to pay attention to how things arise and pass away, and from that conclude that all attachment is bad because you will feel grief when it passes. This ties into Buddhist philosophy.

To me the problem with this philosophy can be summed up by, _'Tis better to have loved and lost, than never to have loved at all.'_ I was fascinated by the experience, but receiving indoctrination while I was in such a delicate state was not to my liking.

<comment><USER3> As things are right now, any meditation technique worth the effort is coming from one or another religious background. So there is going to be some infusion of dogmatic elements into it. At least some schools are honest about it and tell you to feel free and ignore the mythology and focus on the psychological work.

I practice a different meditation system, and they have their own dogma attached to it. I found that whether I "believe" in it or not is irrelevant. Meditation itself is far too fascinating to get distracted with extras.

Another way to look at it is that some dogmatic aspects may not represent literal truths, but are metaphors for certain psychological aspects occurring in meditation or as an effect of it. This appears to be a very appropriate interpretation for many pantheons - heck, even the Greek gods are quite obviously representations of states of consciousness and functions of the mind, and the ancient greeks were not exactly famous for their meditation techniques.

<comment><USER4> I've been doing transcendental meditation. I imagine its roots are from a "religious background", but I don't feel like there are any religious elements. There are only a few dogmatic rules such as don't eat 2 hours before/after meditating.

<comment><USER5> There is a recommendation to wait a while after eating until the main digestion is completed before meditating. But there is no recommendation to wait any time after meditating before eating.

</comment></comment></comment></comment><comment><USER6> Very interesting. Incidentally, I do like:

 _Ninety percent of Maslow's pyramid has been taken care of for as long as I could remember, leaving me to arrogantly believe it's my responsibility to improve this world_

\-- that resembles a feeling that often brings me angst, but I always struggle to put into words.

<comment><USER7> Disclaimer: I haven't actually read Maslow's original work.

Looking at Maslow's pyramid, way more than 10% of it has to do with very abstract stuff. Given what the author has written, he almost by definition hasn't achieved "self-actualization" in the sense Maslow means. He almost by definition hasn't achieved 90% of the pyramid.

Only a small part of the pyramid has to do with food, shelter, clothing, and having people to socialize with.

</comment></comment><comment><USER8> I like to run once a week or so. It helps me shed a lot of stress, and is supposed to be good for me.

At first I hated it. But then I began bringing my iPhone and listen to music. I mostly listen to electronic dance music, but there was a specific genre that I found worked well for runnig; Trance.

There is one "song" that illustrates this very well. It is 9.5 minutes of very monotonous, slowly building "umm-tss". [http://www.youtube.com/watch?feature=player_detailpage&v...](http://www.youtube.com/watch?feature=player_detailpage&v=yOJsjyq_GsE#t=26s)

There is a reason for that name. I found that this music, in combination with the deep breathing in coordination with my steps sort of lets me enter a state of trance. I can empty my mind and just _be_. Stress over deadlines and finances - and even stress over being stressed - pretty much are gone when I get back home.

</comment><comment><USER9> Sensory deprivation is known to cause hallucinations, often within a matter of minutes. People are primed to believe that sensory deprivation in the form of meditation provides profound insights, so they do. If you force a prisoner to sit still for several hours in a silent room as punishment, they perceive it to be a dreadful torture.

It's mystical nonsense. "I did a thing that made me feel better" is a perfectly legitimate statement. "I did a thing and believe it to be deeply profound and meaningful in ways I cannot articulate" really isn't the sort of thing we usually countenance on HN, because it's a line of thinking that we recognise to be dangerous.

For various cultural reasons, mainly ignorance, rationalists are unusually tolerant of Buddhist nonsense, often believing it to be essentially benign. If you know anything of the history of south-east Asia, you will know how foolish that error is. I rather doubt that a post extolling the virtues of Islamic or Christian monasticism with such breathless naivete would have garnered so many upvotes.

</comment><comment><USER10> Tip for the impatient: click 'Start' multiple times for a shorter ten minutes.

</comment><comment><USER11> Meditation is one of the things that most people should do, it enlightens you as to your faults, bringing them to light so that you may change yourself for the better. It's also nothing to do with making you superior to other people(if it is you have other issues that won't work themselves out until you learn some empathy.)

</comment><comment><USER12> For those of you looking for a place to go on a similar 10 day retreat, there is:

Northwest Vipassana Center (PNW Region, I've heard really good things about this one from friends who have done the program) <http://www.kunja.dhamma.org/>

Dhamma Manda (Near SF) <http://www.manda.dhamma.org/>

The closest one to NYC I can find is in Mass: <http://www.dhara.dhamma.org/ns/>

For more info on locations near you:

<http://courses.dhamma.org/en/maps/001>

</comment><comment><USER13> I hate to be "that guy", but clicking your timer more than once seems to be cutting the intervals down each time (ex: click it 10 times, and it goes crazy fast).

I only say this because I love that you actually went ahead and embedded a timer in your post -- knowing that the process of reading and absorbing the content was just as important, if not more important, than the content itself.

Regardless, great post.

</comment><comment><USER14> I enjoyed your article. Thanks. Makes me want to try meditation again. (I've attempted it a few times)

</comment><comment><USER15> Thanks for sharing this amazing experience. I have been wanting to do this same very course myself.

Even today evening I was thinking of just this.

Your experience has inspired me even more. I believe i must stop thinking and just plan go at the next best available free time.

</comment><comment><USER16> Basic brain washing routine. You want a religion. Just pick one. Stop trying to convince yourself you're rational. You're a human being: you're not rational. Irritating post. Why the hell did I read this?

</comment><comment><USER17> Self contradictory title. Once again we're mixing up chemical imbalances (however induced) with this notion of a Creator. If there really is this God thing, then do you really think they give a damn about you sitting on hot rocks? If you do, then you've really missed the point of it all. If you don't then you'll quickly realize you're just wasting your time, the most precious resource you have.

<comment><USER3> Not all speech is literal.

I find myself making this admonition over and over again, when speaking to folks in the computer industry. Occupational hazard, I guess.

<comment><USER17> even if you read it metaphorically, it makes the same amount of sense.

<comment><USER3> to you.

</comment></comment></comment></comment><comment><USER18> So you sat on some stones under extreme physical duress. Congratulations. Your puny mammalian brain acted in a manner dysfunctional from its normal operating environment. Now you can go to parties and feel even more superior to your friends. They won't get it of course because there's no way for you to accurately explain it to them.

<comment><USER19> Why so dismissive? Religious or feel-good benefits aside from the 100-hour regimen, the guys deserves kudos merely for sticking with the exercise to its conclusion. Even without the discomfort, sitting/standing/whatever for 10 hours a day doing _nothing_ physically takes some dedication.

I find his experience amazing on so many levels, and I am gracious for such a intimate account of that experience (I read the full-on article he references).

<comment><USER17> * the guys deserves kudos merely for sticking with the exercise to its conclusion

why? If I pierce my scrotum a hundred times should I get kudos? No of course not, just doing something uncomfortable for no reason isn't admirable.

Meditation is great for some people, and a total waste of time for others. Each to their own, but let's not pat anyone on the back for it.

<comment><USER12> I would totally give you kudos for piercing your scrotum a hundred times. From the people I know in the body modification community, genital modification can be a very spiritual experience.

Also, think of the crazy rush that you would get from the first piercing, when your body is changed forever, till the end of the hundred-piercing ritual. That would absolutely be something worth blogging about.</comment></comment></comment></comment>


Jailbroken PS3 running Linux, flashed permanently - <AUTHOR> http://www.youtube.com/watch?v=lGI0EnNQ5GE

<comment><AUTHOR> Sony failed to safely sign their executables with ECDSA, effectively yielding their private key to the team. They then used this, plus some bugs in the lower-level loaders to permanently flash a loader than would bring up Linux at the same level as a game would normally run.

This is in addition to the release yesterday of the private HMAC secret to generate dongles for downgrading the OS.

More information:

[1] How to sign things properly with DSA: [http://rdist.root.org/2010/11/19/dsa-requirements-for- random...](http://rdist.root.org/2010/11/19/dsa-requirements-for-random-k- value/)

[2] The actual talk from yesterday: <http://www.youtube.com/watch?v=X6CA4fqAdsc> (with slides here: [http://events.ccc.de/congress/2010/Fahrplan/attachments/1780...](http://events.ccc.de/congress/2010/Fahrplan/attachments/1780_27c3_console_hacking_2010.pdf))</comment>


The rise of meatless meat, explained - <AUTHOR> https://www.vox.com/2019/5/28/18626859/meatless-meat-explained-vegan-impossible-burger <comment><USER2> If I read bynd financials right their cost of production isn't greatly different to meat packing companies. Hormel's cost of production is only a little worse, yet they have been profitable for a very long time and no profit as of yet with bynd. Though that can be expected at this stage. I just find it dissapointing that so called plant based "meat" isn't naturally a vastly less expensive product.

Indeed the cost of complete proteins found in chicken, eggs, and dairy is really hard to beat. Concentrated protein is helpful for a diet requiring fewer calories to acheive. Chickens make complete protein more cost efficiently than engineers cooking up plants.</comment>


Robert N. Hall, whose discoveries led to microwave ovens, died in 2016 - <AUTHOR> https://www.nytimes.com/2018/05/10/obituaries/robert-n-hall-96-whose-inventions-are-everywhere-is-dead.html <comment><USER2> > _In a 2012 interview for this obituary, he talked about the pleasure he took > in a life of science._

That has to be one of the eeriest and most flattering calls one could ever receive:

"Hi, I'm from the New York Times, and I would like to interview you for your obituary."

<comment><USER3> They try to be circumspect about it, like "Hey famous person, I haven't heard about you for a while. What have you been up to?" but it's still pretty obvious what it's about.

</comment></comment><comment><USER4> This is fascinating. I've never seen an obituary published so long after someone's death before.

<comment><USER5> Indeed. I can only think of one other, which probably holds the record.

[https://www.economist.com/news/obituary/21571379-richard- pla...](https://www.economist.com/news/obituary/21571379-richard-plantagenet- englands-most-controversial-king-was-officially-rediscovered-february)

<comment><AUTHOR> None of the obituaries come close to matching the elapsed time of Richard III, but the NY Times has started publishing obituaries of overlooked individuals since the paper started publishing in 1851.

[https://www.nytimes.com/interactive/2018/obituaries/overlook...](https://www.nytimes.com/interactive/2018/obituaries/overlooked.html)

<comment><USER4> This is a different thing, though. In the case of Robert Hall, the NYT had written the obituary ahead of time, as is typical practice, but the passing was not even noted.

</comment></comment></comment></comment><comment><USER6> He died in 2016, to be clear.

</comment><comment><USER7> You mean the Done bell only went off now?</comment>


Why code that never goes wrong can still be wrong - <AUTHOR> http://www.pathsensitive.com/2018/01/the-three-levels-of-software-why-code.html <comment><USER2> Instead of first digging into the author's _" Definition #3"_ and _" Level 3 Design/Logic"_, I would recommend reading the 1985 paper _" The Limits of Correctness"_ by Bryan Cantwell Smith.[1]

I think it's one of the top 5 papers every programmer should read. It's a short and easy read that makes one think about the limits of _models_ , the limits of _specifications_ , and the limits of _formal verification_. After grokking BCS's insights, there seems to be (an unintended) hubris in James Koppel's statement, _" I now have two years experience teaching engineers a better understanding of how to [...] make code future-proof_" in his framework of removing defects from "Level 3" design.

(As a side note, there's also a cosmic irony as that paper starts with an anecdote about the "correctness" of detecting ballistic missiles in 1960 given the recent false alarm in Hawaii.)

[1] [https://www.student.cs.uwaterloo.ca/~cs492/11public_html/p18...](https://www.student.cs.uwaterloo.ca/~cs492/11public_html/p18-smith.pdf)

<comment><USER3> The incident in Hawaii was user error and is a UI design problem.

<comment><USER2> _> a UI design problem._

When a military general or Secretary of Defense asks if the 1960s missile warning system is working "correctly", it means it's working _incorrectly_ when the moon is categorized as an incoming enemy attack.

Likewise, when a general asks if the 2018 warning system is working "correctly", it means the system is designed _incorrectly_ if the pixels of text on the screen[1] lead operators to trigger the unintended action.

Categorizing one error as a "radar error" and another as a "UI error" as if they are 2 disconnected concepts of correctness is missing the point of BCS's essay.

When people think of something working "correctly", they want the whole system to work correctly. They will not explicitly enumerate all the subcomponents nor all the subdisciplines such as "UI design".

[1] [https://twitter.com/CivilBeat/status/953127542050795520](https://twitter.com/CivilBeat/status/953127542050795520)

<comment><USER4> In this instance, the phrase " _code that never goes wrong_ " does not imply recognition of human factors affecting an operational system.

<comment><USER5> > _(Where "wrong result" is broadly defined to include performance bugs, > usability bugs, etc.)_

The author seems to disagree - isn't bad design a usability bug?

</comment></comment></comment></comment></comment><comment><USER6> If code is wrong, yet nothing goes wrong, it's miles ahead of almost all of the software I battle with to get work done every day.

<comment><USER7> exactly. Also: Never touch a running system. I'm sure there is so many "wrong" software out there but as long as it works good enough we are not doomed hopefully.

<comment><USER8> How much time does it have to run without failing to qualify for "safe" ?

</comment></comment></comment><comment><USER9> I think this is a bit overthought. There are 2 classes of errors: Errors that can manifest in a problem (we usually call these "bugs") and errors that can not manifest in a problem (these are usually called "software errors"). The second class of error is not really an issue until you change the code (or some other factor) and the error manifests as a problem (and then it is a bug). You might imagine some off-by-one error, where by chance it doesn't affect the result. However, if you modify the code, then the off-by-one suddenly matters and you get a bug.

Apart from that, software either has some functionality or it does not. It's actually not particularly meaningful to discuss whether or not software was originally supposed to have functionality, unless you just want to finger point. There may be a bug that stops the functionality from working correctly or it may be that you got the requirements wrong and implemented the wrong thing, or it may be that you never even tried to implement something. It doesn't matter -- the functionality doesn't exist.

When you are designing code, or implementing, or refactoring it, or whatever, then you need to consider how easy it is to modify the result. It's tempting to look ahead and assume that you know what you will need in the future, but you should also consider that you might be wrong (The YAGNI (You Aren't Gunna Need It) rule is surprisingly effective). Generally speaking, as a programmer, your goal should be high throughput of development throughout the lifetime of the project. Attempts to cut corners are usually repaid with interest later down the road. Similarly YAGNI work not only ends up being wasted, it complicates the code base and slows you down later. Because of this, you should usually attempt to just keep the code as simple as possible to modify in general. You should also make the functionality you have developed as accessible as possible (i.e. hiding your functionality under 1000 layers of abstraction is usually a recipe for slowing you down later, even if it looks cool now).

Worrying overmuch about if your code is wrong is probably a class of YAGNI. As long as it is easy and obvious to fix, then it doesn't really matter if it is wrong. Concentrate on making sure that it produces the result that you want and that you can modify it if it turns out to be wrong. Incidentally, it will be wrong. Eventually. You can pretty much count on it.

<comment><USER10> This is fine if the bug is _only_ triggered when you modify the code. Many bugs that classify as #3 (from the article) are not _only_ triggered by modifications to the code. For example, many lower-level languages have runtimes with sub-allocators that grab chunks of memory from the OS and dole them out in smaller bits to the calling code. This means that an off-by-one error on the read of an array can cause absolutely zero problems when you run the same binary 1000+ different ways, but have the user change the order of operations in the application in one particular way and boom !, now you get an AV/segfault in your application. It's all down to the how the OS MM and the runtime sub-allocator work and what the user does (and in what order). The solution is to make sure to use a sub-allocator that allows you to test your application with rigorous allocation tracking, which will catch these types of bugs, but not all developers are so thorough.

<comment><USER11> It's also possible for two off by one errors to cancel out. The code is not correct as implemented, but you need to fix both locations to avoid noticeable bugs.

</comment></comment></comment><comment><USER12> Whenever anyone starts talking about formal proofs of correctness I like to tell the story of the RAX bug:

[http://spinroot.com/spin/Doc/rax.pdf](http://spinroot.com/spin/Doc/rax.pdf)

This was code that ran on a $150M spacecraft, so getting it right really mattered. It had a formal proof of correctness. We tested the living shit out of it. And it _still_ failed.

<comment><USER13> _> One of the errors found with SPIN, a missing critical section around a conditional wait statement, was in fact reintroduced in a different subsystem that was not verified in this first preflight effort. This error caused a real deadlock in the RA during flight in space._

So they used code that they had already discovered an error in, in a different subsystem. I would not contend that that means that software verification doesn't work.

<comment><USER12> That sentence is not a completely accurate account of what happened. The error was not in a "different subsystem", it was in the same subsystem as the verified code: the executive. The code was structured as a verified kernel with unverified application code written on top of it. The verification proved that the code would be free of deadlocks if the application code used the kernel operations exclusively, and did not directly use any primitives like mutexes, but it turned out that this design rule was violated.

</comment></comment></comment><comment><USER14> I don't think there's any particular reason to apply the label of "bug" to erroneous reasoning that cannot result in erroneous behavior.

If you can't in actuality cause a flaw in a program despite the presence of unsafe operations or faulty reasoning, then I would say that by definition there is no bug. Rather I might say that the code is brittle and perhaps unmaintainable, with risks for people who modify it later. Which is of course bad, but thinking pragmatically there's not much different between a latent pitfall like this and some poorly documented or gnarly spaghetti code that is equivalently difficult to maintain.

Fixing what the author calls "Level 1" and "Level 2" problems is sort of a mandatory imperative, as you can't realistically ship software with prominent issues at these levels. But shipping software with latent "Level 3" problems is something that happens every day, and it might be entirely correct to do the hacky and expedient thing rather than the "correct" thing at this level -- this is not a luxury you can afford at other levels, which makes this level fundamentally not a "bug".

That doesn't mean it's not worth thinking about erroneous reasoning. Erroneous reasoning is often the source of actual bugs that slip through a test suite. And if you're using loose reasoning and relying on assumptions holding true in the future, this is the sort of thing you should be documenting next to the code for the benefit of future maintainers. And indeed we should be working to write more maintainable, safer software, but not under the guise of a "bugfix" \-- this is just good software engineering practice.

Thinking about "Level 3" problems is good. But be pragmatic. The reason you're doing it is because they make software difficult to reason about, and hence maintain. Investing time into fixing these problems helps future maintenance, but there are probably a lot of things you can do to improve software maintainability and you do need to actually ship the software at some point.

<comment> loup-vaillant > _I don 't think there's any particular reason to apply the label of "bug" to > erroneous reasoning that cannot result in erroneous behavior._

Undefined behaviour. Can't go wrong now on current compilers with current architectures, but who knows what will happen at the next rounds of optimisations.

</comment></comment><comment><USER15> The opening account of what it means to be right seems to me related to the "justified true belief" model of knowledge:

[https://plato.stanford.edu/entries/knowledge- analysis/#KnowJ...](https://plato.stanford.edu/entries/knowledge- analysis/#KnowJustTrueBeli)

I wonder if that inspired it, or if the author just ended up heading in that direction>

</comment><comment><USER16> Good article. I think this is more relevant for Model based development and auto code generators. In auto-generated code there usually exist may unreachable paths and un-resolved conditions which only surface up when code is run over certain period of time or some environmental conditions are met. Visualising Level 3 as explained in article is easy in model based development but it's consequences on Level 1 and Level 2 are difficult to predict. These things are of topmost priority in safety critical systems. E.g. [1] Toyota's unintended acceleration case [1] [https://embeddedgurus.com/barr- code/2013/10/an-update-on-toy...](https://embeddedgurus.com/barr- code/2013/10/an-update-on-toyota-and-unintended-acceleration/)

</comment><comment><USER17> "Just because it works, doesn't mean it isn't broken."

<comment><USER18> As a frequent poster of C answers on Stack Overflow, this is a succinct way of expressing the realities of programming in a language with undefined behavior ("UB").

Many newcomers to C seem to think that just because they wrote something, and it compiled, and it had the expected output, they wrote a correct program. But since there can be UB which results in _any_ (hence undefined) behavior, including whatever the person expected, that really isn't true. Unfortunately that seems to go against many people's expectations/intuition. :/

<comment><USER19> A valid pet-peeve.

<ramble>

Conflating a working build for good code, isn't specific to C. Students being taught Java (or any other safe language with an explicit verification/compilation phase) can also be tempted to assume that just because their code finally compiles ok, then it must be the program they hoped to write.

Then there's the issue of the code working for one or two particular combinations of inputs, but not all. Again, failure to test well is not specific to C.

There is the possibility that the UB only rears its ugly head in very rare circumstances, but again, obscure bugs slipping past testing isn't specific to C.

Where C is unique is that, as you say, even where the resulting binary _always_ gives the right outputs (on your current compiler+platform), that doesn't mean you have a 'truly correct' C program, even assuming that platform independence is a non-goal.

To put it another way, exhaustively demonstrating the correctness of the resulting binary, doesn't prove the correctness of the C program. This isn't the case for all other languages, however - sometimes exhaustive testing of the binary _can_ prove program-correctness.

(At least, if we ignore non-deterministic runtime factors like threads' scheduling and RNGs. One could concoct a deterministic subset of Java that would have this property.)

Regarding multi-platform code: It's not just UB that gives C the ability to behave so differently between different compilers/platforms. If you switch platform and are suddenly subjected to a new width of unsigned int, your code might behave differently in this new environment (it might fail to wrap-around when it used to, say) even if it never invokes UB.

</ramble>

> that seems to go against many people's expectations/intuition

In an ideal world we'd take the edge off by requiring all new C programmers to use something akin to Clang's 'ubsan' runtime UB detector.

</comment></comment></comment><comment><USER20> The trouble with formal specification is that for a lot of systems the specification is a substantial fraction of the length of the program it is meant to be specifying. In fact if you code in a high level language like Haskell it is actually possible for the code and specification to be the same length. At this point finding errors in the specification is just as difficult as finding errors in your code by inspection.

What it comes down to is that a formal specification is a program we don't know how to compile.

The exceptions to this are specifications that are non-constructive; they define an allowable behavior without defining how the result is computed. An example would be a specification for TCP that specifies that the data must be presented to the receiving program in the same order it was sent; the behavior is simple but the underlying mechanisms are complicated. However this is often not what the specification looks like. More usually its like the specification of a bank transaction, which says that afterwards the sending account must be debited and the receiving account credited. Well gee!

The real problem is that the "correct" behavior of the program is complex and contingent, and making sure you have covered all of the issues during requirements gathering is very difficult. And you can't put a formal specification in front of the customer and say "Is this what you want it to do?" because they can't read it, any more than they can read source code.

</comment><comment><USER21> A program is wrong if it doesn't meet its explicit requirements, plus certain common implicit requirements for good engineering (unless they are explicitly waived by the former).

An example of an unwritten requirement might be, say, that the word processing program doesn't violate the user's privacy or security. That might not be on the list of functional requirements for a word processor, but would be implicit.

The problem is that requirements can be deficient in some ways. The program is the most visible deliverable related to the requirements and so it takes the blame for requirement problems.

Requirements can be outright wrong and that's when they are 1) contradictory in some way (there exists a subset of the requirements which cannot all be simultaneously implemented) or 2) unclear: they have multiple different interpretations (unintentionally) and such.

When requirements are clear consistent, then they are subject to opinion: someone would like the requirements to be more complete. Or for some of them to be something else entirely. This turns into a criticism of the program: why isn't it that way, rather than this way. People blur the boundary between this kind of criticism and a criticism of correctness. "How can this be a correct word processor; it has only three levels of undo?". (But the requirement specification was written such that it calls for three levels of undo; how can the program not be correct on grounds of that requirement?)

</comment><comment><USER22> I went on a similarly themed rant [1] a while ago when talking about why static analysis is important, mostly out of frustration that my coworkers seem to think it's largely unnecessary.

Trying to get people to listen makes you feel like Cassandra. No one listens even though you're right. lol

[1] [https://donatstudios.com/StaticAnalysis](https://donatstudios.com/StaticAnalysis)

</comment><comment><USER23> This article makes some useful and clear distinctions, but it's worth pointing out that the goal of level 3 (guaranteed compatibility with new versions) is impossible even in principle when most libraries and environments don't have formal specifications that they guarantee they will stick to in future versions.

For example, there's no guarantee a web app will work in a new browser or even a new version of a browser. Browser vendors try to avoid breakage for _most_ apps but not necessarily _your_ app. They will make backward-incompatible changes to rarely used API's.

A web app usually will work with a new browser, but this is an argument based on statistics, not logic. There is good reason to run automated level 1 tests against beta versions of browsers, to get an early warning of breakage.

Reasoning based on API specifications has a lot in common with mock-heavy testing. It can sometimes find logic bugs that are your own fault, but it's no good at finding breakage that is not your fault (but may still be your responsibility).

</comment><comment><USER24> There are in fact more levels - the definition of "level 3" is hand-wavy enough that it may capture everything, but there surely is at least a level 4, illustrated by the recent Hawaii missile alert: the software worked "as designed", but if it's easy to misuse it, can you actually argue that it was "correct"? Somewhat different (and ironically, illustrated in the article itself) are the very-reasonable-but-wrong assumptions about the environment: Take the case of Microsoft Windows & SimCity - who fixed the bug? Microsoft did... for all intents and purposes, even if in a technical/theoretical sense the Windows memory manager was "correct" \- in a very practical sense, it was buggy and needed to be fixed. This occurs in practice far more frequently than we are willing to admit.

<comment><USER25> UI design is a different disciplines than software design, the Hawaii missile alert issue was a UI issue the software presenting the UI worked as intended. The issue is that we consider UI design as software and we perform UI testing (which is not even testing the UI but the software underneath) and we say everything is good we are ready for prod.

<comment><USER24> It's really just an easy-to-understand symptom of the general problem: if you write/design software that is easy to misuse, that's really a faulty software. If you want a different example - I think Tony Hoare's "billion-dolar mistake" statement is an admission of the fact that 'null' can really be interpreted as a language design bug. Technically speaking, a language design can't be buggy if it's coherent - it just "is". But in practical, everyday terms - the fact that null leads to lots of problems, very often, could/should be considered a "language design bug".

That was kinda' my point. The article claims that "bug" is not just "coding errors", and I agree - and furthermore, I say that "design considerations are still bugs by that definition"

<comment><USER25> I don't agree with the author, IMO bugs are coding error, the crash or the bad behaviour coming out of it is just a symptom. Not having any symptom does not mean that I do not have any defect/disease, with the appropriate set of tests the doctor could find that I have a disease but with no symptoms. To come back to the auth example on simcity, the software had a coding error and the proof of it is that when the symptoms were visible (with the windows 3.1 malloc version) we needed a change in the code to fix the error. The other only category that do not fell under coding error for me is design/architecture error and Hawaii issue fell into that category and it's not bug because it do not prevent us from use the software as intendant it just make the user more error prone or not able to add feature easily or wait too long or worst, no symptom at all until you want to modify expand the software.

<comment><USER16> NFRs or Non Functional Requirements are root cause of bugs in most of the cases. Functional requirements are easy to meet. It is NFR where our assumptions come into picture. As an example consider selecting improper data type to represent something. When this datatype fails to accommodate given quantity/ overflows creates the bug. But this will not happen immediately. Even such issues can easily escape rigorous testing. Check 911 outage case for that matter [1]. I think it was more than just a coding error - A bad design decision. [1] [https://www.theverge.com/2014/10/20/7014705/coding- error-911...](https://www.theverge.com/2014/10/20/7014705/coding- error-911-fcc-washington)

<comment><USER24> > Functional requirements are easy to meet.

That really depends. Coding against specs is just like walking on water: easy, if frozen :)

<comment><USER16> Yeah .. I mean apart from 'Functionality' these are to be taken into consideration; [https://msdn.microsoft.com/en- in/library/ee658094.aspx](https://msdn.microsoft.com/en- in/library/ee658094.aspx)

But again ... You try to make system foolproof and nature will create better fools :-D

</comment></comment></comment></comment></comment></comment></comment><comment><USER26> This is kind of my argument to champion logical robustness over design. Design feels good and logical robustness is hard and difficult.

But the latter can be achieved and some cases the design must be discarded in some ways to achieve it.

I took a grad course about formal verification. Basically, there are ways to mathematically ensure a program will never go wrong.

[http://old-www.cs.dartmouth.edu/~cs50/data/tse/wikipedia/wik...](http://old- www.cs.dartmouth.edu/~cs50/data/tse/wikipedia/wiki/Formal_verification.html)

</comment><comment><USER27> I would still argue level three does not exist - future proofing is futile over the short or long term, and only maintainance is the solution. Good article otherwise though!

<comment><USER14> This doesn't really work as a blanket statement. Future proofing and trying to guarantee bug-free code is worth something -- for example if I'm building a space shuttle to go to the moon, I want some degree of certainty that software bugs will not cause that mission to fail, and I might be willing to spend a lot of time and money to ensure that doesn't happen.

I think a more accurate statement of this sentiment is that investing time and effort into preventing future bugs and problems stops being worth it after a certain point (and perhaps earlier than many software engineers would think).

<comment><USER28> Interesting read about the level of effort and process invested in the Space Shuttle's software (~1996): [https://www.fastcompany.com/28121/they-write- right-stuff](https://www.fastcompany.com/28121/they-write-right-stuff). For a TLDR, this answer ([https://space.stackexchange.com/questions/9260/how-often- if-...](https://space.stackexchange.com/questions/9260/how-often-if-ever-was- software-updated-in-the-shuttle-orbiter#answer-9271)) is great.

My favorite excerpt: The Shuttle software consists of ca. 420,000 lines. The total bug count hovers around 1. At one point around 1996, they built 11 versions of the code with a total of 17 bugs.

</comment></comment></comment><comment><USER29> Designed to fail?</comment>