Ask HN: What are the craziest war stories you've ever come across? - <AUTHOR> <comment><USER2> During the cold war there was a story to the effect that Digital Equipment Corporation had a security feature in its VAX minicomputers that disabled them in the eastern hemisphere by sensing their longitude. That was before our current GPS infrastructure was operational.</comment>


Extremely simple productivity tool I wrote - <AUTHOR> http://www.twogoals.com

<comment><USER2> pfft, mine's better

<http://blog.extension.ws/onegoal.html>

<comment><USER3> I trump you all with my webapp: Nihilism!

</comment></comment><comment><USER4> I'm curious:

What tasks did you manage to procrastinate on while putting this app together?

</comment><comment><USER5> Reminds me of TASCK. <http://tasck.com/>

</comment><comment><USER6> +ve. I really enjoyed how the text area border and shading appear and disappear when you tab between them. And I am not easily amused.

-ve. On a HD monitor, it almost doesn't fit on the screen. Trying in in a smaller window, only the first goal appears - even after closing the instructions.

-ve. When closing the instructions, the text of the goals is not moved (though the headings are). I'm using FF 126.96.36.199, linux.

However, your main focus is the productivity of the app, and any remarks I make on that would uninformed, as I think it would take a trial of at least several days to tell (1) how helpful the "two goals at a time" approach actually is for a specific person; and (2) how helpful this tool is for supporting that approach. But I like the idea, and I like the execution.

</comment><comment><USER7> Hmmm....I like the idea of having two goals to switch back and forth from, but I'm not seeing how your app is any different than putting a post-it note on my computer screen. In fact, a post-it note on the computer screen might be a little bit better about keeping me focused, simply because it would always be there, staring me in the face accusingly as I procrastinate by reading HN.

Of course, the fact that I have to babysit myself may be more of a reflection on me than on your app...

</comment><comment><USER8> Why no more than 2 goals? Is this number arbitrary or is there any reason for it?

<comment><AUTHOR> Not arbitrary per se. I like having two goals because then I can directly compare the goals when making a decision on what to try to accomplish. It becomes an either-or decision. If I am in the mood to complete something quickly, I can look at both goals and pick the one with the shorter time investment. I actively try to position goals against each other so that they help me stay balanced (e.g. one goal is fitness related, one goal is work related). Having 3 goals tends to introduce too many points of comparison for me.

<comment><USER9> Why not just one goal (viz. much more immediate focus)?

<comment><AUTHOR> One goal means you have no choice in what you are focusing on. At least with two goals, I can pick the better of the two to fit a specific mood or situation I am in (e.g. maker's versus manager's time per Paul's recent essay).

</comment></comment></comment></comment><comment><USER10> I'm going to have to try it out and see if it inspires me, but you win the first test, which is that this is a very, very sexy app.

</comment><comment><USER11> The design is broken on IE8

<comment><USER12> The support for standards is broken on IE8.

</comment></comment><comment><USER13> Not bad! :-) A nice mnemonic tool, anyway. See it once and never forget.</comment>


A few more details on Reddits recent troubles from ex CEO Yishan - <AUTHOR> https://np.reddit.com/r/TheoryOfReddit/comments/3d2hv3/kn0thing_says_he_was_responsible_for_the_change/ct1fsoi?context=3

<comment><AUTHOR> Yishan also commented a few days ago with this: [https://np.reddit.com/r/AskReddit/comments/3cs78i/z/cszjqg2](https://np.reddit.com/r/AskReddit/comments/3cs78i/z/cszjqg2)

</comment><comment><USER2> I never understood why everyone jumped on the Pao hate train... She never seemed like she was in the wrong.

</comment><comment><USER3> popcorn tastes good</comment>


A Killer Adversary for Quicksort (1999) [pdf] - <AUTHOR> http://www.cs.dartmouth.edu/~doug/mdmspe.pdf <comment><USER2> I used this technique to prove libc++'s implementation of std::sort is O(n^2). There's still an open bug report for this in libc++: [https://llvm.org/bugs/show_bug.cgi?id=20837](https://llvm.org/bugs/show_bug.cgi?id=20837).

On a related note, I'm talking to the libc++ and libstdc++ developers about replacing introsort with pdqsort ([https://github.com/orlp/pdqsort](https://github.com/orlp/pdqsort)) as the implementation for std::sort. It solves the worst case in a subtly different (and potentially more efficient) way than introsort. Although that's not the real selling point.

EDIT: I forgot I still use my old username on hacker news. To prevent confusion, I'm also the author of pdqsort.

</comment><comment><USER3> I made an implementation of this algorithm as a university assignment;

here's a vanilla implementation of Quicksort [https://github.com/leonid- shevtsov/uni-programming/blob/mast...](https://github.com/leonid-shevtsov/uni- programming/blob/master/kr_may_2012/custom_qsort.cpp#L27)

and here's the function to generate data that causes the custom implementation to go O(n^2) [https://github.com/leonid-shevtsov/uni- programming/blob/mast...](https://github.com/leonid-shevtsov/uni- programming/blob/master/kr_may_2012/generators.cpp#L78)

</comment><comment><USER4> I've had bad commercial Quicksort implementations go N^2 on constant data, [http://www.win-vector.com/blog/2008/04/sorting-in-anger/](http://www.win- vector.com/blog/2008/04/sorting-in-anger/) . Kind of sours one on the "Quicksort is essentially elegant" idea.

</comment><comment><USER5> I don't get how you could create an adversarial input in advance for an implementation that uses a randomized-partition (index of pivot drawn from a uniform distribution).

Can anyone fill me in?

What this article describes (for that, as far as I can tell) is an adversary that modifies the input while quick sort is working. How realistic is that?

<comment><USER6> That algorithm is only used to create an input pattern. When it is fed back to the same sorting function, it will cause it to go quadratic. If your target is using the same sorting function it will do the same on their side.

This attack is realistic. I have tried it on the glibc qsort, generic quicksort, and Visual Studio qsort, and they were vulnerable.

<comment><USER5> I'm interested in the way you use the word "attack."

I was looking at it from the perspective of you could never run into an input that would consistently sort in O(n^2) using randomized-quicksort.

But your perspective (maybe this article's perspective) is that some malicious adversary could force the sorter to do extra work by knowing in advance the steps that they will take. Am I getting that right? Like from a flops security stand point?

If so, why care about this situation? This only seems like a realistic scenario in very weird domains, like amazon web services messing with everyone's calls to some standard sorting code to charge them more cents for compute time or something...

<comment><USER7> If I'm not mistaken, the attack is aimed at a quicksort implementation where the pivot value is chosen as a median of first, middle, and last values. It would not work on randomized quicksort, of course.

</comment></comment></comment></comment><comment><USER8> What's the problem? From D. Knuth's _The Art of Computer Programming: Sorting and Searching_ ,

(1) if sorting n records by comparing pairs of keys, then the Gleason bound shows that on average can't sort faster than O( n ln(n) ).

(2) Heap sort sorts n records in both worst case and average case in time O( n ln(n) ).

Net, when sorting by comparing pairs of keys, in main memory, on a simple machine architecture, with a single processor, ..., can't improve on Heap sort.

So, just use Heap sort. That's what I do.

<comment><USER2> Big O hides all constants. A hybrid algorithm using Quicksort for the heavy lifting is O(n log n) in the worst case, but is a significant amount faster than heapsort - mainly due to cache effects.

See pdqsort for examples (benchmarks included): [https://github.com/orlp/pdqsort](https://github.com/orlp/pdqsort).

It shows that on average it's twice as fast on the random input distribution.

<comment><USER8> Now and long the usual criterion of performance is big-O notation, and that is what I considered, with the Gleason bound and heap sort and, thus, showed that, with various common assumptions, can't do better than heap sort. As far as I know, I was correct.

So, to claim to beat heap sort, have to set aside some of the usual assumptions and the big-O criterion.

Quicksort is great with a cache since as it has great locality of reference when working with the _partitions_ that fit into the cache. But, worst case of Quicksort is still O( n^2 ) so what happens if Quicksort encounters such a partition?

Just intuitively, it appears that heap sort has a tough time making much exploitation of usual cache designs. We know that. There is a modification of heap sort that helps it work better when have to do virtual memory paging.

I used to get torqued at considering big-O, and did this just because it ignores constants; as a programmer, I worked hard to do well with such constants. But in the end I gave in and gave up and just accepted big-O notation as the most appropriate, simple, single criterion. And, for judging algorithms by how they do with cache exploitation, I gave up on that, also: Or, broadly it's the responsibility of such speedup techniques to work on ordinary code written for a simple processor architecture, not the responsibility of such code to do tricky things to exploit tricky architectures.

In the land of big-O, a factor of only 2 is considered not very exciting.

If relax some of the assumptions, then can beat heap sort and O( n ln(n) ): Use radix sort. That was the sorting algorithm of the old punch card sorting machines. E.g., if have 100 billion records to sort where each key is an alpha-numeric string 10 characters long, then radix sort does all the work in just 10 passes of the 100 billion records. Or for keys m characters long, can sort n records in O( nm ). So that's faster when m < ln(n). Or, to make the arithmetic easier, m < log(n). But log(100 billion) = 12, so radix sort should be faster with m = 10 and n = 100 billion.

So, for a _hybrid_ sort routine, consider also radix sort.

Am I excited about radix sort? Nope!

<comment><USER2> > But, worst case of Quicksort is still O( n^2 ) so what happens if Quicksort > encounters such a partition?

I'd strongly suggest you to read the readme I wrote for [https://github.com/orlp/pdqsort](https://github.com/orlp/pdqsort), which explains in detail how I beat heapsort (and other sorting algorithms). It also shows how I prevent the O(n^2) worst case.

> I used to get torqued at considering big-O, and did this just because it > ignores constants; as a programmer, I worked hard to do well with such > constants. But in the end I gave in and gave up and just accepted big-O > notation as the most appropriate, simple, single criterion.

We have already established that O(n log n) is the lower bound, and we have reached this lower bound. This is where big O stops being useful. A metric that compares equal for every relevant algorithm (mergesort, introsort, pdqsort, timsort, smoothsort, heapsort) is not a useful metric.

> In the land of big-O, a factor of only 2 is considered not very exciting.

I live in the land of real-world performance, powered by actual benchmarks. In this land a factor of 2 is very exciting.

> So, for a hybrid sort routine, consider also radix sort.

I worked in the scope of std::sort, which is strictly a comparison sort.

<comment><USER8> I assumed that we were talking about _in place_ sorting.

"I feel your pain." As I tried to explain, the first time I saw big-O notation taken seriously as the main metric for evaluating the actual running time of actual code on actual data on an actual computer, I had your reaction, that the constants are important and the big-O criterion, not good.

There's another point: The silent assumption of the big-O criterion is that we are interested in (A) something _fundamental_ about algorithms, just the algorithms, and not (B) actual running time of actual code on actual data on actual computers.

And big progress in algorithms is also important and, as we know, in some cases can give much better performance gains in real computing than anything a programmer can do without the big progress.

And we have a great example: There were days before heap sort, shell sort, quicksort when the in place sorting algorithm people coded were bubble sort or something closely related and also O(n^2). Then in practice, the difference was just huge.

Early in my career, I ran into that at Georgetown University: A prof had coded up some software for teaching statistics and had used the IBM Scientific Subroutine Package (SSP) for a most of the actual calculations. One of the SSP routines was to find _ranks_ , and it had two loops, each essentially bubble sort. In testing, the thing ran all lunch time.

Well, the data to be ranked was 32 bit integers, and an array index was a 16 bit integer. So, I was able to do a tricky overlay of two 16 bit integers on the 32 bit data, use heap sort, and get O( n ln(n) ). In actually running time on nearly any possible real data, my code as so much faster than IBM's SSP that I _blew the doors off_ the SSP.

Lesson 1: O( n ln(n) ) instead of O( n^2 ) can be much better in practice.

Lesson 2: Progress in big-O in algorithms can be terrific stuff.

Back to practice, early in writing the software for my startup, I tried to write a polymorphic version of heap sort. I wrote in Microsoft's Visual Basic .NET. For the data type to be sorted, I passed just the type _object_. The software ran correctly right away. Then I did some careful timings -- the software commonly ran ballpark 10 times longer than I would have guessed. What the heck? Well, the run time was smart enough to figure out the actual data type and do the comparison, but the overhead here was enormous. Then I learned that for _polymorphic_ code I was supposed to write some _interfaces_ , one for each data type to be sorted, and for sorting a particular data type pass the corresponding interface. Okay. My confusion was that that use of an _interface_ didn't sound _polymorphic_ to me and sounded no different than what I'd long done passing _entry variables_ in PL/I and Fortran. Okay, for polymorphism, use _interfaces_. And in the code of the interface, have to work essentially without _strong typing_ , essentially with untyped pointers. Okay -- been there, done that, in both PL/I and Fortran; I was surprised that a serious _object oriented_ language with _polymorphism_ would have essentially just syntactic sugar over what I'd been doing in PL/I and Fortran. Okay. Lesson learned: There are cases of hype in parts of programming languages.

Heck, in PL/I my approach to sort an array of PL/I structures would be to pass a PL/I structure that had an element variable that was an entry variable to a procedure that would do the comparisons. That is, could have some conventions that would let PL/I structures be _self-describing_. Then could write code that was more general. Maybe under the covers, that's just what's going in the Microsoft _common language run time_ (CLR) that Visual Basic .NET used for me without letting me know \-- more _syntactic sugar_?

So, when I rewrote my polymorphic heap sort to do the comparisons with a passed _interface_ , the performance got okay. Still, I have non-polymorphic versions for the more important element data types, and they are faster in just they way you emphasized. Yup, been there, done that.

So, I, too, was concerned about actual running time of actual data. But for the _algorithm_ itself, I was still using just heap sort and didn't try to write a _hybrid_ routine that sometimes might exploit, say, radix sort.

On the pros and cons of using big-O for the only criterion, there's a big example in linear programming: In practice, the simplex algorithm is fantastically fast. Intuitively, in practice, the early iterations in effect _focus_ what to do to get to the optimal solution (assuming feasibility, no unboundedness, etc.). But due to some work of Klee and Minty, the worst case of simplex is exponential and just awful. Intuitively the Klee and Minty examples trick simplex into making really bad choices!

So, there was research to find a polynomial algorithm for linear programming. Eventually there was an _ellipsoid_ algorithm that was polynomial but the constant was so high that whenever in practice ellipsoid beat simplex both ran too long to be practical.

So, really, the concern about simplex and the effort for ellipsoid was as progress just in algorithms and in the big-O criterion. And in practice, right away, the constant was so large that ellipsoid was a flop.

Still, in algorithms, people are straining to do better in the sense of the big-O criterion. Of course the biggest effort here is to find an algorithm that shows that P = NP, maybe the one of the most important problems in both math and computer science, based on big-O for some polynomial.

With all of that, I decided in my own work, for something as simple as sorting, just to go with heap sort, maybe even a polymorphic heap sort. Indeed, with all the emphasis on polymorphism, people can't be very concerned about constants! :-)!

<comment><USER2> I'm impressed you can write such a long story yet address none of my points. You should consider becoming a politician.

The only relevant piece of information I could find in your anecdote is this:

> I assumed that we were talking about in place sorting.

If we limit ourselves to in-place sorting algorithms then we still are left with block sort, pdqsort, introsort and heap sort, all of which run in O(n log n). My argument still holds.

<comment><USER8> I wrote that long post trying to explain my attitude on sorting software from 50,000 or so feet up and, in particular, why I have been happy just to use heap sort and forget about looking for anything faster on average.

I was reluctant to read the documentation in your GitHub submission if only because in my software development I have never needed or used GitHub.

Also, I was reluctant to believe that there could be any version of quicksort that would have worst case running time of O( n ln(n) ).

Why reluctant to believe?

First, sure, the usual version of quicksort has us select a _pivot_ value for a partition from a "median of three" keys from that partition.

Second, sure: For a _good_ pivot value, we want essentially the median of the keys in the partition we are trying to split into two partitions. And, sure, the median of three approach to selecting a pivot value is an approximation to the median we really want and, thus, a relatively good pivot value. So this approach to selecting a pivot value promises on average to get faster average running times. Fine. Faster on average is good. Terrific.

But this pivot selection rule says next to nothing about worst case running time, and, for claiming worst case running time of O( n ln(n) ), this is a biggie issue.

Third, with this median of three approach to selecting pivot values, we can think of _bad_ arrays of input keys that will cause quicksort to run in time no faster than O( n^2 ). Then maybe we can think of other ways to select pivot values that result in a new version of quicksort, a version that runs in O( n ln(n) ) again on the bad arrays. But with this change, here's the problem: We are lacking a proof that the worst case running time of the new version of quicksort has worst case running time of O( n ln(n) ).

That is, our new version of quicksort is good for some old cases of _bad_ arrays but may have created for itself some new cases of _bad_ arrays. So, with no proof, the new version of quicksort may also have worst case running time of O( n^2 ) like the old version did. The main difference might be that the _bad_ arrays for the new version are more complicated to construct than the bad arrays for the old case.

But I just looked at the file README.MD you suggested. I see two issues:

First Issue:

> When a new pivot is chosen it's compared to the greatest element in the > partition before it. If they compare equal we can derive that there are no > elements smaller than the chosen pivot. When this happens we switch strategy > for this partition, and filter out all elements equal to the pivot.

If I understand this statement correctly, I suspect that for some arrays of input keys, the resulting algorithm won't actually sort the keys. That is, we won't have a sorting algorithm.

Second Issue:

> While this technically still allows for a quadratic worst case, the chances > of it happening are astronomically small.

For proving worst case running time of O( n ln(n) ), "astronomically small" is irrelevant. Maybe your remark "astronomically small" is just a side comment and not relevant to PDQSORT having worst case running time of O( n ln(n) ), but from your documentation I can't easily tell.

> A bad partition occurs when the position of the pivot after partitioning is > under 12.5% (1/8th) percentile or over 87,5% percentile - the partition is > highly unbalanced. When this happens we will shuffle four elements at fixed > locations for both partitions. This effectively breaks up many patterns. If > we encounter more than log(n) bad partitions we will switch to heap sort.

For this and the associated documentation, I don't see a solid argument that PDQSORT has worst case running time of O( n ln(n) ).

For some work, a big-O guarantee on worst case performance is a biggie, as in crucial to human life. Such a guarantee is essentially a theorem in applied math called _computer science_. A good example of how to prove such theorems is, of course, in D. Knuth, _The Art of Computer Programming, Volume 3, Sorting and Searching_.

Again, I have been happy just to use heap sort and forget about looking for anything faster on average.

<comment><USER2> > If I understand this statement correctly, I suspect that for some arrays of > input keys, the resulting algorithm won't actually sort the keys. That is, > we won't have a sorting algorithm.

You don't understand the statement correctly. However, this is not a trivial realization.

Because pdqsort always recurses on the left partition first it means that every element to the left of the current recursive call is equal to or less than every element within the current recursive call. So if we find that the selected pivot is equal to an element before the current recursive call we can conclude that there can only be elements equal to the pivot, and not smaller, in the current recursive call.

> Maybe your remark "astronomically small" is just a side comment and not > relevant to PDQSORT having worst case running time of O( n ln(n) ).

Correct.

> For this and the associated documentation, I don't see a solid argument that > PDQSORT has worst case running time of O( n ln(n) ).

There is a very simple argument. The 'bad partition counter' is initially log(n). If we encounter a bad partition, we can do up to O(n) work. This can happen log(n) times. So we can do up to O(n log n) work on bad partitions. If we then encounter another bad partition, we switch to heapsort, which is O(n log n).

If we encounter less than log(n) bad partitions Quicksort performed well enough to be O(n log n).

For a similar approach, read up on introsort.

<comment><USER8> Okay.</comment></comment></comment></comment></comment></comment></comment></comment></comment>


A not-so-obvious reason to apply to YC - <AUTHOR> http://yvonne.posthaven.com/a-not-so-obvious-reason-to-apply-to-yc

<comment><USER2> >YC is at its core a group of great people.

Correct me if I'm wrong but I actually thought that was _the obvious_ reason to most applicants.

A $120k investment from YC doesn't provide that much runway. That kind of money doesn't give much wiggle room for founders to splurge on luxuries like Aeron chairs and fancy cappuccino machines. That amount is to allow a small team to live in near-poverty in the SF Bay area for ~6 months and maybe also buy some tech necessities like AWS EC2 time. Basically, provide some breathing room for founders to not worry about rent and put the focus on building their idea. What other reason to work 60+ hours a week in modest conditions unless it was the networking and interaction?

<comment><USER3> I would suspect that this is non-obvious to people who view YC as a structured, semi-guaranteed route to success, the way many people view a degree from a prestigious university. I know many people who are 'interested' in startups and crave some kind of validation that they are a real entrepreneur before sinking their teeth in. My university even offers a 1 year diploma in entrepreneurship. Madness! As though formal training will help you make the hard decisions you face as a founder.

<comment><USER4> > As though formal training will help you make the hard decisions you face as > a founder.

Formal training means a way to structure your thoughts and assess risks. Don't dismiss it out of hand.

<comment><USER3> Point taken. Education is of course a valuable thing - but a year's worth of instruction on entrepreneurship after you've already got a degree?

<comment><USER5> Why not? If someone has a degree in something technical I could imagine following a curriculum consisting partly of corporate finance management, fundraising, HR and other corporate issues for a year could be valuable, especially if they offer night classes or something like that so that you can still be working on your main idea.

Most college new grads are not exactly CEO material from the get-go.

<comment><USER3> I would assert that a recent graduate who wants to be an entrepreneur is mostly doing themselves a disservice by studying those things. It focuses your thoughts on how to run a business rather than how to solve a problem or turn an industry on its head.

Sure, many of those things could come in handy in the future - but there are far more difficult things which you also have to learn "as you go".

<comment><USER5> Entrepreneurship isn't limited to VC-funded moonshots.

Lots of people just want to be their own boss and run a viable business.

<comment><USER6> Great point.

Interestingly, I see several tech startups of this nature started by folks having a deep understanding of a specific business problem due to their prior work experience tend to create such startups.

As a service provider for small businesses, I see many amazing bootstrapped services & products come up around the world, that serves a very specific need for a small subset of customers. These viable businesses tend to make enough for the needs of 2-3 folks for a long time. I have a strong inclination towards finding many of them as a service provider because they just tend to be some of the best customers with great ROI.

</comment></comment></comment></comment></comment></comment></comment></comment><comment><USER7> Knowing all the people mentioned in this post, I don't doubt a single one of these stories. Every one of those people is selfless and eager to help.

Jessica has done an amazing job of instilling a culture at YC that selects for people who are friendly and eager to help others.

</comment><comment><USER8> A not-so-obvious excerpt I took away is this...

>Before joining YC, I had been working on my startup for 6 months and a few of my customers were YC companies.

I think most people are aware that the _startup market_ is quickly growing, and it is not what the author suggested by any means, but I think entire startups can be created to cater to the startup market...in fact YC is probably so large that a startup could probably succeed by catering solely to YC startups. For example, I applied to YC once with an incorporation/legal service idea, with the thought that even serving as a Delaware Registered Agent (~$100/year) and filing the Delaware annual compliance documents (~$100) on behalf of the YC companies - a captured market - would generate ~$100k/year, which is probably peanuts from a investors point of view, but a solid life style business that has the potential to cater to ever Delaware C-Corp startup.

Its kind of like the 49er days and the old saying: "In a gold rush, some entrepreneurs dig for gold, and some sell shovels."

<comment><USER9> Funny enough, there's a YC-funded company that does exactly that: [https://www.clerky.com](https://www.clerky.com)

The list of customers on their homepage is mostly YC companies.

<comment><USER8> I was aware of clerky, but in all honesty I thought they were not operating any longer. Having clicked the link you posted, I am very impressed with the changes they have made in web design and product presentation/description.

</comment></comment></comment><comment><USER10> Very cool of Yvonne to share about her pivot, not many founders (yc or not) are open about that.

The core message is so true. YC partners (and the founder community) is incredibly genuine, very eager to help out. This scales past being a "small company" as well -- the Collisons are some of the most approachable founders ever.

</comment><comment><USER11> I attended a workshop hosted by the Center for Applied Rationality, and the most valuable part of that was getting more social contact with the kind of people who are into that sort of thing.

Like, spending four days and $4000 to have a dozen short conversations with Anna Salamon is probably a good buy. It's rather hard to evaluate, since you're getting things that are difficult to buy with money.

I don't have any experience with YC, but I imagine that it's a similar sort of deal - especially since I've heard that they focus on community-building.

</comment><comment><USER12> Nurturing relationships while struggling to master a subject or anything else for that matter is the main reason for going to any school in the world.

The key here though is the struggling aspect. If a school does not make you struggle to the point where you look for connections, I doubt then there is a point to the school itself.

Further, every major founder of every major startup has always looked back at the single biggest reason to their success are the relationships they acquired, nurtured, and mastered.

</comment><comment><USER13> once upon a time, all of silicon valley basically operated like this.</comment>


Delicious.com loses its holy grail - <AUTHOR> http://briancray.com/2009/08/17/delicious-front-page-fails/ Delicious.com has lost value to publishers. Why promote it on your blog at all? <comment><USER2> I just realized that:

A) I don't even use delicious for anything but storage, basically; it's where I keep most of my browser bookmarks, via a plugin in my browser.

B) If delicious isn't making money hand over fist, it may not survive more than a couple more years.

I need to back up my delicious bookmarks, post-haste.

<comment><USER3> There was that other bookmarking service whose DB got corrupted a few months back. Backing up is always a good idea.

I've grown to depend on Delicious bookmarks too much, since I work from multiple locations.

That said, I use the front page of Delicious maybe a couple of times a year, tops.

</comment></comment><comment><USER4> I have never, to my knowledge, been on the Delicious front page. However, they're the only social bookmarking I have ever had success with. Slap that beautiful, beautiful Delicious button which says "X people have saved this" (social proof!) on a meaty reference article aimed at geeks and you'll get a long-tail stream of tech-oriented linkerati visiting that page for years, rather than the typical big-one-minute-gone-the-next tidal wave of ADHD chipmunks hopped up on crystal meth.

This has resulted in a few of my reference articles getting more than enough links to justify the pixels.

<comment><USER5> Did you custom code that with the API?

I did a bit of searching but haven't come across a way to add a "save with delicious" type link that shows how many people already have.

Not from delicious nor from anyone else, except as part of one of those big "add a grid of 100 social networks in a big popup when someone clicks share" buttons.

<comment><AUTHOR> Yea those big popups are _annoying_! The only good one is AddToAny.com, which looks at the user's history to only show the ones that the user has visited. :)

For the details of an individual bookmark, see the API <http://delicious.com/help/api> and look for this headline: <https://api.del.icio.us/v1/posts/get>?

<comment><USER6> Hey Brian, Pat from AddToAny. Even without the drop-down menu (which displays the Delicious saves count) I love your implementation. If Delicious can stay relevant we should totally add the # of saves to the share/bookmark landing page as well.

</comment></comment></comment></comment><comment><USER7> Delicious is one of the Web's most under-rated services. I've been a heavy Delicious user since 2004 and it's invaluable to me. Not just to store bookmarks but to find stuff I _didn't_ bookmark that I just remembered about.

For example, let's say I remember seeing a site about an awesome new WordPress theme a few weeks ago. I can go to <http://del.icio.us/popular/themes> and chances are I'll find it. If not, I can go through the tag pages (say, <http://delicious.com/tag/wordpress+themes>) until I find it. Google does not even compare when it comes to finding content in this way.

Even if I backed up my Delicious account and hosted it myself somehow, it still wouldn't have as much value as it does when combined with 100,000+ other people's links.

<comment><AUTHOR> Agreed. From a bookmarker's perspective, I love /popular/tag filtering

<comment><USER8> The /popular/tag algorithm is busted now, and regularly coughs up very obvious stuff (python.org for tag python, iirc.)

I wish they hadn't messed with my algorithms so much.

<comment><AUTHOR> Agreed. I enjoyed that delicious.com was a place I could find _articles_ related to a subject, not the site itself (if that makes sense).

delicious.com is not a stitch of what it was.

</comment></comment></comment></comment><comment><USER5> What is up with those crazy guys that took over Delicious at Yahoo!?

Not only do I not want Delicious to be a Tweetmeme clone, but the front page has a two column layout with an empty second column unless you switch away from the fresh tab... what?

<comment><AUTHOR> Tweetmeme clone is exactly what it has become!

</comment></comment><comment><USER9> This article is garbage. Delicious is not Digg and it's not Reddit and if you're only using it to boost traffic to your site - you have no fucking clue what this service is actually about.

<comment><AUTHOR> lol. Did you read the article? It's from a publisher's perspective, not a bookmarker's.

Just FYI: Neither Digg nor Reddit are only used to boost traffic either. Apparently social media marketing is off your radar.

<comment><USER10> You ask: "So why promote delicious bookmarking at all!?"

Well, it seems to me that you should spend more time asking yourself how to serve your visitors rather than how to serve yourself.

The reason so much of the internet sucks is because publishers spend too much time trying to get people on their site by doing SEO and all that crap, then they crowd up the best parts of their website with obtrusive ads (a bit like the ad bar right above your articles).

Instead of all that, just focus on creating good content. I'm not trying to be mean, that just makes a better internet for all of us.

<comment><AUTHOR> On my blog I explore everything that has to do with designing, developing, and marketing websites. Internet marketing is an important part of an effective website.

Regarding your implication that I don't address the user's needs, one of my blog's primary topics is user experience design. Under that you'll find such posts as "Online community best practices: Reward your top users," "Web form usability: Better form submission feedback with jQuery," and "3 eye tracking studies that influenced my latest redesign." So to imply that I'm not concerned about what my users want or creating good content, you've been mislead.

Good content is important. And so is finding audiences for that good content. You need both. Good content and good traffic.

<comment><USER8> Good traffic is not the same as exploiting sources of traffic. That's actually called spamming.

There's a lot of code in delicious (or at least there was) to prevent that sort of gaming.

<comment><AUTHOR> Would you say that every blog that promotes delicious bookmarking is spamming? That's what I see you implying. If so, you are implicating nearly every popular blog that exists today.

<comment><AUTHOR> "The main reason to save things to delicious is for memory. Sharing is secondary. And getting on the front page or popular were a distant third."

I think the first and second reasons apply to bookmarkers, and the third applies to publishers. For publishers, the primary reason is the front page IMHO.

"So stuff that goes beyond "please bookmark us" - that's what those buttons do - seems dangerous to me. Especially since actual users have the extension or bookmarklets installed and do not need the site buttons."

I can understand this sensitivity. If you look on my blog, I have a simple link that says "bookmark everywhere." But my popular delicious content is no longer rewarded with a front page link.

"I'd seen an enormous amount of shady behavior in and around this so perhaps I am oversensitive. At one point I was spending half my day, every day, dealing with spam on delicious."

Spam sucks hardcore ass. What else can I say?

<comment><USER10> I don't see how you can seriously argue this. You have 10 submissions to Hacker News, and all 10 of them are to your own website.

<comment><AUTHOR> Argue what? I'm not denying that I use social media as part of my inbound marketing strategy. But I engage with the people that comment. Besides, I spend my time writing what I feel are important blog entries. I'd say I do my part for the community I'm a part of.</comment></comment></comment></comment></comment></comment></comment></comment></comment>


Experimental "Never slow mode," Chrome tries to stop Web devs making it slow - <AUTHOR> https://arstechnica.com/gadgets/2019/02/with-experimental-never-slow-mode-chrome-tries-to-stop-web-devs-making-it-slow/ <comment><USER2> Original source of story with link to the commit: [https://www.chromestory.com/2019/02/google-is-testing-a- neve...](https://www.chromestory.com/2019/02/google-is-testing-a-never-slow- mode-for-chrome/)

</comment><comment><USER3> Let's see if Chrome takes this seriously by eliminating _addeventlistener_ and slow abstractions from DOM access, like query selectors.</comment>


Microsoft Ad Monetization platform shutting down June first - <AUTHOR> https://social.msdn.microsoft.com/Forums/windowsapps/en-US/db8d44cb-1381-47f7-94d3-c6ded3fea36f/microsoft-ad-monetization-platform-shutting-down-june-1st <comment><AUTHOR> Microsoft Advertising is the only realistic ad platform for Microsoft Store apps and this eliminates a huge swath of business models. IMO the writing is on the wall for Microsoft Store apps.</comment>


A difference between Haskell and Common Lisp - <AUTHOR> http://chrisdone.com/posts/haskell-lisp-philosophy-difference <comment><USER2> Actually Common Lisp supports a gazillion of different programming styles.

The version with small functions, similar to the Haskell version:

        (subseq
         (remove-if
          (complement #'numberp)
          (butlast list 3))
         0 5)

In above Common Lisp code, we use four different functions which do one task:

        * subseq sequence start &optional end => subsequence
        * remove-if test sequence => result-sequence
        * complement function => complement-function
        * butlast list &optional n => result-list

For different approaches see Common Lisp libraries like Series or Iterate... Iterate is LOOP on steroids.

[http://series.sourceforge.net](http://series.sourceforge.net)

[https://common-lisp.net/project/iterate/](https://common- lisp.net/project/iterate/)

> This is known as composability, or the UNIX philosophy. In Lisp a procedure > tends to accept many options which configure its behaviour.

Check out the UNIX man for tail, grep, ... to see how strange above quote about 'unix philosophy' is. In reality Unix commands are programs with obscene amount of configuration options, sometimes piping data as text around, sometimes glued together by strange shell languages...

<comment><USER3> > Check out the UNIX man for tail, grep, ... to see how strange above quote > about 'unix philosophy' is.

The "UNIX philosophy" is good, it's just that UNIX doesn't really follow it.

The C and shell programs that make up UNIX commands are actually UNIX's own little _programming language_ , complete with ad-hoc data types.

Look at `cat` for example. It might as well be `str + str...`. Or look at `grep`, it's basically `filter` or `reduce` at heart. But it has to do this per-line, and it has no metadata about the line, it literally just works on string contents. The `head` and `tail` commands aren't much different than `take` and `drop`. Heck there's even a `sort` command.

That's why shells that actually use a programming language (e.g. eshell) don't seem so crazy to me. To be honest, I use eshell way more than I use bash, and half the functions I use there are written in lisp rather than bash or C.

<comment><USER2> > The "UNIX philosophy" is good, it's just that UNIX doesn't really follow it.

It never did, beyond some examples in beginner books.

> Look at `cat` for example. It might as well be `str + str...`. Or look at > `grep`, it's basically `filter` or `reduce` at heart.

Then look at the options of `cat`. On my Linux system cat has a -n option, which numbers the output lines. If it were following the 'UNIX philosophy', this option would not exist.

<comment><USER4> UNIX may have been about small commands ("cat -v", anybody?), but its most important property is COMPOSABILITY. You could use small programs to build larger programs, allowing you to do things by gluing together code that you would previously have to write new programs to do. It made this very easy, and you could also do it from within C, so it wasn't an either/or situation. This is something your namesake system could have learned to do. The Right Thing isn't always the right thing.

<comment><USER5> That was already available in Xerox PARC systems, by making use of function call composition in Interlisp-D REPL, Builders in Smalltalk transcript or live debugger in Mesa/Cedar.

The UNIX composition is only a novelty for those that never saw other OSes that surfaced at the same time. After all UNIX just adopted the idea from MULTICS.

<comment><USER6> _" The UNIX composition is only a novelty for those that never saw other OSes that surfaced at the same time. After all UNIX just adopted the idea from MULTICS."_

One could certainly chain programs through intermediate files. My understanding has it that pipelines were new in Unix, and Wikipedia agrees: "The pipeline concept was invented by Douglas McIlroy and first described in the man pages of Version 3 Unix."

<comment><USER5> Yes the concept was popularized by UNIX, but anyone that spends time doing computer archeology will find similar patterns in other OSes, like the ones I listed.

Don't forget that back then computing was developed in silos, with knowledge only shared at conferences or when researchers switched universities/companies.

So it was quite common that researchers across the globe would come up with similar discoveries.

</comment></comment></comment></comment></comment></comment></comment><comment><USER7> Is this really a philosophical difference? Granted, I've only used Clojure as far as Lisps go, but composability seems to be something that's emphasized.

Rather than

       (remove-if-not #'p xs :count 5 :start 3)

It seems to me like most Clojure users would do something like

       (->> xs (drop 3) (filter p) (take 5))

which is much closer to

       take 5 . filter p . drop 3

<comment><USER8> Minor nitpick. Technically, this:

        #(->> % (drop 3) (filter p) (take 5))

Is equivalent to:

        take 5 . filter p . drop 3

<comment><USER7> Is

        take 5 . filter p . drop 3

An anonymous function call in Haskell? I don't know the language (although it's on my to-learn sequence).

<comment><USER8> It's an anonymous function, which it not being called.

</comment></comment></comment></comment><comment><USER9> Common Lisp has these kitchen-sink functions and macros because it was a standard developed by a committee whose goal was to incorporate several popular implementations of Lisp that each had several decades worth of of cruft. Lisp was big enough business at the time that having several mutually incompatible versions of Lisp was making knowledge sharing and business difficult. And having a standard was important for many reasons.

 _update: spelling and..._

The real philosophical differences between Haskell and Lisp are basically apples and oranges. Lisp's composition strategy is the recursive application of symbolic expressions... the famous EVAL and APPLY. I don't know enough about the theoretical underpinnings of Haskell to make any kind of apt comparison but my intuition suggests that to do so would be moot. They're just too different.

<comment><USER2> > standard developed by a committee

You know that Haskell was developed by a committee and was designed to bundle the various research streams on lazy/statically typed/ purely functional programming languages?

From the Haskell history:

> ... to discuss an unfortunate situation in the functional programming > community: there had come into being more than a dozen non-strict, purely > functional programming languages, all similar in expressive power and > semantic underpinnings. ... It was decided that a committee should be formed > to design such a language...

[http://haskell.cs.yale.edu/wp- content/uploads/2011/02/histor...](http://haskell.cs.yale.edu/wp- content/uploads/2011/02/history.pdf)

Now about Common Lisp:

> it was a standard developed by a committee

That's basically nonsense.

The core of Common Lisp was designed by mostly five people (the 'gang of five': Scott Fahlman, Guy Steele, David Moon, Daniel Weinreb, and Richard P. Gabriel) in 1981/82\. This group was supported by various Common Lisp implementors - around 30 people. Steele wrote the book on Common Lisp the Language and published it in 1984.

The ANSI Committee to expand and clean-up the language was set up years later.

> incorporate several popular implementations of Lisp that each had several > decades worth of of cruft

That's also nonsense. Common Lisp is mostly based on a single language: Lisp Machine Lisp (aka Zetalisp), which is an extended version of Maclisp. Groups developing other successors to Maclisp joined: NIL, Spice Lisp and S1 Lisp. Lots of things in Zetalisp were new in Lisp and it took quite some time to get it into Common Lisp, which itself also brought new things into Lisp (like type annotations, sequences, ...).

So Common Lisp is directly based on Lisp Machine Lisp, which only was a few years old. NIL, S1 Lisp and Spice Lisp were brand new and morphed into Common Lisp. Spice Lisp was morphed into CMU Common Lisp, which forked the now popular SBCL.

The style to use keyword arguments in parameter lists was brand new in Lisp. It appeared in Lisp Machine Lisp just a few years before. LML did get it from an obscure Lisp dialect called MDL ('Muddle').

> Lisp was big enough business at the time that having several mutually > incompatible versions of Lisp was making knowledge sharing and business > difficult.

Lisp was emerging as an implementation/research language for the military. DARPA called for a Lisp standard, because they got several Lisp applications and each had its own version of Lisp...

<comment><USER9> As always, thank you for the clarification. My 6 month old is teething and waking me every 40 minutes starting around 3am. I'm mostly recalling from hazy, caffeine fueled memory. I like your posts -- so informative.

I admit to knowing little about Haskell's history. I had assumed it was an outgrowth of ML -- itself having an interesting history intertwined with the LCF theorem-proving system. Thanks for the clarification.

>> it was a standard developed by a committee

> That's basically nonsense.

In my much-abridged comment, yes I understand it could sound that way. I was referring to the entire process but mainly the ANSI committee. I was also under the, apparently mistaken impression, that there was more than one Lisp involved.

      In April 1981, after a DARPA-sponsored meeting concerning the splintered Lisp community, Symbolics, the SPICE project, the NIL project, and the S-1 Lisp project joined together to define Common Lisp. Initially spearheaded by White and Gabriel, the driving force behind this grassroots effort was provided by Fahlman, Daniel Weinreb, David Moon, Steele, and Gabriel. Common Lisp was designed as a description of a family of languages. The primary influences on Common Lisp were Lisp Machine Lisp, MacLisp, NIL, S-1 Lisp, Spice Lisp, and Scheme. Common Lisp: The Language is a description of that design. Its semantics were intentionally underspecified in places where it was felt that a tight specification would overly constrain Common Lisp esearch and use.

Quite right.. it's all there in ye old Hyperspec. Thank you for pointing that out.

Cheers.

<comment><USER2> > My 6 month old is teething and waking me every 40 minutes starting around > 3am.

Congratulations!

</comment></comment></comment></comment><comment><USER10> I'm not sure I agree at all with the premise of this article. Languages are a syntax they don't have "Philosophies." They may have design elements that reflect or support the philosophies of their designers(e.g. functions as first class citizens), but the author doesn't provide critique on what they believe these to be instead looking at a few std lib functions that some yahoo implemented.

Look at something like java. Java has a core set of design elements. It was built by a person with some philosophical leanings("Everything is a class", "Checked/Unchecked exceptions being different things", "no first class functions") Then it has standard libraries(i/o, collections, threading/synchronization) each of these was built by a person with there own set of biases and understandings. The original Collections implementation has lots of mutable data structures then later Josh Bloch decided that he didn't like that anymore and stopped adopting "immutability" as core design philosophy. Immutability was not previously considered important when evaluating a java implementation. What you end up with is a mish mash of different opinions that only gets more different as you go.

Some 3rd party libraries like Guava didn't jibe with the Philosophical leanings of the language itself and looked for work arounds. They went as far as to create their own implementation of functions as a first class citizen in a language that was expressly designed to omit them. Some commonly used Android libraries do this as well.

My point here is that "language" can mean lots of things. It can refer to the language itself, its run time, the syntax+runtime+community. What is idiomatic and on, on, on. People and groups of people have the philosophies. I'd like to see the author point to something a little more critical about the differences between these two concepts. This premise is a little muddled.

</comment><comment><USER11> Some of the Lisp and Haskell code examples aren't doing the same thing. For example, these two do completely different things:

        (remove-if-not #'p xs :count 5 :start 3)

        take 5 . filter p . drop 3

I don't like Haskell, and it's not immediately obvious to me how to achieve what the Common Lisp is doing, so I won't bother, but one way of writing the Haskell in CL would be:

        (loop for x in (subseq xs 3)
              when (p x) collect x into result
              until (= (length result) 5)
              finally (return result))

Another option would be to use subseq and remove-if-not, etc, but without lazy evaluation, the loop version will be more efficient. And though some Lisp people dislike LOOP, I like that it's easy to read, if not always easy to write ;-)

About the topic of the article, though, to me this seems like less a philosophical difference than a result of Haskell not having easy to use default and optional parameters. There's currying, but it's not a great substitute, and it's a little awkward to use.

I like the Common Lisp way, even if it's crufty at times, because the keyword arguments to functions like remove-if-not and sort are easier for me to use than chaining a half dozen functions. I don't have to think about whether I need to call filter before or after take or drop, etc. At the end of the day, it's a personal preference, though.

Another advantage is that I don't have to "roll my own" for common idioms.

</comment><comment><USER12> IMHO whoever wrote this article should change the title to "A philosophical difference between Haskell and Common Lisp". There are a lot of LISPs and not all of them follow Common Lisp's philosophy.

</comment><comment><USER4> And us schemers would express it like this:

(cut take 5 (filter <> (drop 3 <>)))

or, without the cut macro:

(λ (pred list) (take 5 (filter pred (drop 3 list))))

And yes, in most schemes, you can use λ as a synonym for lambda. Sometimes you have to define it first, though. Anyways, that looks a lot like the Haskell to you, doesn't it? It doesn't have the laziness, but other than that...

Oh! Oh! I almost forgot! you can also use the thrush combinator, if you use the clojurian package:

(λ (list pred) (->> list (drop 3) (filter pred) (take 5)))

And yes, I think this is all the ways you can do this in scheme. CHICKEN specifically. With some various macros packages.

Oh, wait! I forgot we have function composition, too, but you'd have to use lambda or cut constantly to make the thing work because we don't have currying. So these are all the ELEGANT ways to make this in chicken scheme. With the cut SRFI. Or clojurian. And srfi-1, which is basically standard. and it's better than the examples given, because pred and list aren't pre- specified.

<comment><USER13> It's easier for people propping up one language over another language family to ignore the similarly easy ways to do things in prominent members of that language family. ;)

<comment><USER4> Well, yes. Lisp and CL are not the same.

If anything, this has made me rethink possibly going over to common lisp, which I was thinking of for the larger stdlib, because SBCL is very fast, supports TCO, and you can disable case insensitivity.

<comment><USER13> Common LISP was made to smooth over the differences of the ancient LISP's plus standardize their situation a bit. If those don't matter to you, then the alternatives are often better. SBCL being one of them. If I get back into LISP, I think the Racket Scheme community looks like it's delivering most bang for buck in terms of what the tools can do after investing time learning them.

<comment><USER4> Most schemes don't have a lot going for them in terms of libraries, which is the primary reason I'd want to go over to Common. I really don't like racket, for mostly aesthetic reasons. It seems a bit over complicated, trying to stuff a lot of cutting edge research into its core, and forcing you to learn about 6 different models at once just to understand what its documentation is saying. Its OO system is apparently lackluster, especially since most schemes fork tinyCLOS for OO, and syntax-case is too complicated for its benefits.

I'll stick with CHICKEN for now. Its module system may be a bit awkward at times, (you can't cleanly bind all your dependent modules into one executable), but it's much more minimal, and while its documentation may not be the best, at least I can understand what its saying.

</comment></comment></comment></comment></comment><comment><USER14> I'm not entirely sure that this is due to philosophical differences. The fact that Haskell is lazily evaluated makes writing functions that do only one thing much easier, since there is no performance hit for writing code like:

      take 5 . filter (not . p) . drop 3

In a strictly evaluated language. This would involve iterating over the list three different times. (Kind of not really, since take 5 isn't going to be that expensive.)

<comment><USER15> > there is no performance hit for writing code like:

> take 5 . filter (not . p) . drop 3

That doesn't seem to be the case in my testing. Writing this out as an explicitly recursive function sped things up 3x on GHC -O3. (Dropping 10^8, taking 10^7.)

FWIW, I also tested on Rust, Python (PyPy3) and Java (OpenJDK) with iterators, iterators and streams, respectively. Python and Java were about as fast as the manually recursive version, and Rust was two orders of magnitude faster than that. And half of the time in Java was spent boxing, because Java can't reify types away like Haskell.

It's true these are all using opt-in laziness, unlike Haskell's lazy-by- default, so it's not a fair comparison. But I also see little reason to believe that there's "no performance hit", given that that's exactly what I saw.

</comment></comment><comment><USER8> The difference is not one of "philosophy", but rather of _using the right types_. Haskell's so-called "list" type constructor is actually a type constructor of _streams_. Unsurprisingly, streams are much better than lists if you want to do stream processing.

<comment><USER16> >Haskell's so-called "list" type constructor is actually a type constructor of streams.

Most papers consider streams to be lists _without_ a terminal constructor. Haskell lists are a superset of streams. All streams have infinite lengths, but only some lists have infinite length. (Again, this just comes down to definition, but this is how most functional papers describe it.)

<comment><USER8> In chapter 4 of his book, Okasaki defines a type of both finite and infinite streams (which is really just the type of Haskell "lists"), and, in the remainder of the book, he only uses finite ones.

A stream of infinite length, which you call "stream" without qualification, is what I call "a function on the natural numbers". (Well, up to isomorphism.)

<comment><USER17> Speaking of things that the Haskell type system lets you make explicit, the isomorphism between streams and functions from the natural numbers means that streams are "representable functors" in the jargon of category theory. [1] Knowing that a data type is representable allows you to immediately build a bunch of other interesting structures on the data type. [0]

[0] [http://covariant.me/notes/rep- functors.html](http://covariant.me/notes/rep-functors.html) [1] [https://pamiz.wordpress.com/2014/02/13/the-functor-of- infini...](https://pamiz.wordpress.com/2014/02/13/the-functor-of-infinite- lists-is-representable-by-natural-numbers/)

<comment><USER8> Nitpick on both links. They say `alpha . beta = id = beta . alpha`. This is wrong: `alpha . beta` composes to a _different_ `id` from `beta . alpha`.

</comment></comment></comment></comment></comment><comment><USER18> Perhaps it's just me, but I don't see that Haskell and Lisp are that similar, other than...

1\. They're both programming languages.

2\. They both allow you to pass functions as arguments to other functions.

Am I missing something here? Why are the two linked? Is it because Lisp is seen as the birthplace of functional languages (because of point 2)?

<comment><USER19> Yeah, people talk about "functional languages" as if they're a unified thing. IMO the differences between the strongly typed ML/Haskell tradition and the Lisp tradition are as big as the differences between either and "OO languages" or "imperative languages", but that's not the way it's usually presented.

<comment><USER4> That's nonsense. Lisp in the functional style vs. Haskell is two different implementations of what are at their essence the same ideas. However, lisp is multi-paradigm, which complicates the comparison somewhat...

<comment><USER18> What are the essential features that they share?

<comment><USER4> They're both primarily based on lambda calculus. Although haskell on typed lambda calculus. They both emphasize purity over mutations. They both are designed to make higher-orderisms idiomatic.

But the point isn't so much the features they share. I'd be the first to admit that Lisp and Haskell are very different. But functional programming in both is very much based on the same ideas. Claiming that they're as different as OO vs imperative is like saying that washing dishes by hand is as different to using a dishwasher as football is to baseball.

</comment></comment></comment></comment></comment><comment><USER20> Title is misleading; this is about Common Lisp in particular.

<comment><USER21> Well, Common Lisp is Lisp.

Scheme, Clojure etc. are lisps, with lower-case "l" ;)

<comment><USER4> That's just wrong.

Clisp is the most popular lisp bearing the name, but the LISP, Lisp, or lisp family includes Scheme, and Clojure. if you just refer to Lisp, you may be referring to Clisp, the lisp family, or maybe even LISP 1.5, the lisp equivalent of V7 unix.

<comment><USER2> Clisp is an implementation of Common Lisp. Common Lisp includes a core of the original Lisp. Lisp programs from the 60s can either be run or ported to Common Lisp with little or no effort.

Clojure is FULLY incompatible with any other Lisp dialect or Lisp derived language. Porting code means 'rewrite'.

<comment><USER4> Oh. Sorry. I was abbreviating Common Lisp. Whoops. Anyways, that's like saying that Go, Plan 9 C, D, Java, and Cyclone aren't in the C family, because you can't run ANSI C '99 on them and have it work. The Lisp family is diverse.

<comment><USER2> See C++, Objective-C and a bunch of other languages actually in the C family.

They all share C. Real basic C.

'The Lisp family is diverse.' You interpret it in a way to make it practically meaningless.

<comment><USER4> No. The lisp family is a real thing. They all share homoiconic syntax, singly linked lists as a primary data structure, and most of them support syntactic extension through macros.

While the validity of some of my examples may have been questionable, how is Plan 9 C not in the C family? and just TRY to compile ANSI C on a P9C compiler without significant modification.

<comment><USER2> Significant modification is something different than complete rewrite.

The Lisp languages share a common core language, code, ideas, literature, community.

Derived languages like Logo, Dylan, Clojure, Racket, ... have their own core language, their own code, their own ideas, their own literature and their own community.

<comment><USER4> Yes, but they also share a history and a set of syntax and ideas... Well, except Dylan, syntax-wise. But ultimately this is an argument about terminology. And the majority of people would say that scheme is a lisp. A lisp. Not a language derived from lisp, that is independent. A LISP. in the LISP family, because that is a thing. And if you want proof that that is what most people think, you need only check Wikipedia: [https://en.wikipedia.org/wiki/Category:Lisp_programming_lang...](https://en.wikipedia.org/wiki/Category:Lisp_programming_language_family)

<comment><USER2> THat's what people thought twenty years. Today this does not matter anymore.

> Yes, but they also share a history and a set of syntax and ideas...

Clojure:

        user=> (cons 1 2)
        IllegalArgumentException Don't know how to create ISeq from: java.lang.Long  clojure.lang.RT.seqFrom (RT.java:542)

        user=> (cdr '(1 . 2))
        CompilerException java.lang.RuntimeException: Unable to resolve symbol: cdr in this context, compiling:(NO_SOURCE_PATH:2:1)

What I say...

<comment><USER4> ... Well, maybe you could be right. I'm not sure. I do know that when most people say "lisp," they think of scheme, clojure, etc. as in that category.

I like to think that I can admit I may be wrong, and in this case I think I might be wrong.

</comment></comment></comment></comment></comment></comment></comment></comment></comment></comment></comment><comment><USER22> I'm confused by the last example. There are no elements greater than 5 in the list (1 2 3 4).

Also, I'm not sure why they used takewhile instead of filter in the last haskell part.

<comment><USER23> I assumed it to be a typo; i.e., it should say "less than".

`takeWhile` is different to `filter` in that is returns the input list until some element matches the predicate, whereas `filter` returns all elements that match the predicate. For example, if the predicate is `(< 5)` and the input was `[9, 2, 3, 6]`, then `takeWhile` would return an empty list, but `filter` would return `[2, 3]`.

<comment><USER24> He should have used a better input, though, maybe 1, 2, 3 ,4 ,5. With the given input it's a bit confusing, it's equivalent to filter . even [1..4]. Also, the Lisp loop should have been checking for (>= i 5), to be equivalent to the Haskell example.

</comment></comment></comment><comment><USER25> The biggest difference between Haskell and Lisp is that Lisp is multi- paradigm, while Haskell is not. Haskell is more opinionated, and makes a bunch of decisions for you (that you can choose to work around/sugar/hack until Haskell looks like something else/does what you want).

All the other things that Haskell comes with - strong typing, monads, lazy evaulation, can be written into common lisp, but whether you need them is often questionable.

<comment><USER26> They can't be written in Lisp well, or at all. Strong typing with inference can't be bolted on. Monads that take advantage of this typing can't be bolted on. Changing Lisp to have lazy semantics across the board ain't gonna happen.

You might be able to write a Haskell interpreter from scratch that interacts with the Lisp environment, but you can't feasibly transform Lisp itself.

<comment><USER27> Nobody told Dr. Tarver[1]. He built a series of lisps with tight integration with the underlying Common Lisp platform featuring a strong typing system rooted in the propositions of Sequent Calculus[2][3]. Type delcarations are only on top level forms with all locals inferred. There seems to be work to improve this in Shen Professiona's new compiler. Shen offers tight integration with the underlying platform (although it has been ported to a number of runtimes (SBCL, CLISP, and V8 amongst others)[4]).

[1] - [http://www.shenlanguage.org/history.html](http://www.shenlanguage.org/history.html)

[2] - [https://en.wikipedia.org/wiki/Sequent_calculus](https://en.wikipedia.org/wiki/Sequent_calculus)

[3] - [http://www.shenlanguage.org/learn- shen/types/types_sequent_c...](http://www.shenlanguage.org/learn- shen/types/types_sequent_calculus.html)

[4] - [http://www.shenlanguage.org/download_form.html](http://www.shenlanguage.org/download_form.html)

<comment><USER26> I guess I wasn't clear in my post.

Usually when people say "you can do X in Lisp", they mean that you can integrate a feature into the language.

Don't have list comprehensions? Write a macro.

Don't have "thrush" syntax? Write a macro.

Don't have lazy evaluation? Write a... err. You can't write a macro[1]. You can't write something which completely changes the entire calling semantics of the language. What you can do is make a little sub-language which uses different values and objects from Lisp, but you can't magically make the standard library support lazy evaluation.

Same with types and type inference (a la Haskell).

Same with many other things.

Of course, _obviously_ , you can write a compiler that compiles to Common Lisp, or C, or Scheme, or COBOL. But writing a compiler -- while Lisp is good at that -- isn't really taking advantage of what it usually means for Lisp to be extensible.

[1] For those who are ready to call out the many "lazy" libraries in Common Lisp, perhaps even my own, you're missing the point. You can make a new version of DEFUN and a new version of FUNCALL. But that doesn't make REMOVE- IF, SUBSEQ, MAPCAR, LIST, CONS, etc. lazy. As such, many, if not most, of the benefits that laziness brings, don't get applied to the language at large.

<comment><USER27> What are macros if not custom compiler extensions?

Sure, Shen is enough of a compiler extension to be its own language, but I can call Common Lisp code from Shen and call Shen code from Common Lisp. Doing either isn't very different from calling a native function (calling Shen from Shen is similar to calling CL from Shen).

As far as [1], I don't really see this as an issue with CL. CL has not made the effort to rewrite its core in terms of generic functions. If this were to be done, drastically changing CL's behavior for random new types would be relatively painless. But the way that the current CL standard chose for its library and core functionality isn't to use generic functions everywhere. As such, it is expected that if you drastically change implementation, you end up with separate functions. I think this is a huge draw of something like Clojure/JVM with its interfaces/protocols as a base level over a far more mature system like CL/SBCL.

</comment></comment></comment></comment></comment><comment><USER28> > _In Lisp a procedure tends to accept many options which configure its > behaviour. This is known as monolithism, or to make procedures like a > kitchen-sink, or a Swiss-army knife._

This is the case in some areas of the Common Lisp language; it is not true of the Lisp, as a family of dialects.

There are plenty of examples of Lisp functions or operators that just do one thing: `cons`, `car`, the `lambda` macro operator.

       ;; CL
       (remove-if-not #'p xs :count 5 :start 3)

       ;; Haskell
       take 5 . filter p . drop 3

       ;; TXR Lisp: a dialect with ties to CL:
       (take 5 [keep-if p (drop 3 list)])

       ;; Compose the functions using opip macro
       ;; (result is a function object):
       (opip (drop 3) (keep-if p) (take 5))

TXR Lisp's library functions don't have the :count, :start and whatnot. In fact, there are no keyword parameters, only optionals. If you want to default an optional on the left and specify a value of one on the right, you can pass the colon keyword to explicitly default:

       (defun opt (a : (b 1) (c 2)) ;; two optional args
         )

       (opt 4 : 5)  ;; b takes 1, c takes 5.

The colon is just the symbol whose name is the empty string "", in the keyword package. It makes for nice sugar and has a couple of uses in the language. Note how in the defun it separates required args from optionals.

(Anyone else cringe at "UNIX philosophy"; how silly! This is the Unix philosophy: let's reduce everything to a string in between processing stages and parse it all over again, with simplifying assumptions that it always has exactly the format we are looking for without actually validating it.)

<comment><USER29> That's the JWZ perspective, but if you add strong typing you can basically turn the "string" into "SomeType" and process records like that. If you look at languages with a |> operator they often act like that.

</comment></comment><comment><USER30> Real general question about function composition - when you're comfortable with it, how do you think it to yourself, or say it to yourself, like what's your shorthand mental model?

I was able to really intuitively get comfortable with unix piping a long time ago, so instead of:

take 5 . filter p . drop 3

I'd be thinking, ok, take a thing, drop the first three, grep (or whatever), now take the first five. It felt intuitive because each step solved a problem, and then I'd move forward into the future, and have to only think of one additional solution (head -5) assuming I did the previous steps right.

Meanwhile, take 5 . filter p . drop 3 is in the opposite order, from right to left.

Maybe I'm just saying that left association is easier to think about than right association. Don't you feel that weird recursive bump in your head, the increasing mental stack, when you are dealing with function composition and right association?

<comment><USER31> I like imagining functions as various pipes, the real world ones. Compose is that short pipe that connects two others. I imagine that the data comes from the right and needs to be output on the left of the function. I then can read such line (take 5 . filter p . drop 3) twice. Once following the order of creation (ie. we're laying our pipes first) and then the second time in reverse, following the data and function applications. That did the trick for me when I first learned about function composition coupled with (auto)currying.

</comment></comment><comment><USER32> Lisp actually does have stream fusion, but it has it in the form of a library![0]

[0] [https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node347.html](https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node347.html)

</comment><comment><USER33> Haskell has strong typing and lazy evaluation, which makes it easy for functions to _take only one argument_ at a time. Although a function could take a tuple parameter, it's usually rewritten to take each component of the tuple as a separate parameter, which makes the strong typing and built-in currying simple, higher structures like monads possible, and a syntax to suit this style. Lisp functions and macros OTOH _must be variadic_ to enable the homoiconicity of the language. It's therefore much more difficult for parameters to be typed, or to curry them.

These two styles make Haskell and Lisp mutually incompatible, unless they use clunky addons like Template Haskell macros or Typed Clojure annotations. The pure form of each language, however, is based on two mutually exclusive foundations, i.e. strongly typed auto-curried parameters vs variadic untyped macro parameters. The poster child of each language, i.e. monads and macros, thus also don't mix well with each other.

<comment><USER34> > higher structures like monads possible

What is it about the features that you mentioned that makes monads possible? Lisp (or at lease Scheme and Clojure, which I'm familiar with) make monads trivially possible -- just as they are in Haskell. They're not as useful because those languages have other mechanisms that make monads largely unnecessary, but they're no less easy to express.

<comment><USER19> Well you can't have implicitly resolved typeclasses without a static type system. You could pass around explicit dictionaries with all your values or some such, but most of the value of explicitly sequencing relatively minor effects is only there if you have an extremely low-overhead way of doing so, and a system that can verify the correctness of that sequencing at compile time.

<comment><USER35> > You could pass around explicit dictionaries with all your values or some > such, … if you have an extremely low-overhead way of doing so

A lot of that plumbing could be hidden from the user given the right dynamic features.

[http://www.eighty-twenty.org/2015/01/25/monads-in- dynamicall...](http://www.eighty-twenty.org/2015/01/25/monads-in-dynamically- typed-languages.html)

<comment><USER19> It sounds like racket generics are at least partway on the road to a type system. And those placeholder values seem a bit greenspunny - I'm not sure how they'd interact with native racket features (e.g. macros). (I mean, you are right, but in a degenerate sense you could implement typeclasses in any dynamic language by having your program construct strings and writing a Haskell compiler in that language that executed those strings at runtime. So the more relevant question is whether monad techniques can be used effectively in an idiomatic program).

<comment><USER35> The big difference is that generic dispatch is resolved dynamically.

I haven't yet found myself reaching for monads in Racket (or writing much non- Redex Racket code) since tonyg wrote that post, so I don't know if there are any odd interactions to watch out for.

</comment></comment></comment></comment></comment></comment><comment><USER36> Having worked on one of the largest common lisp projects I have to say this is spot on. And monolithism it's not just visible on level of functions it's visible on higher level. Common lisp nudges you to write monolithic applications and it's crucial to keep many details in one head (in case of big project - many heads).

Also I think Clojure is scheme, so overall approach is different.

<comment><USER8> No, Clojure isn't Scheme. Scheme has hygienic macros and pattern matching on syntax, which in turn Racket's `syntax-parse` library makes even better.

Clojure... well... has that ugly `defmacro` kludge.

EDIT: I was being kind of unfair. Clojure also has kickass collections in its standard library, which Scheme doesn't have.

</comment></comment><comment><USER37> Minor nitpick. The loop at the end could make the range by 'for i from 1 upto 4' instead of a list literal to more similar to the haskell code.

<comment><USER38> That wouldn't be the same. The point was filtering a list (which could contain anything, not just a sequence from 1 to 4).

The example seems a bit strange to me. Why does it have the check for i being less than 5, when the problem is "get all elements _greater_ than 5, then just the even ones of that set.". Was it supposed to be "remove all elements greater than 5..."? (edit: although the code would then only work for sorted lists; I think it'd be better to just loop over the whole list and have "(and (< i 5) (evenp i))" as the condition for collecting)

</comment></comment><comment><USER39> You have to be clear about which Lisp. Clojure and Scheme are Lisps, and their focus is very much towards simplicity and the use of combinators.

The complex, do-it-all-in-one-huge macro is a Common Lispism, not a Lispism.

Secondly, Clojure, like Haskell, is focused on sequence abstractions, not lists. Sequences can include collections, streams, observables, sockets and many other kinds of process that can be modelled as an event stream.

<comment><USER2> > Clojure and Scheme are Lisps

Basically new languages with strong Lisp influence.

> very much towards simplicity

Scheme maybe until the early 80s. Later it grew to Common Lisp size and beyond. See Scheme R6RS which is a complex language with tons of features and still underspecified.

> The complex, do-it-all-in-one-huge macro is a Common Lispism, not a Lispism.

Not really. Macros appeared in Lisp in the early 60s and many Lisp dialects have used it in complex ways. For example the 'famous' LOOP macro of Common Lisp actually was developed in Interlisp in the early 70s (as a part of 'Conversational Lisp' / CLISP), redesigned in Maclisp/Zetalisp and then brought into Common Lisp. The original Common Lisp in 1984 did not even have that macro in the language description, it was standardized several years later - after a search for a better alternative failed.

<comment><USER4> R6RS was basically DOA, with only 3 or 4 implementers (Guile, Ikarus, Ypsilon, and (partially) Racket) actually going along with it. Most of the other implementers, most notably CHICKEN's Felix Winkelman, refused. R7RS is now split into a small core, and a large standard library for practical, as opposed to teaching, use, whose development STILL isn't done.

<comment><USER2> The R7RS homepage says something different:

>This is the home page for R7RS, the Revised⁷ Report on the Algorithmic Language Scheme. This version of Scheme has been divided into a small language, suitable for educators, researchers, and users of embedded languages; and a large language focused on the practical needs of mainstream software development.

>The report on the small language was finalized on July 6, 2013. It is available in PDF format and as LaTeX source code. There are errata.

>The development of the large language is still in progress. For details on the development process of both languages, see the Scheme Reports home page and the Working Groups home page.

<comment><USER4> Yeah, that's what I said. Large still isn't done.

</comment></comment></comment></comment></comment><comment><USER40> The main difference is: it is trivial to build an efficient Haskell implementation on top of Common Lisp, keeping interoperability with the rest of the system. And it is impossible to do it the other way around, to build a Lisp on top of Haskell.

<comment><USER18> [https://wiki.haskell.org/Haskell_Lisp](https://wiki.haskell.org/Haskell_Lisp)

<comment><USER40> I'm talking about an _efficient_ implementation with a full interoperability with the host. Interpreters and standalone compilers do not count.

</comment></comment></comment><comment><USER41> Or you could use Shen and spend less time philosophizing

[http://www.shenlanguage.org/](http://www.shenlanguage.org/)

<comment><USER42> Could you elaborate? What about shen makes you say this?

<comment><USER8> Shen is like C++ in that it's bolted on top of a less typeful language (except this time it's Common Lisp, rather than C), and is "type safe" as long as you don't deliberately use a number of escape hatches.

<comment><USER4> That's wrong in just about every respect.

Shen is a PLATFORM INDEPENDANT (not clisp based) language with an emphasis upon functionalism, a novel and very powerful type system based on sequent calculus, and OPTIONAL type checking, IF you want it. It is platform independant because it is built upon an incredibly simple lisp that you can build an interpreter for on top of almost any platform, so long as you can guarantee TCO.

It really is lisp flavored haskell.

<comment><USER8> The point to type checking is protecting abstractions, and it being "optional" reduces its value to zero.

<comment><USER4> Wrong. Sometimes type checking is uneeded. In addition it can make prototyping easy: Write the code, add the annotations later. Of course, you need some discipline to make it work, but of what good practice isn't that true?

And if you really hate it, just type (tc +) at the start of your code. Magic!</comment></comment></comment></comment></comment></comment>


Show HN: GitHub's user status as Weather Widget - <AUTHOR> https://github.com/narqo/github-weather <comment><USER2> "A silly program to update a GitHub user's status with the current weather" On point, but I like it!</comment>


People Make It So Hard to Ditch Plastic Straws - <AUTHOR> https://www.bloomberg.com/opinion/articles/2019-07-15/people-make-it-so-hard-to-ditch-plastic-straws <comment><USER2> The best solution is one that eliminates the need for a straw entirely.

Seattle mandates compostable straws or no straws. The rather innovative thing that Starbucks did was to create a lid that is essentially the adult version of a sippy cup. Now that I've experienced that, I much prefer it to straws.

</comment><comment><USER3> Why don't we make them out of a polymer that will degrade quickly?</comment>


Why don't C++ programmers like Go as much as former users of dynamic languages? - <AUTHOR> http://commandcenter.blogspot.in/2012/06/less-is-exponentially-more.html

<comment><USER2> This is the fourth time in less than 10 hours that this has been posted. At least the first three used the correct title. Here is the first post with comments, <http://news.ycombinator.com/item?id=4158865>

</comment><comment><USER3> I wasnt aware that anyone liked GO</comment>


Portland's Mayor Is Tear-Gassed by Federal Forces on Another Night of Protests - <AUTHOR> https://www.npr.org/sections/live-updates-protests-for-racial-justice/2020/07/23/894591409/portlands-mayor-is-tear-gassed-by-federal-forces-on-another-night-of-protests <comment><USER2> Why are Federal agents in Portland -- because of threats like this: "Rioters Set Fire to Federal Courthouse in Portland" [https://www.nationalreview.com/news/rioters-set-fire-to- fede...](https://www.nationalreview.com/news/rioters-set-fire-to-federal- courthouse-in-portland/) .</comment>


Apply HN: IMe – Social networking based on activities - <AUTHOR> IMe is a new social networking platform which helps bring people from same location with same interests together. Users will be able to create competitive one on one or team events and invite other users from the same location. Along with players and participants, having an event created on a social platform will also bring audience for the events.
Along with planning and organizing events, serious players will get to collect the stats and ratings from the events. Having more ratings and stats as proof will help these serious players stand out from others and can fetch them unique opportunities which otherwise might be missed.
In a trending local event, audience forum will be available for sports fans to express their analysis and also to validate the data from that event for serious players. This data and stats can also be used by coaches and recruiters who are constantly looking for new talents. <comment><AUTHOR> We highly appreciate your opinion and suggestions on our project</comment>


Ex-Googlers have spent 2 years secretly solving 'the hardest problem in banking' - <AUTHOR> http://uk.businessinsider.com/google-engineers-thought-machine-vaultos-core-banking-platform-fintech-2016-7 <comment><USER2> _Today, most banks run on old systems, some dating back to the 1970s, strapped together with metaphorical gaffer tape. Banks are too afraid to update them for fear something going wrong._

I wouldn't say banks are too afraid, I'd say they are being prudentially cautious. Banks have _very_ different standards when it comes to reliability. This isn't about some system losing clicks, or likes, or whatever. Here, every single mistake can cause significant financial loss.

Just think what would happen when client trades get stuck at some point during execution. If market prices develop unfavorably in the minutes or hours until the error is fixed, the bank has to take the loss, on every single trade.

Almost all people I know who work in banking (including myself) would love to get rid of our legacy systems, but that's much easier said than done. Especially since many of those legacy systems are inter-connected.

 _VaultOS is based on "smart contract" technology that allows people to tailor their own products such as mortgages, loans, and overdrafts._

Those are nice new features and all, but none of that means anything if you can't replace the existing core features first.

<comment><USER3> Yup, exactly this. And cautious is putting it nicely, I think. Tack on regulatory risk and you have an extremely strong headwind against any sort of major change.

</comment></comment><comment><USER4> Heavy on buzzwords, light on details. Is it literally an operating system? Is it blockchain tech? Both? Neither?

<comment><USER5> > VaultOS is a bit like Amazon Web Services or Google Drive, but for what's > called "core banking" — the technology that allows banks to hold deposits > and accounts. Essentially, it's the heart of banking, around which > everything else is built.

I hypothesis they are considering what I've been working on for about 4 years now, which is basically a blockchain + container/VM/repo deployment mechanism for infrastructure services. The people who were most interested in what I was presenting were financial institutions. The primary reason why was because that software shouldn't change a lot as it handles money. Changes to software that handle money typically == loss of funds. If you build a piece of software that gets deployed and versioned using smart contracts/DAOs/whatever blockchain thing, you end up with a fairly robust way of managing financial systems, and the various contracts those systems manage, including cryptocontracts running in the containers launched by other contracts.

In other words, the immutability of the blockchain should be able to be applied to infrastructure provisioning. My sense is that is what is happening here with VaultOS.

<comment><USER4> Do customers today look at an ATM and say "Oh it's running the 2.7 release! OK, I'm good then!"? It'll be interesting to see what perceived value there may be.

<comment><USER5> Do you ever look at reality and wonder what version it's running? That's where all this is going...and the second it does, those Pokemon we're all chasing become de facto reality.

<comment><USER4> I'm still trying to figure out where to file bug reports and request root access.

</comment></comment></comment></comment></comment><comment><USER6> I think I smell a Fool's Mate:

[http://blog.gardeviance.org/2014/11/fools-mate-in- business.h...](http://blog.gardeviance.org/2014/11/fools-mate-in- business.html)

</comment><comment><USER7> Alright, my turn. The bankers want back-end software that's near 100% uptime, cost-effective, future-proof, flexible for integrations, and secure. They have all of those but cost-effective and flexible. The next architecture will have to do better on those. We'll start with a sort-of, three-tier architecture & client-server model since those have been analyzed to death with tons of tool support for getting them right.

First, the datastore that simply stores raw data everything else depends on. The datastore will be bootstrapped on HP NonStop or OpenVMS clusters to inherit their high-availability. These systems already run banking backends in multiple datacenters with automatic failover and no lost transactions in specific, case studies. Decade plus uptime is not uncommon. They're also way cheaper than mainframes with more support for modern SW & easier to access for ISV's. The software itself will be built to have minimal dependence on underlying platform with tools to rapidly export data, sync with, or switch to a replacement. The will be a licensed copy of Google's F0 RDBMS on OpenBSD & reliable servers rewritten in the manner about to be described. If not, then something similar. :)

The core, banking stack. This is the banking software for withdrawls, deposits, basic security checks, audit events, and so on. Anything that's happening constantly in real-time with high-criticality. This will be contracted to Altran/Praxis who will apply Correct-by-Construction method to produce it in C, SPARK, and Rust simultaneously. Best available tools for static analysis and testing will be applied to each to catch whatever others miss. Prior work in just SPARK has almost no defects. A combination of simplified components with extra checkers should further reduce that. The protocols will be contracted to Galois Inc to do in TLA+ and Haskell. Especially generic, secure, messaging protocols to replace SWIFT. Altran will implement anything Galois finalizes to integrate with rest of system. Paid, peer review by people with track record of finding esoteric flaws will occur for each of the deliverables.

The client, presentation, and application layers' hardware will be SAFE architecture (crash-safe.org) or CHERI CPU's (CheriBSD). These will be implemented with Leon3-FT processors on a Silicon-on-Insulator node with ChipKill and ECC RAM. They will run minimal OS's created for embedded systems with proven reliability & performance. Those will be modified to support security features of processors plus support security labels for users & apps. Each machine, a la DiamondTEK LAN, will have PCI cards (or on-SOC HW) that authenticates users on trusted path, checks system integrity, end-to-end encrypts all data, and especially tags/checks packets with security labels of users & apps. Specific hardware modules will exist with data diodes to constantly sniff network, transaction, and audit trails to check them against a security policy. Similar one for reliability and performance of network.

The software stack will akin to REBOL's reblets and container apps. The apps will be isolated on microkernels with basic, GUI forms. These apps will be developed in both a safe, systems language plus an information flow language like SIF. The systems will be shown with analysis & testing to be free of common errors. Information flow analysis will prevent common forms of information leak and security breach. The apps will integrate with trusted hardware to pass labels along. The server apps will pick up those labels & continue to factor them into their operations. Over time, the tooling will mature to automate these operations with only basic annotations by programmers plus a formal, security policy by administrators.

People still need to get work done in terms of Internet research, report writing, and so on. OSS apps for these will be ported to the platform overtime. Meanwhile, the client-nodes will support physical virtualization whereby those nodes can run on a PC with mediated, information sharing and built-in KVM. Users simply press a button to be in a regular desktop. Documents and such will be done in easy-to-analyze formats that are checked by a guard upon transfer. Those files are also labeled. Anything that goes into the trusted machine will be shown in text form for visual confirmation by operator plus automatically sanity-checked & logged for any other auditing. Overall process will be like switching tabs + drag n drop to encourage users to work with security features instead of against them.

The corporate itself will be a non-profit. The charter will put a cap on how much profit it can take with a lean approach to administrative expenses, limits on executive compensation, and limits on management-to-staff ratio. Incoming revenue is to be put into further QA/pentesting of platform, development of it, support to customers, consulting for integration/extensions, datacenters for availability, and so on. The nonprofit will be established in a jurisdiction with strong laws favorable to honest banking plus minimal corruption. Its operations will be audited by third- parties who also have their own, dedicated hardware & cages. These factors will collectively eliminate or reduce the risks of VC-backed sellouts, management cooking the books, top-heavy organizations, and stagnation from lock-in.

OK. So, let's summarize. The hardware itself will be simple but highly reliable. The software is done in languages immune to most coding errors with high-level properties precisely specified, checked, and pentested. The two integrate well to eliminate abstraction gap attacks. The initial backend is software that has over a decade of uptime with modern stuff coming online _if possible_. The non-core apps on client and server encode sensible use into information flow policies that are checked in several places & efficiently. All apps and network are black-box to attackers with tons of defense in depth. Insider risk reduced as they put individual name & reputation on each action with mutually-suspicious auditing they can't remotely sabotage due to data diodes. All of this tech already exists in either prototype or production form with suitable substitutes for prototypes that turn out infeasible to use. It's also legally setup to be more trustworthy in terms of what people will do & long-term benefit. Initial development costs would be _huge_ but the first year without mainframes and SWIFT will probably pay it off. Especially spread out among numerous banks investing.</comment>