Chuck Moore, Extreme Programmer - <AUTHOR> http://www.cs.uni.edu/~wallingf/blog/archives/monthly/2017-10.html#e2017-10-31T15_44_15.htm <comment><USER2> I want to take a moment to reflect on what a great community HN has. It never ceases to amaze me.

The link is from the CS department at the University of Northern Iowa in Cedar Falls, IA. It sounds obscure, but that's my hometown. I grew up a couple blocks away from it. I sat in on classes there. I even know the author's family. That's small town Iowa, for ya.

I never thought I would see anything related to that on here. This is truly a place for all.

<comment><USER3> I work in the fast food industry, don't code, and I'm not even particularly interested in tech, but spend hours reading the articles and comments here.

<comment><USER4> I was a network engineer and would do the same, can't place the exact reason why, but today i am a python programmer doing network automation. I do think HN had a major part to play in this change

<comment><USER5> Network Engineer here too. I learned to code with Python and now do full-time PowerShell automation at work. It completely changed my career. Best decision I ever made.

</comment></comment></comment></comment><comment><USER6> Quote from ([http://www.ultratechnology.com/1xforth.htm](http://www.ultratechnology.com/1xforth.htm)):

" _I wish I knew what to tell you that would lead you to write good Forth. I can demonstrate. I have demonstrated in the past, ad nauseam, applications where I can reduce the amount of code by 90% percent and in some cases 99%. It can be done, but in a case by case basis. The general principle still eludes me._ "

<comment><USER7> I'm not surprised that the general principle that helps Moore reduce his code size eludes him. Authoring something blinds you to your own style—both to your mistakes, and to your brilliances. It's why prose writers can't be their own editors: you need someone who wasn't in your head during the writing process to actually be able to see what's ended up on the page, rather than just seeing reminders that immerse you back into your own implicit context.

I would expect that, if you took five of these rewrite projects of Moore's, and compare-and-contrasted their source with the source of the originals, principles _would_ leap out at you.

(Why don't we programmers, as a culture, read code this way? It really seems like the only way to deduce novel facts about programming for yourself. Is it just that a rewrite where both the old and new codebases are shared-source is rare?)

<comment><USER8> I'm a big Chuck fan, but I get the feeling that he isn't on a short deadline to build some standard business app like 90% of coders where you almost have a template...sure it has lots of code you don't need and to paraphrase Rich Hickey, it isn't simple, but it's really easy (at least in the short run). He's doing things where he is allotted the time to really understand the problem and deliver a minimal solution. Listening to his interviews make me sad as they call up images for how programming could be if we'd gone about it differently. Small teams writing small and efficient software where you can grok the entire thing at once.

<comment><USER9> Chuck Moore was amazing before I even knew how to code (and was a big inspiration for me), so I'm not going to even pretend that I know how to do what he does. However my view of this is that we, as programmers, can't just look at our jobs from a technical perspective. _Nobody_ is given the time to make great solutions. The best programmers know how to work so that they can get the time they need. This is not trivial.

You can't just wander up to management and say, "I need X to make an optimal solution". They will negotiate you down. That's _their_ job -- to negotiate into a position of advantage. When you need protection from the chaos that surrounds the rest of the organisation, you can count your lucky stars when you have an expert negotiator on your team. But when you go up to that expert negotiator and say, "I want X", the _first_ thing that's going to go through their minds is, "I wonder if I can get that cheaper".

So programming _has_ to be a balancing act of constantly delivering functionality while at the same time ruthlessly refining your vision of how it's going to work. If you are delivering quickly, regularly and constantly _nobody will touch you_ for fear of screwing it all up. But knowing how to do that while still marching inevitably closer to simpler and simpler solutions is hard. A normal person needs to practice (and get it wrong) a long time before they get good at it.

Chuck describes a lot of his techniques in his books, but it's fluency that you need -- and it's fluency _while things are hitting the proverbial fan_ that makes all the difference. You need great judgement to look at what you need and to prioritise it appropriately. If I deliver X quickly, I'll show progress. Do I need to show progress now? How fast? Can I refactor Y while I'm here? Is all of this necessary? And so on and so on.

It's tempting to think, "If only I was given lots of time.", "If only I didn't have incompetent coworkers", "If only people would listen to my advice", "If only management could look past tomorrow"... But that's not useful. Anybody can be a great programmer if we remove every problem before they start. The measure of your worth is how many of these complicating factors you can deal with _while still producing great code_. That's what's rare.

</comment></comment></comment></comment><comment><USER10> Based on the Silicon Valley Forth Interest Group email list, Chuck Moore has declared that he has retired from social media, he has not retired from Forth. He is scheduled to speak at Forth Day, November 18, 2017, as he has for years. [https://svfig.github.io/](https://svfig.github.io/) [http://www.forth.org/svfig/next.html](http://www.forth.org/svfig/next.html)

</comment><comment><USER11> > Moore also has a corollary called Do It Yourself!, which encourages you, in > general, to write your own subroutines rather than import one a canned > subroutine from a library.

The other side of this coin is NIH Syndrome. I've seen that go wrong in all sorts of ways.

One of the key skills of being a great engineer in the real world is exercising good judgment whether to "build or buy".

<comment><USER12> In the real world, anecdotally, my employers have always preferred to buy 160 hours of my time rather than share 480 hours of someone else's time with 1000 other customers.

It may have been because that person is then 1/1000th as responsive to their specific needs. It also may have been because that person wasn't cleared, and paranoia requires their code to be vetted before allowing it within breathing distance of our network. Or it may have been because buying a third-party tool requires approval of the manager's manager's manager, while rolling your own is the manager's call.

I have never seen a company that makes it easy to buy a third-party license, and never a company that makes it easier to use a gratis licensed software than a paid one. They're all afraid that GPL will infect the code, and it will dance out of our source control onto the Internet like children following the Pied Piper.

And on the other side of that coin, I have also seen licensed third-party software become vastly more trouble than it was worth, especially when it came time to upgrade it to a newer version. In general, though, if a third-party tool already does exactly what you need it to do, and you never need it to do anything else, it is always better to license it, configure it correctly once, and then never touch it again (aside from security-related patches).

<comment><USER13> > I have never seen a company that makes it easy to buy a third-party license, > and never a company that makes it easier to use a gratis licensed software > than a paid one.

Meeting anecdote with anecdote, I've never worked at a company that made paying for licensed software easier than using gratis.

</comment></comment></comment><comment><USER14> > If you have read any of Chuck Moore's work, you know that he is an extreme > programmer in the literal sense of the word: a unique philosophy that > embraces small, fast, self-contained programs in a spare language and an > impressive development environment

I haven't read any of his work, what is impressive about his development environment?

<comment><USER15> He designed CPUs from scratch using a bare-bones minimal Forth (ColorForth) as his preferred way of writing code. The resulting chipset is utterly fascinating: [http://www.greenarraychips.com/](http://www.greenarraychips.com/)

<comment><USER16> > from scratch

This is even understating it -- it's not like he used existing software to lay out the chip, and then ran tests using PSPICE to verify the functionality. He wrote his own chip design software and analog simulator, and designed the chip in his own environment, and created the CPU, the GA144: a working 144-core processor designed to run "ArrayForth", a parallel version of Forth that he designed and authored, just as he designed ColorForth, and just as he designed, once upon a time, the language known as Forth.

Any of the tasks above seem like it would be a reasonable accomplishment for a good programmer. Combined, they make me question whether I even qualify as a developer by this standard, and make me wonder whether I should take a year off of development and just really learn Forth.

<comment><USER17> Your ending summary was exactly my thought process as I read the first paragraph. I essentially went through the 5 stages of grief as I realized I am no longer a developer.

<comment><USER18> Round every circle a larger may be enscribed. Don't be downtrodden but be inspired.

</comment></comment></comment></comment></comment><comment><USER19> I've worked with another Forth disciple in the late 80s.

He was on a PC, and thought that my Mac GUI was neat. So he wrote a portable GUI framework from scratch in Forth that had dialogs, buttons, pull down menus, text inputs, graphics, mini Mac clone. It was magic. I think it was way under 100K.

After that, I really wanted to become a Forth wizard. I tried, but it never clicked, my code was very clumsy, write only. I admired my coworker as an almost alien intelligence.

I think it really works well for coders spiritually close to hardware.

<comment> Chiba-City FWIW, I wrote a graphing menuing system with primitive scalable fonts (for Arabic) in Turbo Pascal in '89 on US taxpayer dimes for live variable twiddling graphing of demographic simulations. It was all roll our own back then on 512K PC's. I implemented a Common Lisp compiler packaged in a DLL for Windows before the net took off. Some kind of "hardware and syscalls up" exercise should be part of more CS programs. It is a great experience to engineer truly reusable (and reused) code before the mosh pits of corporate labors. Good times make for useful memories.

</comment></comment><comment><USER20> Charles' extreme minimalism philosophy aligns well with Forth, but it can work in many compact environments. Scheme and Lua come to mind. It is difficult at first but powerful and liberating to realize that one has full agency over their program. With other runtimes, there is no possible way to either understand the whole thing, or effectively fork it and fix what you want. Not so with Lua, Forth or a small Scheme.

I _really_ like that Lua doesn't ship much in the standard lib, but what it does ship can be used to build the world.

<comment><USER21> The _economy_ of Lua's design has impressed me.

You've got just one data structure, the table, and from that you can implement just about anything else... efficiently.

</comment></comment><comment><USER22> Forth was always fun for me because it really was fun to build up a dictionary of words that solved your problem. It practically forced coming at the problem from the bottom. I do admit that I liked some aspects of Postscript better than Forth, but both are experiences.

Thinking Forth is a pretty good starting point and in general a great programming book [http://thinking-forth.sourceforge.net/](http://thinking- forth.sourceforge.net/)

<comment><USER23> It's called factoring with subroutines, and Forth hasn't cornered the market on anything by calling them words.

<comment><USER22> No, but Forth provided one of the nicest, most immediate, and interactive environments to explore a problem. Instead of multiple files in a text editor, you build and test your app live and then dump it all to a text file. I have rarely had that experience with any other language except Smalltalk. I understand some Lisp environments act that way, but Forth was available places Lisp and Smalltalk were not.

<comment><USER23> Developing on the target is just so last century. Now that programmers have developed the IDE you'll have to pull them from their cold dead hands.

<comment><USER22> I don't think I've used any IDE (other than Smalltalk) that was vaguely in the class of using Forth for interactivity and building of programs from the bottom up.

Whats up with mocking everyone you reply to on this thread?

</comment></comment></comment></comment></comment><comment><USER24> I found this video of Chuck speaking in 2011 just awe inspiring [https://www.youtube.com/watch?v=odBjuSCX8jE](https://www.youtube.com/watch?v=odBjuSCX8jE)

<comment><USER25> I really worry for what we'll lose when he dies and no-one carries on his work. Reading about his systems is like peering into an alternate universe of engineers and technicians making the world go 'round.

</comment></comment><comment><USER26> Is Moore okay? His charming homepage ([http://www.colorforth.com/](http://www.colorforth.com/)) has been down for a while now.

<comment><USER6> Last working archive on archive.org is here: [https://web.archive.org/web/20160414102635/http://colorforth...](https://web.archive.org/web/20160414102635/http://colorforth.com/)

</comment></comment><comment><USER27> If our technological civilization collapses and we need to recreate it from scratch, Chuck Moore could do significant part of that.

<comment><USER28> Off topic, but we can't. All the readily available sources of energy have been used. As someone else said, this is literally the last great civilization. Best not screw it up!

<comment><USER29> That's a note on whether a future civilization without access to our knowledge attempted it, no? I imagine some good physics and engineering texts from now might help a future civilization bootstrap itself technologically, even you have to slowly and painfully jump a few steps that would be easier with readily available oil.

</comment></comment></comment><comment><USER30> Legend has it Chuck Moore had a 3D wire-frame CAD program he used to carry around as a punch-card deck in his shirt pocket.

<comment><USER31> I've heard he just types it in from memory when he needs it.

<comment><USER32> Not from memory: from scratch, every time. Adapted to the problem at hand and not carrying unnecessary baggage.

</comment></comment></comment><comment><USER23> THE central problem with pure stack machines and stack languages:

The programmer knows in their heart that moves, swaps, dupes, drops, etc. - any stack manipulation that doesn't involve a functional change to the data itself - is an inefficiency to be minimized, but this effort isn't in any way related to the problem at hand (writing a program to do something) so it's unwelcome mental overhead.

I like puzzles as much as the next person, but not so much when they seriously impede the solving of a bigger more serious puzzle, nor when the sub puzzle solving is an exercise in the minimization of something bad rather than the elimination of it.

<comment><USER33> Traditional languages are pushing and dropping data from the stack every time a function or procedure is called, they just give it another name: parameter passing. Making it explicit, at least Forth tries to reduce the need of copying things from the stack to local variables.

<comment><USER23> I don't think the stack in a traditional languages is the same as stacks in stack machines and languages. It's a lump of memory that gets allocated to a thread for stuff, and the allocation is indeed done in LIFO fashion, but I believe access to individual memory locations in the allocation is random. Name is the same, LIFO and all, but the mechanism granularity makes it quite different.

<comment><USER33> It is true that traditional languages lump local variables and return information in the same stack. But the difference is only in the way this is handled by the program. In traditional languages the programmer has no idea how parameters are passed in the stack and the compiler does everything. In Forth this is made explicit, but on the other hand there are no formal parameters to worry about (notice that Forth can use local variables if you want, it is just not the idiomatic way).

</comment></comment></comment></comment><comment> Chiba-City I used to go to the NASA Forth User Group meetings in the early 90's to hang with compiler and language nerds. Chuck Moore is a genius problem solver. His Starting Forth is one great example of an introductory language text.

<comment><USER34> Starting Forth by Leo Brodie is an excellent book, considered one of the best programming books ever written.

[https://www.forth.com/starting-forth/](https://www.forth.com/starting-forth/)

<comment> Chiba-City Sorry I recalled the author wrong. I'll leave your correction. Thanks.

</comment></comment></comment><comment><USER35> The "Do Not Speculate!" idea reminds me of the practice of delivering "the kitchen sink" when only a small program that does one thing would suffice.

It reminds me of when, e.g., a 1990s-2000s Windows user needed a small program that does one thing, and in order to get it, the download from Microsoft was an installer with hundreds of megabytes of unneeded binary files. It was not possible to download only the single program, which was no more than 1-2MB in size.

It reminds me of this quote: "The problem with object-oriented languages is they've got all this implicit environment that they carry around with them. You wanted a banana but what you got was a gorilla holding the banana and the entire jungle." \- Joe Armstrong

It reminds me of bloat, of giving users things they do not need. A problem that continues to this day.

Instead of bloated, complex UEFI, I wish something like OpenBIOS/OpenFirmware/SmartFirmware/OpenBOOT would be available for today's hardware. I have played around with fgen on i386 and read some of the history. They even provided courses on how to write drivers. Besides OLPC, why did this not catch on?

IMO, Forth is the most elegant and flexible language for initializing hardware.

<comment><USER8> This is what I like about Rebol & Red...pity Rebol didn't catch on more. The full Rebol download is a single executable (no real install) and can build GUIs, and so much more in a very small amount of code.

<comment><USER36> Not to mention Red can cross compile for multiple OSes and the parse dialect that is basically generalized, readable regular expressions.

My personal theory why Rebol/Red didn't succeed in the mainstream is steep learning curve, it's hard to discover how to do things if you haven't already done some substantial programming work in it. While built-in help is good you need to know what you're looking for. (Delphi had better help in this matter, with examples etc.).

By the way I wonder why Pecan's post is [dead], it doesn't seem to be violating any rule.

<comment><USER37> > didn't succeed in the mainstream

Is that true of Red? I was playing with it the other day and it looked really promising, and I was under the impression that it's still quite new and hasn't reached 1.0 (my point is that it might not be at a stage where we can write it off).

<comment><USER36> > it's still quite new and hasn't reached 1.0

According to the main page [0] the project was unveiled 6 years ago. For comparison Rust (a random example) started 7 years ago [1] but compare results for "Rust" and "Red/Rebol" on Algolia [2] (sorry no deep links). It's clear Red is niche.

I'm not writing it off. It's definitely one of most interesting languages and runtimes but it's super hard to capture people's attention nowadays when you don't have support of large companies (Go, Rust, .NET).

[0]: [http://www.red-lang.org/search?updated- max=2011-03-29T15:38:...](http://www.red-lang.org/search?updated- max=2011-03-29T15:38:00%2B02:00&max-results=7&start=40&by-date=false&m=1)

[1]: [https://en.m.wikipedia.org/wiki/Rust_(programming_language)](https://en.m.wikipedia.org/wiki/Rust_\(programming_language\))

[2]: [https://hn.algolia.com/](https://hn.algolia.com/)

<comment><USER37> Hmm, you're right. I didn't realise it was 6 years old!</comment></comment></comment></comment></comment></comment>


Bolivia, The Saudi Arabia of Lithium - <AUTHOR> http://www.nytimes.com/2009/02/03/world/americas/03lithium.html

<comment><USER2> so thats why they are all so chilled out

</comment><comment><USER3> And Brazil is the world's sugar daddy: [http://current.com/items/89112645/the_world_s_sugar_daddy.ht...](http://current.com/items/89112645/the_world_s_sugar_daddy.htm)

Maybe the time has come for South America. They're rich in natural resources. Let us hope these resources are used for the benefit of the peoples. not just the ruling kleptocracy.

<comment><USER4> I believe the potential for the ruling parties to reap all the rewards from North America were all present, but the long history of the populating nations and sheer political disobedience certainly put a stop to that notion.

I hope that South America's political heritage will win out and they'll follow suit of NA into leading nations. Portugal is a post-empire country, and hopefully this will imbue the Brazilians with a healthy demand of respect when trade starts becoming more important.

Sadly the reason I think Africa is a different story is because for thousands of years they've had the choice between doing as they're told and staying alive or protesting and dying. I believe it doesn't help that literacy and information aren't as prevalent there, which certainly hurts people knowing their fair rights so everyone would stand up for them and not just a few.

<comment><USER3> I didn't get the point you were trying to make when you mentioned that Portugal is a post-empire country. How relevant is that to the future of Brazil? Or South America in general?</comment></comment></comment>


Using the KVM API - <AUTHOR> http://lwn.net/Articles/658511/ <comment><USER2> _" A virtual machine using KVM need not run a complete operating system or emulate a full suite of hardware devices. Using the KVM API, a program can run code inside a sandbox and provide arbitrary virtual hardware interfaces to that sandbox."_

This is amazing. If you're building something platform-level, like for e.g. NaCl, I presume you could use the KVM API to provide stronger isolation beyond the standard limited isolation of a regular Linux process.

<comment><USER3> See also Cappsule, for launching Linux applications in VMs, [https://cappsule.github.io](https://cappsule.github.io)

 _" Cappsule is a new kind of hypervisor developed by Quarkslab (to our knowledge, there's no similar public project). Its goal is to virtualize any software on the fly (e.g. web browser, office suite, media player) into lightweight VMs called cappsules. Attacks are confined inside cappsules and therefore don't have any impact on the host OS. Applications don't need to be repackaged, and their usage remain the same for the end user: it's completely transparent. Moreover, the OS doesn't need to be reinstalled nor modified._"

<comment><USER4> Is it similar to Spikes Security's Malware Isolation?

<comment><USER3> That seems to run browser sessions in VMs on network appliances, then it sends a processed (?) version to endpoints.

Cappsule is currently targeted at Linux desktops. It could theoretically be used on a Linux server to implement the isolation component of Spikes Security, but additional functionality would be needed to generate the "safe" version of content for endpoints, or to forward pixels to thin clients.

</comment></comment></comment></comment><comment><USER5> Related: KVM / QEMU technical architectural overview slides by Stefan Hajnoczi, one of the QEMU maintainers. (No talk recording, unfortunately-- pity, he's an excellent speaker).

      http://vmsplice.net/~stefan/qemu-kvm-architecture-2015.pdf

</comment><comment><USER6> Fun to see renewed attention to this article recently. Happy to answer any questions.

</comment><comment><USER7> I think this is one of my favorite articles demonstrating the application of "everything is a file" principle in Linux. Most people think of files as something with a path, and something you read and write to, commonly in a relatively streaming fashion. But as the article demonstrates with KVM API there is more than that in how files are used in Linux.</comment>


The super-recognisers of Scotland Yard - <AUTHOR> http://www.newstatesman.com/politics/uk/2016/08/super-recognisers-scotland-yard <comment><USER2> I have prosopagnosia. It's not that I can't recognize people at all; however, I have to rely mostly on haircut styles, mimics and movement patterns, and, above all, voice. I almost never identify actors in the movies (as they change their appearances professionally and I have trouble in remembering actual facial features), and it is out of question for me to remember anyone's face after several months. Especially when the haircut changes.

I thought it is relatively common condition (around 2% of people). But other people seem to be genuinely surprised by it every time: "how could you not recognize me? I have passed directly in front of you?" Sorry.

<comment><USER3> Studies show that people have trouble recognizing someone out of context about half the time. In other words, you work with John, you run into him elsewhere. You may not recognize him at all or you may realize you know him, but struggle to say from where.

People who are giving you a hard time about this likely are overestimating their ability to recognize faces. Context significantly influences this.

</comment></comment><comment><USER4> > "Caballero was gobsmacked," Rabbett told me. "He then got a bit arsey, > saying, 'I'm not speaking to you until I've had a cigarette, I'm getting out > of here, you can't do this to me.' And then it was: 'Yeah, it's gonna be a > full hands-up. Let's get it done.'"

I love English slang. Great article as well, I was surprised that the Scotland Yard group was the only one in the world.

> DCI Mick Neville reckons that it will be ten to 20 years before software is > advanced enough to be a useful tool, and even then super-recognisers will > still be needed to analyse the results and identify the suspects.

Perhaps augmentation is a better approach than replacement. By that I mean it might be really useful for them to be able to search a database of mugshots or photos for 'people with bigish ears, smallish nose and a spot on the left cheek'.

<comment><USER5> I'm betting that the system they have is an old pre-NN thing. Certainly not state of the art. The big gains in image recognition has happened fairly recently. Here's a survey of results on the Labeled Faces in the Wild dataset:

[https://people.cs.umass.edu/~elm/papers/LFW_survey.pdf](https://people.cs.umass.edu/~elm/papers/LFW_survey.pdf)

<comment><USER6> They use L1 Identity Solutions ABIS Face Examiner

</comment></comment></comment><comment><USER7> > Porritt's unit has its own software but this has been responsible for only > one of the 2,010 identifications made since May 2015. DCI Mick Neville > reckons that it will be ten to 20 years before software is advanced enough > to be a useful tool, and even then super-recognisers will still be needed to > analyse the results and identify the suspects

And yet so much surveillance is based on using facial recognition software to identify 'people of interest. Here's an empirical study showing it doesn't really work.

<comment><USER5> That's no empirical study. It's anecdote from one police department, and who knows what software they use.

In the best case, maybe some 5-6 year old academic project that got commercialized. In the worst case, maybe something their nephew who's really good with computers wrote ("its own software" suggests some bespoke thing, which makes the latter more likely).

<comment><USER6> I know. It's L1 Identity Solutions ABIS Face Examiner

</comment></comment></comment><comment><USER8> I'm amazed that someone (who committed 40+ thefts that) they worked so hard to catch got less than 4 years in jail. Perhaps they're wasting their time on petty criminals.

I suspect that computers will help out quite a bit. Similar to other topics, computers will first outperform most people, then ultimately everyone, but computers plus people will outperform just computers.

<comment><USER9> 4 years in prison is approximately 5% of a typical lifespan. That seems like a lot to me.

<comment><USER10> He will likely serve 2 years at most, and after those two years one could reasonably predict he'll re-offend. In which case I'm reminded of porridge:

" _You are an habitual criminal, who accepts arrest as an occupational hazard, and presumably accepts imprisonment in the same casual manner._ "

Now, apparently the guy never thought he'd go down for all of his crimes, but he knew arrest was a real risk. Same with prison. I'm afraid I don't have a strong opinion on what the best choices are that a criminal justice system can make. Clearly you aren't going to scare people straight with hardnosed punishments though, because their evaluation of risks are not what you think they should be.

<comment><USER11> Not sure if you're talking about the individual or reoffending in general, but according to HM prison service the reoffending chance would be 36℅:

[http://open.justice.gov.uk/reoffending/prisons/](http://open.justice.gov.uk/reoffending/prisons/)

<comment><USER10> I was basing it entirely on the guy as described by the article (as in, I was making wild assumptions).

Super cool site. That data would be pretty fun to play with though, age/offense count/previous offences/family etc would all be cool buckets to play with. Plus all the things I don't think of off the top of my head

</comment></comment></comment></comment></comment><comment><USER12> Could super-recognizers be used for parallel construction? Seems like it would be a great fit.

[https://en.wikipedia.org/wiki/Parallel_construction](https://en.wikipedia.org/wiki/Parallel_construction)

<comment><USER13> I suspect the "super-recognizers" are a good cover for some new algorithm for face identification..

"trawling through an image database with more than 100,000 stills.." sounds quite incredible to me.

<comment><USER14> I have seen organisations manually perform larger, more tedious tasks, for more money, with less useful results, so I'm happy to take it at face value.

<comment><USER15> Pun intended? If so, nicely done...

</comment></comment></comment></comment><comment><USER16> For some reason I thought of Tron.

[http://tron.wikia.com/wiki/Recognizer](http://tron.wikia.com/wiki/Recognizer)

In that universe, recognizers are "capable of capturing fugitive programs and vehicles"

</comment><comment><USER17> It'd be fun to try that test - I find myself noting the similarities between people "X looks like Y", and people nod along.

Maybe I'm not material for their special unit, though: one that completely escaped me is that George from Blackadder is one and the same as Dr. House: Hugh Laurie.

<comment><USER18> Here are some tests for talent (or lack of talent) in this area:

[https://greenwichuniversity.eu.qualtrics.com/jfe/form/SV_e3x...](https://greenwichuniversity.eu.qualtrics.com/jfe/form/SV_e3xDuCccGAdgbfT)

[http://www.abc.net.au/cm/lb/6744428/data/david- white27s-face...](http://www.abc.net.au/cm/lb/6744428/data/david- white27s-face-recognition-test-data.pptx)

[http://www.testmybrain.org/SupersRecruitment.html](http://www.testmybrain.org/SupersRecruitment.html)

[http://www.faceblind.org/facetests/ff/ff_intro.php](http://www.faceblind.org/facetests/ff/ff_intro.php)

[http://www.bbk.ac.uk/psychology/psychologyexperiments/experi...](http://www.bbk.ac.uk/psychology/psychologyexperiments/experiments/facememorytest/startup.php)

I'm not totally face blind, but I'm definitely impaired. I recognize people I see regularly just fine if they are in a familiar context. In other situations, rely more heavily on voice, gait, and haircut. The idea of choosing movies based on "favorite actor" makes no sense to me.

On tests such as these, I'm happy when I get the "do you understand the instructions" training questions right. Sometimes I can pick a face that I've just seen out of a short lineup based on verbal description of a single feature ("bushy eyebrows" or "full lips"), but usually I'm just purely guessing, hoping that my subconscious has the fabled "blind sight" that I can't consciously access.

<comment><USER19> I just did the greenwich one. That was fun - thanks. One complicating factor is that they re-use faces in the lineups, so you end up recognizing people from two faces ago. (intentional, no doubt).

<comment><USER20> I did that one, as well. 9/14, which is a lot better than I expected - I did "cheat" though. I picked details on their faces, and concentrated on remembering them.

I have aphantasia (to a degree). For example, I had difficulty recognizing my mother when she dyed her hair a few years ago.

<comment><USER21> Thanks for introducing me to aphantasia, which I hadn't heard of. For others that haven't, it means not being able to imagine images or sounds in your mind. It was only discovered recently, and I think it was popularised by this blog post by Blake Ross, which is well worth a read.

[https://www.facebook.com/notes/blake-ross/aphantasia-how- it-...](https://www.facebook.com/notes/blake-ross/aphantasia-how-it-feels-to- be-blind-in-your-mind/10156834777480504/w)

</comment></comment></comment></comment></comment><comment><USER22> As someone who can barely remember faces, i find this quite amazing.

Another thought is - how long before AI recognition would eliminate this job. 20 years they give sounds like an enormous over-estimate.

</comment><comment><USER23> What is up with this site? The tab rapidly climbs to 1.8 GB of memory and 100% CPU utilization, on the latest version of macOS and Chrome.

</comment><comment><USER24> I'm surprised face recognition software isn't used in the high-end stores.

</comment><comment><USER25> maybe humans do better in facial recognition than NEC software. But I found no statistical evidence for that.

</comment><comment><USER26> Just a note on the title: it appears to be an homage to Warren Buffet's classic speech "The superinvestors of Graham-and-Doddsville"</comment>


Ask HN: Why are so many coding challenges about math? - <AUTHOR> And where can I find ones that aren't? I want to improve my skill but I don't feel like I should pick up advanced algebra or number theory just to do a coding assignment. <comment><USER2> \-- "Why do you keep looking for your car keys under the lamp post?"

\-- "Because that's where the light is."

Less snarkily: that's because they traits that _really_ matter in a modern development environment -- the ability to deal with ambiguity and complexity; to navigate the tipping points between technical perfection and optimal business value; and and top of all this, a genuine sense of _humility_ and a willingness to work with others whose strengths and weaknesses are different from your own -- are very hard to test for, if they can be "tested" for at all.

But since the current interview "process" is so obsessed with "testing" and stack-ranking... not surprisingly, it's largely rigged around traits that are... easy to "test" for.

Like you know, the ability to crank out rehearsed solutions to algorithm puzzles and the like.

</comment><comment><USER3> I find it true that most coding challenges are either about math, or simple algorithms, such as path finding, DFS/BFS, tree traversal, etc. I think it's because they're simple to explain in a quick way, and don't involve the person needing to know libraries or frameworks.

That being said, most of the coding I've done in my life has been all about integrating different libraries and frameworks together. I don't see a lot of complex algorithms, which is good (because they are complex, and probably someone else already wrote it better, with less bugs and better performance). I'd never want to work with someone who rolls their own red black tree into production code just for the lols.

That being said, I don't think it's a great way to evaluate candidates, because it's not what most people do all day. I find problems about integrating systems, and understanding complex topics like networking, databases, testing, protocols, and APIs to be much more useful.

To find a good middle ground, I like to ask design questions, and then give people a "library" of functions they can call with prototypes, and tell them what they will do. This focuses on the logic of putting it together rather than off by one errors in loops, which still happens to me all the time. Those kinds of bugs are easy to fix when you can actually run the code, but a right pain on a whiteboard.

I'll never forget the look of surprise on the interviewers face when I was doing an intern interview and asked "can I use stdlib calls like memset and memcpy, or do you want me to write loops?" I think just asking the question gave me huge interview points. (and yes, I got the job.)

Let me finish by giving an example of what I thought was a good coding assignment: Write a service that listens to rabbitmq and rotates the images 90 degrees and post them back to a different queue. This wasn't about writing code to rotate images either, it was about knowing how things work, and stitching them together correctly (with the right error handling and failure modes).

</comment><comment><USER4> Coding challenges involving number-theoretical math have small, simple input cases, and can be stated compactly, yet can be fairly complicated and subtle. They often have the property that it's easy to test whether a solution is correct. They are also a good way to test someone's understanding of subtleties in requirements; if you misunderstand some key element in the problem, you will solve the wrong thing. Some problems in this area will drag in the use of data structures; you may have to keeps some hashes or lists, or even construct a graph. Or generate permutations, or some sort of tree with backtracking and such; it's not necessarily just numbers and nothing but numbers.

</comment><comment><USER5> I figure the math-heavy tests probably represent an unconscious attempt by elite educated CS guys to homogenize the talent they hire, to build teams of people more or less like those doing the hiring - very smart and well-trained in a particular tradition. Smart matters of course, but a CS background, while worthy, is one among many ways of becoming a competent, creative, productive developer.

</comment><comment><USER6> Because everything is math.

> I want to improve my skill but I don't feel like I should pick up advanced > algebra or number theory just to do a coding assignment.

Really? Advanced algebra or number theory? Can you show me a coding assignment that required either? Are you sure you're not just excusing your ignorance by suggesting that stuff you've been asked and didn't know the answer to is somehow advanced when it's really not?

<comment><USER7> I got asked a project Euler question at an interview for a crud job. I'm sure it's simple if you break it down, but there are plenty of other fish in the sea. If you ask me a question that starts: "let n be ...", I'm out.

An integer partition of a number n is a way of writing n as a sum of positive integers.

Partitions that differ only in the order of their summands are considered the same. A partition of n into distinct parts is a partition of n in which every part occurs at most once.

The partitions of 5 into distinct parts are: 5, 4+1 and 3+2.

Let f(n) be the maximum product of the parts of any such partition of n into distinct parts and let m(n) be the number of elements of any such partition of n with that product.

So f(5)=6 and m(5)=2.

For n=10 the partition with the largest product is 10=2+3+5, which gives f(10)=30 and m(10)=3. And their product, f(10)·m(10) = 30·3 = 90

It can be verified that ∑f(n)·m(n) for 1 ≤ n ≤ 100 = 1683550844462.

Find ∑f(n)·m(n) for 1 ≤ n ≤ 1014. Give your answer modulo 982451653, the 50 millionth prime.

<comment><USER8> Questions like that are asked more to find out how people cope psychologically with ridiculously hard requirements.

Can they start picking it apart, and at least find some bits of it they can solve, or do they squirm, or whine, or rage quit?

Attacking ridiculously hard requirements is a valuable skill even in crud jobs.

<comment><USER2> _Questions like that are asked more to find out how people cope psychologically with ridiculously hard requirements._

It's more like -- how they cope with some one deliberately playing with their head.

Or if they're not deliberately playing - they're at at least acting very, very pretentiously. Believing that they know how to cook up a "test" for real-life problem-solving skills. When in reality they're just parroting some toy problem they read on the internet somewhere. Or that someone that they thought was cool gave them in an interview way back when.

 _Can they start picking it apart, and at least find some bits of it they can solve, or do they squirm, or whine, or rage quit?_

In a completely contrived and artificial context that not only bears very little resemblance to the conditions in which developers actually do need to solve difficult real-life problems - but in many ways is in fact a grotesque distortion of those conditions.

</comment></comment></comment></comment><comment><USER9> Because there is a right and wrong answer. There is very little ambiguity, either the algorithm you wrote on the white board will do the the thing in required time/space complexity or it won't. Which makes it easy to ask and easy to compare candidates.

IMO this is horribly broken but the Big 4 do it so everyone else does too.

</comment><comment><USER10> Because it separates out those who went to Uni from those who learned to code in their basements.

<comment><USER5> Many excellent developers earned degrees in areas other than CS, or are self- taught and have demonstrably first-rate minds, well worth the salaries on offer.

<comment><USER10> Don't interpret my statement as a value judgement about the candidates, it's not. A guy who just got a phd in physics would probably have problems with these "programming as math" problems. I was just stating why these types of problems are being used. It's like a secret handshake.

<comment><USER11> Yeah, some of us (phd) physicists do have these problems.

More interestingly, some of the problems on places like hackerrank, which are expressed as math problems have fundamental problems in that the answers they posit as being correct are not. I dealt with one such failure, where one could write down an closed form solution for a problem in complex analysis that the author mistakenly assumed was a number theory problem. They did not comprehend that their answer was nonsensical.

<comment><USER10> Well it's true that the ignorance of some of these company's (hiring process) is in fact pretty insulting to the kind of people they really want to hire.

Compare that poor souls experience with Elon Musk's interview question for a tech hiring position, "So, tell me about a time you had a really hard technical problem to solve and how you did it?" The difference is night and day.

</comment></comment></comment></comment></comment><comment><USER12> [http://codeforces.com/blog/entry/23054](http://codeforces.com/blog/entry/23054)

[https://www.hackerrank.com/calendar](https://www.hackerrank.com/calendar)

I think topcoder ([https://www.topcoder.com](https://www.topcoder.com)) covers a wide spectrum, but i have never tried them.

</comment><comment><USER13> Why should I need to learn about measurements and rulers to design and build a house?

<comment><USER5> That's precisely it -- one does not build modern applications using the kind of knowledge OP is being tested for.

</comment></comment><comment><USER14> 1\. Because computer science is about mathematics (combinatorics, permutations, counting, etc) and sometimes interviewers want to make sure that the candidate's foundation is solid.

2\. As stated in earlier comments, because mathematics is unambiguous making the problem easy to state and easy to verify. Can you take a small piece of mathematics you may not be familiar with, understand it and translate that into working code? That is a core skill of any software developer -- not necessarily with just mathematics but you get the point.</comment>


Readable Clojure - <AUTHOR> http://tonsky.me/blog/readable-clojure/ <comment><USER2> Eh I dunno. Clojure comes closer than any other programming language to being like spoken language in that there are tons of different tenses and conjugations and a large, expressive vocabulary to articulate precisely what you mean. Like when writing in English - decide who your audience is and then use the vernacular they know to the full extent. In any serious project, that pretty much means you get to assume at least that they are fluent in clojure, before adding in other DSLs like funcool/cats (category theory) if your problem domain needs it. If your audience needs guard rails, Clojure is probably not the language for you for other reasons, for example the culture of "just read the source" (which is a great thing i think!). Just my 2c as someone who has written clojure full time for a couple years. Tonsky has probably written more Clojure than I have.

</comment><comment><USER3> > prefer (not (empty? coll)) over (seq coll),

There's a reason why _(seq coll)_ is a standard Clojure idiom, which the source for _empty?_ reveals:

        (defn empty?
          "Returns true if coll has no items - same as (not (seq coll)).
          Please use the idiom (seq x) rather than (not (empty? x))"
          {:added "1.0"
           :static true}
          [coll] (not (seq coll)))

By using _(not (empty? coll))_ , you are effectively writing _(not (not (seq coll)))_ , which isn't really very elegant, even if of marginal significance performance-wise.

Curiously, he later champions the use of _(some? x)_ rather than the arguably more readable _(not (nil? x))_ , even though in this case the former is directly equivalent to the latter:

        (defn some?
          "Returns true if x is not nil, false otherwise."
          {:tag Boolean
           :added "1.6"
           :static true}
          [x] (not (nil? x)))

> correct, error-proof way to choose "first non-nil value"

        (cond
          (some? a) a
          (some? b) b
          (some? c) c)

I'm sorry, but that's _horrible._ What if you had 20 items to check? Or an indeterminate number?

How about:

      (first (remove nil? [a b c]))

<comment><USER4> Must say I prefer or for this, and consider differentiating false and nil to usually be a code smell:

        (or a b c)

<comment><USER3> The relevant bit of the article was explicitly concerned with situations where false values needed to be returned if present, and ruled out the use of _or_ for precisely that reason.

But I agree: if you were ever in a position where you needed to do this, you might want to reconsider how you were representing your data.

</comment></comment></comment><comment><USER5> * Don't use "use" - agree completely.

* Use consistent, unique namespace aliases - agree. This helps tremendously when consistent across projects given the varying tooling capabilities. We even have a dictionary of namespace -> alias mappings that is expanded as new commonly used namespaces appear.

* Use long namespace aliases - agree partially. I have a few favourite namespaces present in pretty much every project that get a single letter alias.

* Choose readability over compactness - agree partially. Another part of the solution is keeping the functions small and all the types explicit. However, there's a fine line between that and having to use something like a hungarian notation for the local variables.

* Don't rely on implicit nil-to-false coercion - agree. However, I never find myself in this situation. Mostly because I just don't use plain booleans. Pretty much always you can use an enum (keyword) instead to better express the intent. When used locally - in the scope of a single function - I find that boolean-nil problem doesn't cause any issues.

* Avoid higher-order functions - agree completely. `comp` and `partial` in Clojure are awkward. If you find yourself using them, you're probably nesting too many lambdas with hash (#) notation - move some of them out into a `let`.

* Don't spare names - agree partially. The suggestion is definitely more readable. I just love writing threading expressions.

* Don't use first/second/nth to unpack tuples - agree completely.

* Don't fall for expanded opts - agree completely.

* Use * as prefix for references - agree. This needs some sort of a blessed reference in the Clojure documentation. Something to syntactically mark constants, e.g. `+constant+`, something to mark refs, e.g. `+ref`.

* Align let bindings in two columns - this is purely a matter of preference. I don't care either way.

* Use two empty lines between top-level forms - also a matter of preference. I prefer a single line.

<comment><USER6> What is wrong with Hungarian notation? I use mX and vY for maps and vectors when they are not totally transparent and it does help. Of course you have no guarantee that your

       (defn foo [mA]
         (:foo mA))

will be passed a map in mA but at least you are drawing a boundary.

<comment><USER5> I'm not a big fan - once you start encoding type information in names, you have to be extremely attentive when refactoring. It doesn't scale too well in a larger team.

I prefer _clojure.spec_ to guard significant (ns, api) boundaries.

</comment></comment></comment><comment><USER7> Agree with most of them, except,

Advise against higher order functions. Higher order functions separate clojure from other languages, and is one of defining features of this class of languages.

Advise to not use threading. Threading is just a series of steps. I find it very readable. If I start using symbols the step sequence can become a step graph FWIW.

<comment><USER8> I for one enthusiastically agree with the author's advice to use the `#()` syntax in place of `partial` and/or `comp`. It's just plain easier to parse, even for those who are familiar with higher-order functions but especially for those that aren't.

<comment><USER9> That's interesting, because I find #() rather _less_ easy to parse compared to (comp) or (partial) for otherwise equivalent expressions.

At a glance I know that (comp f g h) and its flat list of arguments expresses a simple function composition chain. Seeing a #(f (g (h %))) where (comp) will do makes me sift through more parens; more than that though, when (comp) is embraced as convention, a #() is an immediate cue that simple function composition is _not_ what's being expressed, which draws me in necessarily to examine the particular structure of the #() body.

</comment></comment></comment><comment><USER10> Like the *-prefix, I derived significant readability by prefixing all reference type symbols (like atoms) with !, which goes hand-in-hand with the exclamation mark in `swap!` and `reset!`. For example:

        (let [!input (atom {:some "data"}]
          (emit! ::event @!input) ;; @ and ! always go together
          (reset! !input {:new "data"})) ;; mutations against plain symbols "looks wrong"

<comment><USER11> I like that. I think it reads a bit better because ! looks less like @. The analogue with reset! and swap! is nice too.

However, right now I'm also working with Java (unfortunately :D) and !input looks a bit too similar to a not condition, so adds a tiny bit to my language context switch.

</comment></comment><comment><USER12> I've been bitten before trying to use (if (some? (thing))) instead of just (if (thing)) for the sake of readability, because as (defn thing ...) evolved, it ended up returning a function call that sometimes returned false instead of just nil, so the conditions were sometimes inverting in subtle ways and it was _really hard_ to track down why.

</comment><comment><USER13> I was hoping that this would be an implementation of readable lisp (aka sweet expressions) for clojure.

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

<comment><USER14> Disagree that it's readable. The parens are great - they show exactly where a function call starts and where it ends. The program is a tree!

<comment><USER15> +1 That thing is gross. I'd edit so much more slowly if I had to go back to a messy, complex syntax. At least without a very clever / specialized editor effectively undoing the change for me.

Infix is occasionally more readable for math, but I'd rather have a macro to transform a delimited section of infix code than to mess with the language.

<comment><USER14> Infix is only easy to read if you're only used to it. Not inherently better - I'd say opposite even.

Also, I don't want to live without Paredit (or Smartparens)

</comment></comment></comment></comment><comment><USER14> One thing me and my teammate did in our last Clojure gig was to not shorten namespaces (with the `:as` keyword).

Instead of in this example write `[cognician.chat.dom :as dom]` just write `cognician.chat.dom`. Then when calling, use the whole namespace.

It's a tradeoff between typing a little bit more (in reality, using the autocomplete function) in exchange for having the code readable. When you read something on line 213, you don't have to scroll up to double check what that short name refers to.

Wish :as was never added to begin with.

</comment><comment> dj-wonk I remember having these kinds of discussions with coworkers in a previous job where I did Clojure daily.

I don't necessarily want to comment on the particular details here. You may agree or disagree with elements of any one particular style guide; many depend on your team and audience.

With that said, I would make these comments. First, your team might find value in choosing an existing style guide and updating it as you go. Second, it might use pairing as a way of letting these decisions happen organically.

<comment><USER16> A lot of these can be linter rules, like no single-letter aliases, or forcing common packages to be imported as one consistent name. (I don't know a ton about clojure but I'm assuming linting is a thing.) To the extent that linting keeps things consistent and helps prevent mistakes, without unnecessarily hamstringing developers, it's a good idea imo.

</comment></comment><comment><USER17> Advice for the author, skip most of the "don't" if you write both the bad and the good, it will be confusing and the reader will remember both, but after some time forget which was better.

<comment><USER11> I found the comparisons useful. It showed me why its better, instead of just saying "hey this is better, do this".

</comment></comment><comment><USER3> > My (incomplete) set of personal rules:

> \- use contains? instead of using sets as functions,

[snip]

> An example. To understand this piece of code you need to know that possible- > states is a set:

          (when (possible-states state)
            ... )

> By contrast, to understand following code you don't need any context:

          (when (contains? possible-states state)
            ... )

I disagree. In the first example, it's clear from context that _possible- states_ is a function (to be precise, an object that implements _IFn_ ) that returns a truthy or falsy value depending on the value of _state_ ; the name _possible-states_ suggests it's checking that the value of _state_ is valid, according to some criteria.

To determine what those criteria are, you'd have to look at the definition of _possible-states_ : but that would also be true even if you used the more verbose _contains?_ construct.

By not using _contains?_ , you also retain the option to replace _possible- states_ with an actual function, should you later discover you need further validation or processing not possible with a simple set.

For example, if _state_ is a text string, and you find out further down the line that sometimes it's in the wrong case or has unwanted leading or trailing white space, you can replace

        (def possible-states #{"foo" "bar" "baz"})

with

        (defn possible-states [state]
          (->> state
            clojure.string/trim
            clojure.string/lower-case
            #{"foo" "bar" "baz"}))

without needing to change code elsewhere.

Even if you don't feel that this flexibility is worth the ambiguity, _contains?_ offers little comfort, as it can take many things other than a set:

        (contains? #{"foo"} "foo")     ; true
        (contains? {"foo" 1} "foo")    ; true  ("foo" is a key of the map)
        (contains? {:bar "foo"} "foo") ; false ("foo" is a value but not a key)
        (contains? ["foo" "bar"] 1)    ; true  (vectors are keyed by integers)
        (contains? '("foo" "bar") 1)   ; false (but lists aren't)
        (contains? "foo" 1)            ; true  (but strings are)

</comment><comment><USER18> I find the advice on prefixing atom names with * very useful, especially for Clojurescript / Reagent code. I have never encountered such style before though - is it a widely accepted convention?

<comment><USER19> I haven't seen it. I don't find myself using atoms very much and when I am using atoms, it's almost always because I'm trying to use doseq when a more functional version of my code exists if I would think about it.

<comment><USER18> From my experience, atoms are indeed rarely needed on the backend, where you have a DB to store the app state, but you can't do pretty much anything without them in cljs / Reagent.

</comment></comment></comment><comment><USER20> > Align let bindings in two columns

> I do it by hand, which I consider to be a small price for readability boost > that big. I hope your autoformatter can live with that.

Cursive's formatter has this option.

<comment><USER21> Is it just me who doesn't find this to boost readability?

It also has downsides (overly large diffs if you need to adjust alignment after adding a new binding-with-a-long-name to a let clause).

I also find two empty lines between functions to be too much for my taste.

<comment><USER22> I'm with you on the column alignment. I don't see how the items in the right column have so much to do with each other that reading down the column is helpful. All that really gets aligned are the opening parentheses, and what's the point of that?

Lining up columns like this can make you crazy. There's a good example of this earlier on the page:

      (ns examples.long-aliases
        (:require
          [clojure.spec          :as spec]
          [clojure.test          :as test]
          [clojure.java.io       :as io]
          [rum.core              :as rum]
          [diatomic.api          :as diatomic]
          [clojure.string        :as string]
          [cognician.chat.util   :as util]
          [cognician.chat.server :as server]
          ;; you can use dots in aliases too
          [cognician.chat.server.schema   :as server.schema]
          [cognician.chat.ui.entries.core :as ui.entries.core]))

Here we have two aligned sections, one above and one below the ;; comment. Why aren't they _all_ aligned to the same column? Apparently it's the ;; comment that says "OK, you can stop worrying about alignment here and start a new alignment section below this line."

Now what if we remove the comment?

      (ns examples.long-aliases
        (:require
          [clojure.spec          :as spec]
          [clojure.test          :as test]
          [clojure.java.io       :as io]
          [rum.core              :as rum]
          [diatomic.api          :as diatomic]
          [clojure.string        :as string]
          [cognician.chat.util   :as util]
          [cognician.chat.server :as server]
          [cognician.chat.server.schema   :as server.schema]
          [cognician.chat.ui.entries.core :as ui.entries.core]))

Well, that won't do. Time to realign everything to keep it clean:

      (ns examples.long-aliases
        (:require
          [clojure.spec                   :as spec]
          [clojure.test                   :as test]
          [clojure.java.io                :as io]
          [rum.core                       :as rum]
          [diatomic.api                   :as diatomic]
          [clojure.string                 :as string]
          [cognician.chat.util            :as util]
          [cognician.chat.server          :as server]
          [cognician.chat.server.schema   :as server.schema]
          [cognician.chat.ui.entries.core :as ui.entries.core]))

Now we see another problem with alignment. The sheer amount of horizontal white space makes it hard to visually match up the first several lines that have much names on the left.

And how do we decide what to align and what _not_ to align? We're lining up the :as, but why not the closing brackets too?

      (ns examples.long-aliases
        (:require
          [clojure.spec                   :as spec           ]
          [clojure.test                   :as test           ]
          [clojure.java.io                :as io             ]
          [rum.core                       :as rum            ]
          [diatomic.api                   :as diatomic       ]
          [clojure.string                 :as string         ]
          [cognician.chat.util            :as util           ]
          [cognician.chat.server          :as server         ]
          [cognician.chat.server.schema   :as server.schema  ]
          [cognician.chat.ui.entries.core :as ui.entries.core]))

Plus, alignment obviously works only in a monspaced font. I like to make my code readable whether someone uses a monospaced or proportional font. If you forgo alignment, code is equally readable in any kind of font.

And really is non-aligned code any less readable than the aligned version? It may not be quite as pretty, by some definition of "pretty", but does it really matter? And it has the advantages of not requiring constant fiddling as you add names, not messing up your VCS diffs, and keeping the left and right parts of the :as close together so you can easily match them up visually?

      (ns examples.long-aliases
        (:require
          [clojure.spec :as spec]
          [clojure.test :as test]
          [clojure.java.io :as io]
          [rum.core :as rum]
          [diatomic.api :as diatomic]
          [clojure.string :as string]
          [cognician.chat.util :as util]
          [cognician.chat.server :as server]
          [cognician.chat.server.schema :as server.schema]
          [cognician.chat.ui.entries.core :as ui.entries.core]))

<comment><USER23> Sadly, for me you made the opposite point. The column aligned sections were _far_ easier to see the sections than the other.

Now, I do think this is of rather limited value. So I wouldn't die on this hill. But, column alignment is clearly superior to my subjective eye. It is a shame not everyone has align-regexp.

<comment><USER24> Could it be a matter of syntax highlighting? I find highlighting draws the subjects out to me better. In my case the :as would be a different color and the closing bracket a muted color, which makes it easy for me to pick out the importing names.

<comment><USER11> Not for me. My code is syntax highlighted, but I still personally find the aligned code easier to see. The difference is between having all of the stuff side-by-side (vertically) and looking for colours inside other code fragments.

Definitely subjective, though, I guess.

</comment></comment></comment></comment></comment></comment><comment><USER25> These feel like things that a linter could check and a Gofmt-like tool could do. Has anyone here used such tools? A quick Google turned up these options:

\- Lint: [https://github.com/candid82/joker](https://github.com/candid82/joker) \- Gofmt: [https://github.com/pesterhazy/boot- fmt](https://github.com/pesterhazy/boot-fmt)

</comment><comment><USER26> Very well designed website.

</comment><comment><USER27> For such a young language Clojure seems to have a lot of cruft. 3 ways to import a module, what were they thinking?

<comment><USER28> Clojure is almost 10 years old. I don't think this reasoning makes sense though, because from what I've seen most of the cruft in any language comes from the very early design decisions (both in what's included and what's missing).

<comment><USER27> Cruft in a language isn't such a big deal as long as it is fixed. What really matters is cruft in the ecosystem. There are so many Clojure tutorials that use "use" and "refer". That's the real problem. JavaScript has with(), but there are approximately 0 articles online that use it, so its not an issue.

</comment></comment></comment><comment><USER29> Is that an actual editor in the screenshots? I thought most clojurists use emacs...

<comment><USER30> I used to, but now I use Cursive in IntelliJ IDEA.

</comment></comment><comment><USER31> quite sensible advice, will probably start minimising my use of refer. I don't agree with all of it, but that's the nature of style guides.

</comment><comment><USER32> A lot of this applies to Python as well.</comment>


Falcon: a fast multi-paradigm programming language - <AUTHOR> http://www.falconpl.org

<comment><USER2> Nice-looking language, but not-so-nice looking license proliferation: <http://www.falconpl.org/index.ftd?page_id=license_1_1>

</comment><comment><AUTHOR> comment failed, wrong number of arguments.

no, seriously,whats wrong with gpl?

<comment><USER2> _no, seriously,whats wrong with gpl?_

Don't ask me; ask the guy who came up with the "FPLL" dual-licensing.

LGPL single-licensing would probably be better.</comment></comment>


Create your online CV website and track who views it - <AUTHOR> https://kwickbox.quickpublisher.online/ <comment><AUTHOR> Get started today with KwickBox at [https://kwickbox.intuitive- web.co.za/](https://kwickbox.intuitive-web.co.za/) and easily create your online CV website. Let's start the digital CV revolution</comment>


Ask HN: Best trade show swag for developers? - <AUTHOR>

What are your favorite freebie items you have received at IT trade shows?<p>My company is trying to come up with the best developer "swag" for some upcoming trade shows. We are looking for some great ideas! <comment><USER2> I don't know what the best swag is, but I assume you're trying to think 'outside the box'.

I think swag has two purposes.

1) Try to build a relationship with the developer, let them think about how you care about them, get them keen on your product, stay front of mine. For these sorts of things, we've seen stuff like coffee mugs, usb keys,keychains, etc. Stuff the developer uses, but the focus is not on being seen by other people.

2) the other type is stuff that broadcasts your company name and tries to make an affinity between the developer and the community. This is the stuff like t-shirts, hats, jackets, laptop cases, etc. etc. Sure the developer uses these things, but they are promoting your brand by using them, and are (sometimes) proudly showing their affinity to your company.

So first off, which type of swag are you looking for? What is your product, who are the developers? Is the brand on a public item going to help you get more clients, or are you so niche that you just want the developers who use your product to talk about you?

Today I got my first qi charging pad, and it is ripe to have some branding on it. If that fits your market, that could be a cool thing that developers use every day, but it would be rare than anybody sees it other than the dev.

<comment><AUTHOR> Our customers are developers. My company is Stackify. We provide a service for operations that is a mashup of monitoring, metrics, errors, remote access and more.

T-shirts seem to be popular and we give those away. Just trying to think of some other clever ideas.

<comment><USER3> No-one takes t-shirts seriously - you're wasting your money with those. They're just a winter vest at best. Practical things devs use, that's different. +1 on mugs. To this day, because some real effort went in some multimap mugs are great. Good size quality mug. Possibly even a keyring with a decent amount of weight - making it hard to lose. Or similar.

How about a pen that also doubles up as a touchscreen stylus?</comment></comment></comment>


Xkcd: Business Idea - <AUTHOR> http://xkcd.com/827/

<comment><USER2> I hate when Xkcd makes fun of me...

</comment><comment><USER3> I heard he totally would have made it too, except no one would sign his NDAs.

</comment><comment><USER4> I fail to see the humor in the strip? One of the less funny ones (or not at all)</comment>


50-lines AVL binary search tree in C - <AUTHOR> http://pastes.archbsd.net/graphitemaster/50_loc_avl_bsearch_tree

<comment><USER2> Why not remove all the line feeds and make it one line of code? Much more impressive then!</comment>