Show HN: "Never wait on hold again" service built with Rails and Twilio  - <AUTHOR> My buddy paulsingh and I have been working on this for a few weeks, got something up and running and wanted to show you.
The problem we're solving: When you need customer service (your flight got canceled, strange fees on your bill, etc) you just want to talk to a real person. Waiting on hold wastes your time AND your concentration; you can't be coding in the zone when part of your brain is waiting for an operator.
Our solution: We wanted to make it "one click" to reach a real person.
How it works: You click on who you want to talk to (even a specific department, like the billing dept at AT&T) and we take it from there. Our system dials in, presses whatever buttons need pressing and waits on hold for as long as it takes. Only when we have an actual operator on the line do we call you.
Website version: http://www.fastcustomer.com (free) iPhone: http://itunes.com/app/FastCustomer (99 cents) Android: Know any great Android developers?  ;)
Technical: Rails + Twilio, hosted on Rackspace Cloud.
We'd LOVE your feedback, and if any HNers want to review it let me know and I'll send you a promo code.  If there are any companies you call regularly that we don't have (we're closing in on 1000 of the most-called companies) just say the word and we'll add 'em.  Also, if you can think of things to do with our API we'd love to talk to you.
Thanks for checking it out! <comment><USER2> And if you were a forward thinking megacorp, you could build something like this yourself. "Hiya, this is Paypal. Hit 1 to talk to ... Thanks. Type in your last four digits of your... Thanks Mr. McKenzie. Would you prefer to hold while waiting for a representative, or should we call you back in approximately 15 minutes? Hit 1 to..."

15 minutes later.

"Hello, is this Mr. McKenzie? Hiya, this is Steve at Paypal and I have your account brought up. What can I help you with today?"

I think that's far, far cheaper than $100k in dev costs and, if a 6 week test eliminates 5% of your CS spend while bringing your hold times down by 50%, that's like a career-making win. (Seriously guys: Twilio is the startup to watch. I say this while I'm literally wearing their sweatshirt but trust me, they're going to be _massive_.)

P.S. After you have it, you can trivially wire it into click-to-call on your webapp. "We can't show you that transaction, due to routine procedures meant to protect your account. Click here and type in your phone number, and we will have our Security Team contact you in the next five minutes. Thanks for using Paypal."

<comment><USER3> There are many SaaS companies which provide Call Center systems with the call back feature. It works just as you described. You call in and it asks for you phone number and calls you back when an agent is available. It even tells you your position in line if you call back too early.

<http://www.incontact.com> & <http://www.liveops.com> for those interested

</comment></comment><comment><USER4> Interesting, but this doesn't address the fundamental problem. The main reason that companies make you wait on the line is to differentiate the customers who care a lot about their problem from those who don't. By making the cost of waiting, for the customer, practically negligible, you are sidestepping this protection mechanism; your success would flood companies with less important support calls, thus giving them a powerful incentive to shut you out. At first, they'll just instruct their customer service representatives to immediately hang up on anything that sounds like your service. Next they'll ask the legal department for ammo, and do their best to implement technical counter-measures.

It's an interesting idea, but it's IMHO doomed long term, unless you find a way to take the companies' interest into account as well. For instance, in order to maintain the same system of customer disincentives you should probably charge per each minute your service is used.

</comment><comment><USER5> curious how you intend to handle abuse? Maybe have an sms sent to the recipient first and they must confirm? I was just able to enter the example number ("555-555-5555") and it seems to process just fine (currently "Status: Operator on the line! Trying to connect you...") even though I clearly don't own that number. I could cause problems for both customer service people and cellphone users with this. I'm assuming you don't do any of this based on the video though, I'm unable to test as I'm in the UK.

Excellent idea!

<comment><AUTHOR> Great question. There are a few ways we could handle it, but in principle we want to see how the problem happens before solving it. A confirmation process is a great idea but adds friction, and as we roll out we don't want to discourage usage. Basically, we want to see what happens so we don't optimize or problem-solve too early.

<comment><USER6> I personally would be quite worried about it being used for prank calls. At the click of a couple buttons anyone can create a very awkward conversation between AT&T and a random stranger (or a friend).

</comment></comment></comment><comment><USER7> Do you play an automated message when the tech comes on the phone? How many phone service technicians will actually sit there and wait to be connected to the actual user?

<comment><USER8> Also, a lot of phone service reps are literally not able to end a call. Often, the customer has to do it.

<comment><USER9> Not too sure about that -- this would prevent phone reps from ending calls when the connection with the customer isn't functioning properly (but yet the line is still active).

<comment><USER10> Maybe it can be done with manager intervention.

<comment><USER9> If true, you could pretty easily take down a call center simply by calling up and leaving the lines open with no caller. Managers would need to be running all over the place.

Since call center employees commonly have the ability to perform call transfers, I can only imagine they have the ability to hang up on calls. Otherwise, I imagine they could simply transfer the call to an invalid extension to "hangup".

</comment></comment></comment></comment></comment><comment><USER11> Love it. Twilio is a great platform. An idea: if you want to have the customer service rep doing productive work while he waits you can have the user type in a message with their information (account number / name / address) in a text field and read it out to the rep before telling them to wait.

It would probably make sense to do this only for paid customers in the future so that people don't abuse the feature (and CS reps).

Facebooked.

</comment><comment><USER12> I need this for conference calls. Normally, I dial in at the time the meeting is supposed to start, but nobody else comes for ten minutes. This means I have to sit around and listen to the "nobody has joined yet" music, which sucks.

A system where the system calls you when everyone has indicated availability would be much nicer. No wasted time dialing in.

And BTW, these conference call services typically cost something like 30 cents a minute times the number of participants. So if your product eliminated 30 wasted seconds of airtime per employee per day, you would save a company like mine 12 million dollars a year.

<comment><USER13> Founder of a conference call start-up here.

This wouldn't work for conf call services as you'd still be charged from the moment a call was connected on your particular 'room' irrespective of who actually called it. Although it would certainly save time and you wouldn't have to listen to the annoying hold music.

Oh, and if you organisation is really paying 30 cents per minute, then you should get in touch as we could save them well over 12 million dollars a year! ;)

Regarding the dial-out when everyone's ready service... we're working on it.

<comment><USER12> Yeah, I am sure you could. I could probably set up an Asterisk server that would meet our needs in about a day.

What I've learned from working for a big company is that they only want to save money if it makes their employees more miserable in some way. An example is turning off the lights and heat at 6PM. This saves a few cents, and makes anyone who wants to stay late miserable. A job well done.

With technology projects, though, the goal is to spend as much money as possible. For an individual to make money, he needs to be promoted. To be promoted, you have to have a big team. To have a big team, you have to have a big project. So the incentive is to make small projects into big ones. The easiest way to get a big project is to buy some Very Expensive software or service, and then hire a team to "customize" it. This way, your line item at the end of the year is at the top, so you must be Very Important and will get promoted.

Also, conference calls already "save money" -- you can have the important business people in the expensive financial centers, and you can have all the programmer monkeys somewhere cheaper, and they can still communicate effectively. (Not really, of course, but it looks good on paper.)

Anyway, this is a long way of saying, I doubt we will use your service any time soon. Maybe if you make it cost _more_ than what we have now, which a separate service like I originally described would :)

</comment></comment></comment><comment><USER8> Out of curiosity, how does your app know when a real human gets on the line...? Do you have a database of the automatic messages ("Please stay on the line while we sip Cognac and chortle") for each company so it doesn't get false positives?

<comment><AUTHOR> Indeed, we split test Cognac vs other drinks as an indicator of the psychographic profile of operators at various companies. Groupon is all about the rum and cokes, whatever that means.

Kidding! Yeah we play a message so the operators can hit 1 to get their next call.

</comment></comment><comment><USER14> <http://www.fastcustomer.com> clickable link

</comment><comment><USER15> Did you build the database of phone tree options yourself, or is there another place you're getting it from? Building such a database seems ridiculously time consuming.

<comment><AUTHOR> We originally looked at GetHuman, who really pioneered this space a long time ago. Their database is copyright so we would have needed permission, but one downside to crowdsourced data is that sometimes the crowd doesn't come back through and clean it. The result is that you have (for example) 9 different numbers to reach customer service, but what you really wanted was the best number. In the end we just did it from scratch.

</comment></comment><comment><USER16> Just bought your app for my IPhone. One comment: the app is not searchable on Fast Customer, only on FastCustomer (no space). If you just added Fast Customer to your description, it would be searchable.

<comment><USER17> Thanks for the heads up. Apple won't let me edit the keywords until we submit an update (which, actually, is coming soon)... I'll definitely get this fixed on the next release.

<comment><USER18> Never noticed that. Strange that you can edit almost everything else.

</comment></comment></comment><comment><USER19> Your monetization strategy should be... if you're calling at&t about a service issue, verizon could pay to be notified with the opportunity to respond to the call first and win your business.

<comment><USER20> Love it! To take it further, AT&T could choose to pay more to NOT have Verizon notified.

</comment></comment><comment><USER21> Brilliant. You've probably added a few years to my life, both in terms of hours lost and frustration listening to the same 24kbps top-40 song over and over.

Thanks. :)

<comment><USER17> best. comment. ever. :)

seriously, thanks!

</comment></comment><comment><USER22> Aaron and Paul,

You guys weren't joking when you said you were moving fast. Looks great. I'm kicking the tires now and will report back. As I told you in January, great damn idea. Let's grab a beer -Jason

</comment><comment><USER23> This is a great idea. Make sure you have the British Tax Offices on this list ;) Racked up a huge bill this month.

<comment><AUTHOR> Right now we're just USA and Canada, but we want to add more countries ASAP. I've added the British Tax Offices to the list though for when we roll out in the UK! Thanks for the feedback.

</comment></comment><comment><USER24> What an awesome idea. First of all, thanks for building this. Like others have said, you've probably added years to our lives.

As a novel bonus, it'd be neat if you could wire up a twitter account that did song recognition and status updates.

Currently holding to: "Michelle Branch - Everywhere" for the 472nd time!

</comment><comment><USER6> I'm interested to know what you plan on doing for revenue. I'm sure the cost of the calls will quickly outweigh the $.70 you're getting out of the app store.

Other than that its a great idea which I'm certain people would be willing to pay for (I would be if it was available internationally)

<comment><USER17> We're still figuring all that out -- for now, we just wanted to focus on making something that people want (ie, use).

Beyond that, we've got a couple of ideas that we'll be testing out -- maybe selling a brandable widget-based version to businesses, affiliate links, etc.

Not sure what will end up working but I can assure you that we'll be iterating pretty quickly. :)

</comment></comment><comment><USER25> I've used this service a couple of times, and everytime I don't have to wait on hold, I smile.

</comment><comment><USER26> Glad you are having a go at it. I had some thoughts around that space a while ago: [http://blog.outerthoughts.com/2007/01/calling-for-support- ca...](http://blog.outerthoughts.com/2007/01/calling-for-support-calling-for- trouble-the-business-idea/)

Point 6 there is similar to what you are trying to do.

Never did it, never will, but I do have a much longer document with additional idea directions and monetization strategies.

If you like and agree with the article, feel free to ping me and we can chat about the rest of the unreleased ideas. Like I said, I would be just happy for somebody to incorporate them.

Regards, Alexandre Rafalovitch

<comment><AUTHOR> Great ideas Alexandre, I'd love to talk.

</comment></comment><comment><USER27> This is a great service, and if I was in a position where I had to deal with phone trees regularily for my job, then I'd even be willing to pay something for it.

One minor gripe -- at least in Chrome, if you type something in ("Verizon") and hit enter without selecting any of the auto-complete options presented, you just get a generic "whoops, something went wrong". Ideally, just pop the user through a screen that lets them select from a list of possible matches.

I'd make a snarky comment about how the site doesn't render properly in IE 5.5, but I think I'm about 2 years late on that trolly.

<comment><USER17> Ah, sorry about that - I'm working on cleaning things up as we speak. We hammered out the MVP pretty quickly and have been hustling to make the service more reliable, scaleable, etc.

Polish coming soon, promise! :)

</comment></comment><comment><USER28> Great idea guys!

Just curious, what happens when someone finally picks up and hears nothing? Is there a possibility that the other line will hang up before you have a chance to call us?

<comment><USER17> So, there's definitely the possibility that you might pick up and hear nothing (maybe the operator hung up, we got a bad connection, etc)... but we've got a bunch of stuff working in the background to "gracefully" recover from that scenario. Regardless, we're going to get you an operator one way or the other. :)

</comment></comment><comment><USER29> Great idea. I think a lot of companies would love to add this to their own apps. You should start selling this to them ASAP.

</comment><comment><USER30> Fonolo has been offering this type of service for a while (<http://fonolo.com>).

<comment><AUTHOR> Fonolo is pretty cool. There's another similar service called LucyPhone. I'd say the main difference between those great services and ours is that with them you still have to be on the phone, listening to prompts and pressing buttons, and then they wait on hold for you.

With our service you just press a button and go back to your life.

<comment><USER31> Eh? As far as I can tell, these services do everything yours does.

EDIT: actually, Lucy makes you do the phone menus yourself. But Fonolo crawls the voice menus and generates a matching menu online (which is very slick, if it works).

<comment><AUTHOR> I'm definitely a fan of both services, they're great. Our goal is just to take it one step further, and do it all for you. Fonolo does have a beautiful system with the menus, but they do call your phone for you to do the navigating. You can try it out at <http://consumer.fonolo.com/>

<comment><USER32> Fonolo is awesome! My company uses their business service and it handles user input and waiting on hold too.

</comment></comment></comment></comment></comment><comment><USER33> Nice product, will be bookmarking and using in the future. I sent you a bug report to your woodmill email, hopefully you got it. I agree that you need to verify requests in some way, although my friends hopefully enjoyed talking to at&t and verizon randomly just now, I certainly enjoyed them getting the calls :)

</comment><comment><USER34> My ISP and phone provider iiNet (Based in Australia) do this. You call and chose the broad department you want to talk to (tech, sales, or billing), and you're told how long your wait is approximately, and asks if you want a callback on the number you're calling from.

Speaking from personal experience using this sort of system: It's _fantastic_ to use and if you're successfully inserting yourself as the middleman in this sort of experience you're definitely on the right track.

I can see this also being extremely useful for call out tech people who need to jump on the phone to talk to their clients providers on regular occasion.

Great idea, if you expand to Australia it'll be a must have app for me.

<comment><AUTHOR> Thanks, Australia is high on our list when we get to more countries.

<comment><USER35> Internode in Australia also do it, however they don't offer it to the caller until you've been on hold for 8 minutes. An option at the start of the call would be much better.

</comment></comment></comment><comment><USER36> I like it - it's giving a URI to customer service reps. Might be useful to provide a way for customers to create their own macros for services that you do not support so that the list can be both corporate-curated and community- driven.

</comment><comment><USER37> <http://www.fastcustomer.com> <http://itunes.com/app/FastCustomer>

<http://twilio.com>

Sorry if I missed them.

</comment><comment><USER38> The big companies like Amazon, etc already have this or could easily add it. I think this would be more useful for the thousands of other smaller companies out there. Perhaps you can wigitize this product and offer companies to place it on their website. I can see the longtail working out better.

On the other end, as far as I know for something like Amazon, etc you need to call in order to be put in the line for them to call you back. The cool thing about your service is I don't need to call :)

</comment><comment><USER39> This is an amazing idea. I would love to try it. Most of customer service calls I make are with Verizon who are actually quite good, but I want to try with airlines!

</comment><comment><USER40> ekanes--Have you looked into setting these up like freeconferencecall.com where it dead-ends the calls out of a rural area so you can collect subsidies? (Not a fan of the legislation, but if it exists you can leverage it.)

Not sure how you'd do this using Twilio, but rather than routing the user straight to the number, you could route the user to the rural number and then place an outbound call from teh rural conference number and patch the two together

<comment><AUTHOR> Interesting, thanks for the idea.

</comment></comment><comment><USER41> Has anyone else noticed that the California DMV actually has a service like this? If you call them and and the hold time is more than 30 minutes, they offer you the choice to hang up and be called when they are ready for you. Who'd think that would come from the fucking DMV?

</comment><comment><USER31> Would be totally rad if it could detect when any call is off hold. I bet there's some magic DSP heuristic that could do it, maybe with some false positives e.g. "your call is important to us..."

</comment><comment><USER42> So which is it? Do we spend 50 hours or 60 hours on hold? It looks like an inconsistency on your home page marketing copy.

This looks like a great idea. I think it has great word of mouth potential.

<comment><AUTHOR> Thanks for the catch, fixing it now. We hope it has word of mouth potential too!

</comment></comment><comment><USER43> REALLY Cool! How is rackspace cloud hosting? Reliable?

</comment><comment><USER44> Definitely a great service. Wish you guys luck!

</comment><comment><USER45> Are you A/B testing already? I like how the heading subtitle changes on every reload

<comment><USER7> More likely, they're just giving you a random subtitle each page load for fun or as an easter egg.

<comment><AUTHOR> Yeah, we're just having fun there.

</comment></comment></comment><comment><USER46> Best thing since sliced bread.

</comment><comment><USER47> How do you tell the difference between hold music, and a representative?

<comment><USER37> Isn't it a lot harder to tell the difference between a real rep and an inline hold message ... "your call is important to us"|"please have your customer number ready". Or indeed the pre-contact message "this call is being recorded [...]"

</comment></comment><comment><USER48> you guys are awesome.

A few friends and I have been working on a similar project. You totally upped us on it.

Great job :)

<comment><USER49> Synchronicity. We were discussing implementing this exact product not two days ago... decided against it since we couldn't beat Fonolo for free.

Glad someone else is solving this problem :)</comment></comment>


Iterated Prisoner's Dilemma in myriad languages - <AUTHOR> http://jacquesfuentes.com/essays/2014/10/31/Iterated-Prisoners-Dilemma-in-myriad-languages.html

<comment><USER2> I think I will try my hand at an Elixir version, based off the (very functionally well written!) Ruby version.

Also, you should have test suites for these. :)

Elixir's pretty cool if you haven't played with it yet- [http://elixir- lang.org](http://elixir-lang.org)

It's like Ruby, but 100% functional, immutable, concurrent, and faster. :)

<comment><AUTHOR> Thanks for the compliment and please do submit an Elixir version. I'm played around a bit with Erlang/Elixir but not substantially. I try to follow the Elixir community a bit and have done extensive reading of the OTP/actor system in Erlang :) Also, one of the reviewers of the article, Daniel Farrell, does Elixir for fun: [https://github.com/danielfarrell/sass.ex](https://github.com/danielfarrell/sass.ex).

Regarding test suites: yeah, I agree but it's a first pass and right now the "test" is "does running the program produce the correct output?" and that's sufficient for now:)

<comment><USER2> that "test" is literally 1 step away from a "proper" test :) Slap an "assert_equal" in there and boom, tested! Or heck even "raise unless expected == actual"

<comment><AUTHOR> Good point! I'll add an issue for it. Where's that Elixir version? :))</comment></comment></comment></comment>


Staygg - new app lets you invest small amounts of money for free - <AUTHOR> https://www.staygg.com/

<comment><USER2> I hate to be the naysayer, but NOBODY SHOULD USE THIS.

If you don't have a lot of money, open a Vanguard account and forget about it. If you don't have the $1000 to set up a Vanguard account, put your money in an FDIC-insured bank account. Seriously, if you don't have $1000 to invest you are MUCH better minimizing effort and risk than trying to make an extra 5% on your money (that's less than $50 per year).

Also, nobody should "invest" in any app that makes you pay to hide the ads.

</comment><comment><USER3> Finally it's here, the official Ponzi app.

But seriously - What exactly am I buying? Where are the details of the indexed fund? No charges, how does that work? Don't these people need to pay brokerage fees? I'm highly suspicious.

<comment><USER4> My guess: they are eating the management fees on an indexed fund that they are just managing themselves. With enough volume they can offer other fee-ful funds like the other guys and cover the costs. It's just a loss leader.

I'm assuming it's not a Ponzi scheme, but obviously could be wrong.

If everything is up-and-up this is actually kind of cool. I've been disappointed at the lack of decent investment options for low-income savers.

<comment><USER5> Some Vanguard index funds have a $1000 minimum and you don't have to risk your money with a (frankly) sketchy investment like this.

<comment><USER6> You can also buy them on the stock exchange for less than $10 in transaction fee, and I think the minimum there is a lot less than $1000.

<comment><USER5> Good point. IIRC, if you buy the ETFs directly from Vanguard, there is no transaction fee, making it even less expensive.

</comment></comment></comment></comment></comment><comment><USER7> It makes me a bit nauseous whenever I read or hear that somebody wants to outperform the market with an actively managed fund that is resembling an index fund. Like draugadrotten writes, such an endeavor can't be free.

The rule of thumb for the targeted audience of such a startup should be exactly the opposite. To never pay someone to actively manage their portfolio that is.

"Data from recent decades demonstrates that the majority of actively managed large and mid-cap stock funds in United States fail to outperform their passive stock index counterparts."[0]

Edit:

No, seriously. What the kids they are targeting need is to learn to manage their personal finances[1] and invest very early in very boring things. With a very simple and boring strategy that takes a couple hours a year[2].

Most fund managers are essentially useless[3] and according to numerous studies very seldom outperform the market. Unless you have millions in spare change to give away to someone who gambles with your money, stay away from them.

[0] [http://en.wikipedia.org/wiki/Active_management#Disadvantages...](http://en.wikipedia.org/wiki/Active_management#Disadvantages_of_active_management)

[1] [http://www.reddit.com/r/personalfinance/wiki/index](http://www.reddit.com/r/personalfinance/wiki/index)

[2] [http://www.etf.com/docs/IfYouCan.pdf](http://www.etf.com/docs/IfYouCan.pdf)

[3] [https://www.youtube.com/watch?v=SwkjqGd8NC4](https://www.youtube.com/watch?v=SwkjqGd8NC4)

<comment><USER8> I don't think it is promising to outperform the market at all

"Our fund aims to replicate the returns of the S&P 500."

<comment><USER7> Doing that reliably over a meaningful period of time is the problem. In my book (from the perspective of an investor) you'd need to "outperform?" the index to cover the costs of frequent trades and potential losses at no actual cost to the investor.

<comment><USER6> It says replicate, not outperform.

Just buy the Vanguard index fund.

It's easy to replicate the returns on the index, you just use the dividends to pay the fees, since the S&P500 index includes only capital gains only and is not "Total Return" (include capital gains plus dividend).

</comment></comment></comment></comment><comment><USER9> I honestly can't imagine any level-headed investor trusting any amount of money to a bunch of recently-graduated economics majors through an iPhone app.

<comment><USER10> At least they used vanilla Bootstrap for their website.

</comment></comment><comment><USER11> Is this mutual fund registered with the SEC?

</comment><comment><USER12> Why would I put my money here rather than robinhood.io, which is FINRA accredited, free, and has top tier investors?

This needs way better transparency

</comment><comment><USER6> What we need is an app to vacuum up whatever spare change is left of retail customers at the top of a stock market, and Staygg is that app.

</comment><comment><AUTHOR> Hey guys,

I'm Carlos, one the of the Staygg founders. The app is not a Ponzi scheme, the fees will be made up in other ways as described in the FAQs on the website, and the mutual fund will provide daily liquidity, will be registered with the SEC, and will nearly perfectly replicate the S&P 500 - it does not aim to outperform the S&P 500. The mutual fund itself will not be innovative in any way - except that it's free - and the investment team won't be actively managing the fund. The real motivation behind this product is that each person on the Staygg team thought it would be cool to have an app like this so we decided to make it ourselves and make it available to others.

Thanks for the feedback.

Carlos

</comment><comment><USER13> I think this trend is a disaster for tech/finance interoperability. You should - for all intents and purposes - be your most liquid in your savings. Not your least.

</comment><comment><USER14> \- Fees are hidden, nothing is "free" \- The time from when you pay until you own the shares is hidden The time from when you "sell" until you have the money again is hidden \- They "aim" to replicate the S&P500 but then they can differ. How much and how often. \- All risk and volatility is hidden \- Security of computer systems. They seem to be brilliant math guys with little computer security experience at all. Bitcoin syndrome.</comment>


Is this even remotely useful FOR YOU? (Save time looking for website templates) - <AUTHOR> http://websitetemplatebar.com <comment><AUTHOR> It was whipped together quickly and launched about 5mins ago. it's glitchy, but is the idea even useful/valuable? Would you use it over, say googling for templates/themes if it was ironed out?

Would love feedback? Is it just shit?</comment>


Gödel, Turing and Cantor: The Math - <AUTHOR> http://skibinsky.com/godel-turing-and-cantor-the-math/

<comment><USER2> Oh wow! This is a great write up on Godel's work. Anybody who even vaguely cares about fundamentals of computer science should definitely give it a read, and if possible a thorough read.

Slightly related: Although a more technical/deeper discussion, but the book "Godel's Proof"[1] by Nagel and Newman is a very approachable text in this domain, and explains many aspects of the incompleteness theorems.

[1] [http://www.amazon.com/G%C3%B6dels-Proof-Ernest- Nagel/dp/0814...](http://www.amazon.com/G%C3%B6dels-Proof-Ernest- Nagel/dp/0814758371)

<comment><USER3> Honorable mention for [http://en.wikipedia.org/wiki/G%C3%B6del,_Escher,_Bach](http://en.wikipedia.org/wiki/G%C3%B6del,_Escher,_Bach) which has been mentioned many times on HN. Has many different ways of explaining Godel's genius. Though to be fair you could just read this article and be good.

<comment><USER4> +1 for GEB. I have been reading it on and off for about 2 years. It's a fun book, but every time I finish a reading session, I am exhausted. I am about 25% through.

<comment><USER5> IMO just finish chapter 14 and you've basically finished the Godel portion of the book. The rest felt more like Hofstadter's random musings on AI, DNA and some other topics (some of which felt outdated). There's some crazy anecdotes of Ramanujin that I had never heard elsewhere though.

<comment><USER6> Well the structure of the book is supposed to be like a JS Bach song - so in the end, what you get is a combining of all the familiar themes and sometimes it feels a bit repetitive and boring. But if you've read that far, it's worth reading the rest. It's much easier to get through than when you're seeing stuff for the first time and really trying to wrap your head around it.

</comment></comment></comment></comment></comment><comment><USER7> There's a translation of Gödel's paper linked via his wikipedia entries [https://docs.google.com/viewer?url=http://www.research.ibm.c...](https://docs.google.com/viewer?url=http://www.research.ibm.com/people/h/hirzel/papers/canon00-goedel.pdf) [google docs viewer]

curious facts: he died of starvation; he was a theist [http://en.wikipedia.org/wiki/Kurt_G%C3%B6del#Later_years_and...](http://en.wikipedia.org/wiki/Kurt_G%C3%B6del#Later_years_and_death)

<comment><USER8> I found your semicolon quite confusing there - it seemed to suggest that there was some relationship between being a theist and dying of starvation.

<comment><USER9> On the contrary.

I imagine 6ren went to extra lengths to use a semicolon instead of a simple comma, as semicolons are used to emphasize independent clauses.

<comment><USER8> Independent clauses can stand by themselves _grammatically_ , that doesn't mean that their meanings are independent.

e.g.

> I hit him as hard as I could; he laughed at me.

Those are 'independent clauses', but the semicolon emphasizes the connection between them.

<comment><USER7> Radim is right. I actually tried a couple of other forms ("and" and ","), but they seemed worse. Challenge: can you demonstrate a better way?

I think the problem is not syntax but semantics: two unusual facts beg connection.

BTW: getting back on topic, his starvation seems due to a lack of faith... if some connection is expected, perhaps the best solution is to supply one, perhaps the poignant _He believed in God, yet died from lack of faith._

</comment></comment></comment></comment></comment><comment><USER10> This article took me to another from the same author

'[http://skibinsky.com/godel-incompleteness-for- startups/#foot...](http://skibinsky.com/godel-incompleteness-for- startups/#footnote-4')

and I found the below statement and laughed out aloud. Although in the context, this statement makes sense, in general, I trust books that don't belong to human-related matters (technical etc), because in human-related matters it is mostly one's opinion against others.

"As soon as these popular books leave the domain of human-related matters you are totally on your own."

</comment><comment><USER11> Chaitin is cool, too.

<comment><USER12> Definitely. I'd recommend his book _Meta Math: The Quest for Omega_ [1]. He posted the full text of the book on arXiv [2].

[1] [https://www.amazon.co.uk/Meta-Maths-Gregory-J- Chaitin/dp/184...](https://www.amazon.co.uk/Meta-Maths-Gregory-J- Chaitin/dp/184354525X) [2] [http://arxiv.org/abs/math/0404335](http://arxiv.org/abs/math/0404335)

</comment></comment><comment><USER13> What I find interesting are the claims Penrose[1] and others make about human versus machine intelligence based on Godel's results.

[1] [https://en.wikipedia.org/wiki/Philosophy_of_artificial_intel...](https://en.wikipedia.org/wiki/Philosophy_of_artificial_intelligence#Lucas.2C_Penrose_and_G.C3.B6del)

<comment><USER14> I'm sceptical of Penrose's arguments. We don't see human brains as symbol- manipulating formal systems, but that doesn't mean that aren't (or, more correctly, that doesn't mean that there is no symbol-manipulating formal system which is isomorphic to a particular brain, or brains in general).

Brains aren't implementing any known algorithm, but that doesn't mean they aren't implementing any unknown algorithm.

It brings to mind Minksky's advice to Sussman [http://en.wikipedia.org/wiki/Hacker_koan#Uncarved_block](http://en.wikipedia.org/wiki/Hacker_koan#Uncarved_block)

</comment></comment><comment><USER15> It would be interesting to speculate the consequence of Godel's Incompleteness deductions on the quest for Grand Unified Field Theorems in theoretical physics

</comment><comment><USER16> Does this mean that the antivirus industry is nothing but a scam?

<comment><USER17> it means antivirus industry will never be "complete"

<comment><USER14> Indeed, many incompleteness results (the most famous being the Halting Problem) are known as "infinite employment theorems". For example, we can always make a compiler perform more optimisations as follows:

1) Every diverging (non-terminating, non-co-terminating) program can be optimised to the following:

10 GOTO 10

2) The Halting Problem tells us that no compiler can spot every diverging program.

3) Hence there is room for more optimisation, by spotting more diverging programs.

4) Hence there is always more work to do for compiler developers.</comment></comment></comment>


When Parallel: Pull, Don't Push - <AUTHOR> https://nullprogram.com/blog/2020/04/30/ <comment><USER2> > If we're using concurrency, that means multiple threads of execution may be > mutating the same cell, which requires synchronization — locks, atomics, > etc. That much synchronization is the death knell of performance.

You can do this without synchronization by exploiting the fact that all "lanes" of a SIMD vector execute simultaneously, e.g. by doing vector scatters "to the left" and then "to the right" those writes will not race with each other, and don't require locks or atomics.

Whether pull or push is faster heavily depends on the algorithm - there is no silver bullet here. To write efficient parallel algorithms you need to know how to do both.

The author only appears to know how to do pull (if that's wrong, they didn't really do push any justice in the article), so from their POV push just doesn't work.

The article does show something very important though: pull does give you reasonable performance and is quite easy to reason about and get right. In contrast, push is quite hard due to the write-write data-races the author mentions, so I don't blame the author from arriving at their conclusion that one should always do pull. It might not always be true, but it is definitely a safe place to start, particularly if you aren't super familiar with the algorithm yet and don't know how or if push would work well.

For example, many of the convolutions that neural networks use are actually implemented using the "push" approach because that's more efficient, and they are quite similar to what the blog post author is doing.

<comment><USER3> What does push gain you over pull? Why would someone want to use it? Does it help with inplace updates vs having to duplicate storage?

<comment><USER2> The problem it solves is temporal cache locality, and whether pull or push is better often only depends on what is it that you want to keep in cache for the next operation.

For example, suppose you are doing a 3x3 convolution over a matrix, and you want to keep the result of the convolution in cache because the next operation consumes it.

So your cache is pretty much filled with the output matrix, and you only have space in cache to pull in one row from global memory for reading.

Now consider what happens if you process your input matrix row-by-row, first with the pull approach and then with the push approach.

With the pull approach you need to load 3 rows from memory into cache before you can push. No matter how you do this, as you advance through the input, you are going to be loading some rows twice. For example, suppose that from the 3x3 window, we load the rows in this order: top, bottom, mid (and then push the convolution to the mid row of the output). In one iteration we load rows 0, 2 (evicts row 0) and 1 (evicts row 2). The next iteration loads 1 (hit) and 3 (evicts 1), and then 2 (reloads 2!). That's bad!

With the push approach, you load one row, and push partial contributions to the 3 rows of the output matrix. Then you load the next row, and do the same. The output matrix is always in cache, so those writes always hit, and you never need to load a row from memory twice.

So in a sense, pull optimizes for bringing the rows of the output into cache once, which is good if you want to continue working with the input afterwards, while push optimizes for keeping the output in cache, which is good if you want to continue working with the output afterwards.

One isn't really better than the other. Which one to choose depends on what is it that you want to do. Maybe you have one input matrix, and multiple convolution windows, and want to compute multiple outputs that you don't need right away. In that case, you want to keep the input matrix in cache, and compute the rows of the output one by one, evicting them from the cache after each computation.

<comment><USER4> If you can't keep 3 rows of the input matrix in cache, why would you be able to keep 3 rows of the output matrix in cache? If the matrices are large enough that they don't fit in cache, shouldn't they be processed in squareish blocks recursively to maximize cache reuse (not in rows)?

<comment><USER2> > If you can't keep 3 rows of the input matrix in cache, why would you be able > to keep 3 rows of the output matrix in cache? If the matrices are large > enough that they don't fit in cache, shouldn't they be processed in > squareish blocks recursively to maximize cache reuse (not in rows)?

Your cache size is fixed by the computer and you can't change it. If you are doing a convolution, you want "(N+1)xN = cache size" to determine the size of the "blocks" (NxN matrix, and an 1xN row) of the convolution you process. Those blocks are also matrices, so by decomposing your matrix into smaller matrices you don't avoid this problem.

So sure, you could also decompose your problem by doing "(N+3)xN = cache- size", but that means that the size of the "square blocks" that you can now properly fit in cache is smaller, and need to decompose your original problem into more sub-problems to get it done. You could also do: "2Nx2N = cache size", and just load a whole input block and an output block into cache.

In both cases, you are bringing memory into cache that you only touch once, yet continue occupying cache space after you don't need them anymore. You could have used that space to process larger matrices instead, and have to decompose your problem into fewer blocks.

</comment></comment></comment></comment></comment><comment><USER5> A surprisingly simple way to be able to remove synchronization in certain cases. It's mentioned halfway through, but it's still worth noting: you can only use this if your operations are commutative, or you don't mind the lack of ordering. So it's good for things like cellular automata when you have double buffering but less good when you're touching the input directly.

<comment><USER6> an important note

</comment></comment><comment><USER7> Shaders are are a great place to use "pull".

Take an image that is 1024x1024 that you want to display as a 256x256 image.

The simple way to do this is to visit every pixel in the the source and write it to the display buffer [x'=x/4, y'=y/4]. 3 out 4 of those writes will just get written over in the display buffer.

A more efficient way is step though display buffer space and calculate where that pixel came from (reverse transform) [x'=4x, y'=4y]

<comment><USER8> No, they're equivalent. Nobody stops you from from stepping through pixels in multiples of 4 and then writing that to the display buffer.

<comment><USER9> You can write code both ways but it's much easier to ensure every destination pixel is handled exactly once when you interate over the destination pixels, than if you do it iterating over the source pixels. It becomes especially visible when you add perspective distortion and other complications.

Which is why every graphic api out there does it pull-style.

<comment><USER8> Drawing triangles on a screen is a push-style operation, isn't it?

<comment><USER9> Yes, from the POV of lists of polygons. But from the point view of textures it is pull (you go through destination pixels and fill them with source pixels fetched through transformation).

<comment><USER8> In the same way you could apply the reverse transform to the polygon and get the coordinates of display pixels in texture coordinates and then do a push from there.

They are equivalent, as I am trying to say. The only difference is semantics or whatever makes it easier to think about.

<comment><USER9> You would have to skip variable number of pixels in source texture according to the transformation, then calculate the reverse transformation to know where to push.

Notice how you not only change x * 4 into x/4, you also change x++ into x+=4

        for (int x=0; x<width; x++)
            for (int y=0; y<height; y++)
               destination[x][y] = source[x*4][y*4];

vs

        for (int x=0; x<width; x+=4)
            for (int y=0; y<height; y+=4)
               destination[x/4][y/4] = source[x][y];

If it's as simple as scaling: x+=4 isn't much harder than x++. But for complex transformations calculation of how many pixels to skip in any particular row will be slow and complicated. Meanwhile when doing pull you don't need to do it.

This is the reason every graphical API i know of does these tranformations iterating over destination pixels.

</comment></comment></comment></comment></comment></comment></comment><comment><USER10> That's a somewhat misleading wording for a classic rule of parallel algorithm: a thread is the owner of its computations.

So, each actor own a group of cells and is the only one able to modify them. This highly simplifies most algorithms, removes a lot of synchronization issues ...

This is also why in parallel algorithm you should split the outputs rather than the inputs.

<comment><USER11> Often, I find that "if you are synchronizing, you are wrong". Doesn't mean you can't or shouldn't use synchronizing in cases where message passing is impractical. However, it does mean that it should be a last choice rather than a first choice. It is simply far too easy to get locks wrong.

</comment></comment><comment><USER12> It's also an argument against using queues in some cases. Instead of publishing data on a queue, you can make consumers of the data pull the data. Especially if you have a 1 to many relation ship between producer and consumer of the data that moves the problem of ensuring data is received out of the infrastructure to the consumer side. Staying up to date is now their problem and they can ensure they are up to date by simply pulling regularly.

A good example would be the twitter firehose and consuming that. Other examples would be websites publishing RSS feeds. You can actually combine the two and push the information that "something changed" which would cause the receiver to pull. Caching and CDNs make publishing like this cheap and scalable.

<comment><USER13> Well, what do the consumers pull _from_ , if not a queue? What is an RSS feed if not a FIFO queue of published pages?

Queues inherently lead to a pull-based module. The producer does not publish stuff directly to the consumer, but to the queue. The consumers then pull stuff at their own pace/terms from this queue.

<comment><USER12> A rest API. An rss feed is a simple http GET that returns a document. You can cache it, put it in a CDN. There no queues involved here.

<comment><USER14> Can you expand on this? So each worker gets its own REST endpoint to pull from?

Because if all workers pull from a single endpoint then that endpoint is a queue, no?

</comment></comment></comment></comment><comment><USER15> This is pretty much the analogue of gather vs scatter in GPGPU programming. It's a well known fact that in GPU programming, in almost any case a gather approach (threads map to outputs) works better than a scatter approach (threads map to inputs). The challenge is to transform the algorithm to still have some data locality for the reads to allow for caching, coalesced reads into local memory etc, which can be very hard or infeasible.

</comment><comment><USER16> Sysadmins have been using this principle for decades.

When running a fleet of machines, it was always better to have them pull their config rather than push to them. It was far more reliable because you didn't have to worry about whether a machine missed a push.

It would just grab its config whenever it came back online.

<comment><USER17> Well yes, but like another comment here on HN points out, it's not universal, and there are trade-offs, and different systems have chosen differently. E.g.

Monitoring: Mostly push, except prometheus which is pull.

Config management: Mostly pull, except ansible which is push (yes, there is ansible-pull, but most ansible code out there assumes push).

<comment><USER18> In both monitoring and config management, the majority is right.

Monitoring: you don't want to have all your applications and even scripts run a thread to listen on a dedicated port to allow pulling. It's bad for security, code complexity, configuration complexity (all those ports) and reliability (when an application stops the datapoints are lost).

Config management: with a push model you can easily end up having 2 developers push to the same system (or to systems that should be updated in sequence) in an unmanaged manner.

<comment><USER19> Push based monitoring has its own flaws. Mainly service discovery is coupled with service health.

Pull based monitoring makes it so you can remove the service and independently recognize failures.

<comment><USER18> You can do the same easily with push.

</comment></comment></comment></comment></comment><comment><USER20> EDIT: Totally forgot we are giving a webinar tutorial on this on Friday as part of the Security (Analytics) Jupyterthon. See the Python GPU one-liners talk @ [https://infosecjupyterthon.com/agenda.html](https://infosecjupyterthon.com/agenda.html) !

The hardware opts desired here are vector data parallelism, both in bulk data movement and execution. When you realize that those are the instructions the device is running, yet are using languages or libraries that hide that, you end up easily going against the grain.

In contrast, I've been doing a lot of gpu dataframe stuff for the last 6 years, which is basically a specialized and embeddable form of functional nested data parallel libs from the early 90's . (See NESL and later Haskell generalizations. In the top 5 for most beautiful papers I've read!)

Writing code this way basically comes down to writing closed form / point-free solutions as pure maps & scans (~= materialized views) that in turn have easily automatically optimized multicore + SIMD / GPU implementations underneath. Put differently again, columnar analytics where you try to only do pure functions over columns (tbl.col_x + tbl.col_y; tbl.col_z.max()) yet get all your rich functional language features.

Another poster correctly said to focus on vector gather over vector scatter. That is the assembly code primitive starting point for this journey. NESL's nested functional data abstractions were invented precisely for automatically compiling into this kind of extreme vectorization -- and before GPUs were even a thing! By sticking to libraries built entirely for that, it's easy to write data parallel code that can run on say 8 GPUs, with way less brain damage, and lots of automatic invisible optimizations missed here.

The fun part to me is that parallelizing this kind of cellular automata simulation maps to a class of parallel compute called 'grid codes' or 'stencil codes'. There are DSLs with specializing compilers precisely for all sorts of weird tile shapes - imagine writing a weather simulator. Think autotuning, synthesis, etc. It's a dangerously niche space. I suspect GPU dataframe libs can help put them to rest, would be cool to see what extensions it'd take!

<comment><USER2> Which languages are you using?

In my experience, the main problem with expressing your algorithms in that way is "What do you do when the primitives you are suing (e.g. maps and scans) do not produce optimal code?".

For example, suppose that you are doing two scans with two maps, whose efficient implementation does a single memory traversal with the two scans and maps fused into a single kernel. If whatever abstraction you are using isn't able to do this type of kernel fusion, then you easily bump to a 4x larger memory bandwidth, which might be translated to 4x slower performance.

I don't know of any language or optimizing runtime that's able to do these transformations and match the performance of the CUDA code one would have written by hand.

<comment><USER20> I agree in the small and disagree in the large.

Something like single-gpu cudf (think pandas on GPUs) will have that issue because it is eager/concrete. When going to multi-GPU with dask-cudf or say BlazingSQL, the deferred symbolic compute means they can add in fusion, deforestation, etc. That is exactly what happened with Spark's CPU-era compiler over the years.

In the large.. we have a giant code base for GPU visual graph analytics. We hand write maybe 1% of the frontend and 1% of the backend. The libs underneath likewise have handwritten code where it matters, but are also built on the abstraction stack. So yes, we absolutely handwrite... in the tiny minority of cases :)

In practice, I care less about the 4x thing here -- rather get more of our code vectorized and more devs productive on it. In the small, what ends up mattering (for us) is stuff like making sure they do not do excessive copying, which is more of an artifact of trying to match Python Pandas's API design bug-for-bug. Likewise, stuff like testing for performance regressions across upgrades. We have been building a style guide and tools to ensure this, and are able to use practices similar to any big non-GPU software project (lint, CI, etc).

In contrast, a codebase on handwritten CUDA would be incredibly small and quickly out-dated. We have enough stress in our lives as is :)

<comment><USER2> That makes perfect sense, and it appears that you always have the option to handrol something if you discover it as a bottle neck worth fixing.

</comment></comment></comment></comment><comment><USER21> This reminds me of the oddball comment I read somewhere to the effect that " _come-from_ , despite all the humour, turns out to be a very sensible parallel-safe alternative to _go-to_ ". Can't remember the exact wording nor the source, though (unfortunately, because I've taken it to heart as very deep architectural wisdom).

<comment><USER22> If it helps, I've heard "return-from" used to describe Aspect-oriented programming.

</comment></comment><comment><USER23> This seems counterintuitive as it is the opposite of the programming 'rule': Tell, don't ask.

<comment><USER9> Yes. And it's one of the most important reasons OOP is so bad at multithreading.

You want "pretty" OOP? Tell Don't Ask.

You want performance and reliable multithreading? Command-Query Separation. Which is basically the same as functional programming :) Make all the functions pure except for a few clearly marked ones with side effects.

It's especially visible in gamedev. After a decade of trying to make OOP work with multithreading people moved on to Entity Component Systems (which is basically imperative programming with some relational and functional aspects).

It's also why functional programming is getting more popular - because it is pull by default. It's also why almost all graphical shaders are functional even if they look like C :) Many inputs one output and no side effects :)

<comment><USER24> > graphical shaders are functional even if they look like C :) Many inputs one > output and no side effects :)

That's not functional programming, it's just pure functions. Shaders make use of sequential execution of statements, and they don't support recursion.

<comment><USER25> you are splitting hair on definitions.

It is the pure function nature of functional programming that makes it easy for concurrent and parallel tasks. Recursion is neither here nor there

<comment><USER24> It's not hair-splitting. As I understand it, functional shader languages are an active area of research. Mainstream shader languages such as HLSL are most certainly not functional.

<comment><USER9> Languages are functional if they support higher order functions, recursion, closures, etc.

Code is functional if it separates side-effects to small, clearly marked parts of the codebase.

</comment></comment></comment></comment></comment></comment><comment><USER26> The author claims that their code is optimized, yet still took 10 days to run. Unfortunately, they missed a key observation that would have cut their runtime by 1/4 or more.

When stablizing a sandpile that begins in a symmetric configuration, it can never enter a non-symmetric configuration. Therefore instead of computing the whole 10000x10000 pile, you can compute just one 5000x5000 quarter of it, and add a special case for the internal edges. They should not subtract 4 when overflowing, but instead subtract 3 (or 2 for the corner) because they will always trade grains with their mirror image.

Although it's a bit more complex, you can also improve upon that by tracking not a quarter of the grid, but instead 1/8th by using a triangle. When tracking a triangle the cells on the main diagonal of the square are not mirrored, but instead their neighbors are. This may not work quite as well with their parallelism setup though.

<comment><USER27> Very interesting optimisations, but I would not say the author "missed" these points, since this wasn't the point of their post.

</comment></comment><comment><USER28> This is kind of silly. The author has reduced the number of mutations per entry by a factor of up to 4. That's why contention is reduced (less M(O)ESI eviction of shared lines). It happens to be that this problem is amenable to that kind of computation but it isn't always the case.

</comment><comment><USER29> Seems a bit similar to volcano model in databases, where iterators pull next tuple.

</comment><comment><USER30> It is much easier to build reliable distributed system when each component consumes (pulls) input and then publishes results.

This is mainly due to the fact that consumer knows when it is ready to consume.

</comment><comment> code-faster Designs based on pulling are also faster to code than their push equivalents, especially when parallel or in a client server model.</comment>


Leftpad-rs - <AUTHOR> https://github.com/hfiguiere/leftpad-rs <comment><USER2> Your code is a bit inefficient. I took the liberty of fixing that for you: [https://gist.github.com/lhecker/8e89d998c156f0bfdd2d](https://gist.github.com/lhecker/8e89d998c156f0bfdd2d)

(You can use that code freely and without any attribution if you want to.)

The important part here is to use `String::with_capacity()` to prevent unnecessary reallocations. Furthermore I used `usize::saturating_sub()` because it's neat and cleaned up the code with `rustfmt` (which you should use).

<comment><USER3> btw, creating the string with capacity was in my mind at one point. Some contributor submitted a PR already

[https://github.com/hfiguiere/leftpad- rs/pull/2](https://github.com/hfiguiere/leftpad-rs/pull/2)

Sadly it has gathered some rust (pun intended !)

</comment></comment><comment><USER4> Is there a special reason the tests are all asserting inequality? To me this only indicates if it doesn't do stuff it's not supposed to do, instead of working as intended: [https://github.com/hfiguiere/leftpad- rs/blob/master/src/lib....](https://github.com/hfiguiere/leftpad- rs/blob/master/src/lib.rs#L29:L39)

[edit] thanks for the explanation, I'm not familiar with rust and just assumed the bang would mean !=

<comment><USER5> The assert_eq!() calls are calls to the assert equals macro: [https://doc.rust-lang.org/std/macro.assert_eq!.html](https://doc.rust- lang.org/std/macro.assert_eq!.html)

In rust macro functions look like functions but end in a bang(!), it's not using ! to mean negate. [http://rustbyexample.com/macros.html](http://rustbyexample.com/macros.html)

</comment></comment><comment><USER6> I see i'm not the only one who did this. Leftpad for Swift [https://github.com/coryalder/SwiftLeftpad](https://github.com/coryalder/SwiftLeftpad)

<comment><USER2> Your version is quite inefficient too... If you call `insert(_:atIndex:)` N times it will obviously move the _entire_ content of the string N times by only a single character.

The optimal solution would be instead if you create a `CollectionType` which repeats the padding character N times. That way you could use `insertContentsOf(_:at:)` to insert N characters at once into the string and move the contents of the string only once.

If that doesn't work for you might as well simply allocate a new `String`, reserve `pad` chars of space, insert the `pad` chars and then insert the previous string. Even that is probably still faster than your previous approach.

In the end it's still probably the easiest approach in practice to simply use the `NSString` method `stringByPaddingToLength(_:withString:startingAtIndex:)`... :D

<comment><USER6> Thanks for the code review. To me this is the ultimate irony of this whole thing. Many have read it as "you should have written your own leftpad function, it's 11 lines!!" But no bit of code is too short to be buggy / inefficient. Centralizing it allows us to optimize/fix once.

While my implementation is basically a direct port of node's leftpad, pull requests are welcome. :)

</comment></comment></comment><comment><USER7> Lol this is all pretty funny. I also did this but in C++ to make fun of that JS crap.

[https://gist.github.com/zelcon5/7dc42bf91ea958132a0d](https://gist.github.com/zelcon5/7dc42bf91ea958132a0d)

\- "padding" can go either left or right.

\- generic function

\- minimal lines of code

Wow so great, make me a dependency for Windows11, Apache, Firefox, and toasters.

</comment><comment><USER8> I'd hate to see how the borrow checker destroys objects lent to remote systems... Along the vein of [https://xkcd.com/416/](https://xkcd.com/416/)

</comment><comment><USER9> inb4 "leftpad-as-a-service"...

<comment><USER10> too late: [http://left-pad.io/](http://left-pad.io/)

<comment><USER11> Oh my god, I'm crying

</comment></comment></comment><comment><USER12> Leftpad should be the new fizzbuzz in interviews.

<comment><USER3> there is a big irony in that comment... (very personal to me - that no one can get here)

</comment></comment><comment><USER13> So, what is the point of this? Highlight that it is possible to do to Cargo what leftpad has made to NPM?

<comment><USER14> Satire, most likely.

<comment><USER15> Or aiming for > 2000000 downloads ;)

<comment><USER3> definitely not.</comment></comment></comment></comment>


History, or Just Horror? On Historical Medical Images - <AUTHOR> http://www.slate.com/articles/news_and_politics/history/2014/11/old_medical_photographs_are_images_of_syphilis_and_tuberculosis_patients.single.html

<comment><USER2> In the last several months, I listened to the Hardcore History podcast about World War I. I am still struggling with the same question as the article poses, but applied to war instead of disease. I want to believe that it's respectful to try to understand these experiences on their own terms, maybe especially because of how horrible they were. But at other times I remember that I can walk away whenever I want, and so I can never understand, and if I enjoy the podcast (for example), is that exploitative?

I think it is important not to forget these people, but aside from that, no answer here.

</comment><comment><USER3> The horror is the history.

Forgetting that the history is horrible is where the _actually dangerous_ anti-vaccine lunatics came from, for instance.

The article, of course, ignores this.</comment>


Ask HN: Please, review wordoid.com, a smart naming webapp - <AUTHOR> http://wordoid.com

<comment><USER2> Important point on monetization.

I looked for a domain, found one I liked, and clicked "Buy". You sent me to godaddy, who I don't use. I opened up a new tab and bought it with namecheap.

A suggestion: give me a price comparison between multiple registrars, and let me click through to any. That way you get the commission even if I don't use godaddy.

<comment><USER3> This is similar to what Carl Mercier did with ajaxwhois.com

He talked this year at meshU in Toronto, maybe Wordoid could get some ideas from his experiences?

[http://www.slideshare.net/cmercier/how-i-founded- bootstrappe...](http://www.slideshare.net/cmercier/how-i-founded-bootstrapped- grew-and-sold-my-web-startups-meshu-2009)

<comment><AUTHOR> Thank you for the link!

</comment></comment></comment><comment><USER4> I opened up the page and just clicked "go"... seemed like a good place to start. I waited a few seconds and nothing happened.

Then I noticed the little clock at the bottom ticking away. "Okay", I thought, "it's working..." but 30 seconds later it still hadn't done anything (HN effect?). I'd disable the "go" button on click, and move the clock so that it appear right next to it (instant feedback is nice). You can re-enable the "go" button if any of the parameters change.

Also, in the time its taken me to write this it still hasn't generated any results (Mac 10.5, Safari 4). Don't know if it's me or you.

<comment><AUTHOR> ironkeith, this most likely is a HN effect (luckily? :) The webapp has been developed with performance in mind, however I've already noticed some glitches to fix.

<comment><USER5> Well done Oleg but where's the Russian language on the side? =) I don't know if it's in the works or what, because wordoid just generated veter.com for me (which is still available). Would definitely be fun.

<comment><USER6> I like this site very much!

However, I'd consider it an advantage for Russian speakers to NOT have Russian on the list. As a speaker of another language also not on the list, I wouldn't want any automated competition on coming up with words with that basis. (My other language has been a gold mine for me. ;) )

</comment></comment></comment></comment><comment><USER7> Good stuff. Had a quick play and definitely would use it to brainstorm ideas.

One really horrible usability point: when I enter a custom pattern on the right, I can't click enter to submit the form, but instead I have to go across the screen, up, and click the small Go button. Either do it live with AJAX or just add a proper form to refresh the page.

<comment><USER8> or perhaps add another submit button on the right, underneath the pattern choices

<comment><USER7> Yes, that's what I meant by a "proper form" but clearly it wasn't phrased with any level of eloquence.

To build on that: having the form split up is a bad idea. The sidebar serves no purpose really and I recommend all the form functions be collected at the top _and_ bottom of the results.

I'd also rename the Go button to something more sensible like "Search" or "Find". Go has very few good use cases, and even then it's dubious.

<comment><USER9> Along these lines, I would also recommend a graphical button for the go/search/find. Large, bright and tactile or 3-D (within reason). Make it clear "this is what you push" after filling out the form. Make it inviting.

I really like this idea. I spent several minutes looking through the suggestions and bookmarked it for later.

</comment></comment></comment></comment><comment><AUTHOR> Wordoid.com is a webapp that helps you come up with a catchy name for your product, company or domain.

It makes up new words that are unlikely to appear in a dictionary. It knows how to create words in several languages: English, Spanish, French and Italian at the moment. It is even able to create words in imaginary "languages", constructed by blending two or more real languages together.

I would appreciate your feedback!

<comment><USER10> I like it.

</comment></comment><comment><USER11> Woah, my last name appeared on the second page of results.

I found the distinction between "order" and "buy" unclear, although the color coding helps somewhat. Perhaps "backorder" (what Go Daddy uses) would be clearer? An option to only show available domains could be useful as well. Maybe an option to specify lengths?

</comment><comment><USER12> I like it... combining English words with a foreign language seems to make for some really interesting combinations.

Seems to be very quick as well which is great. Would be cool if it would check .com .net and .org variants as I wouldn't settle on a name unless all three were available (+ .co.uk as I'm in the UK!).

On another note, while I was playing with it, the name 'effection' came up and effection.com was showing as available. I went to my preferred registrar to buy* and it's actually registered. effection.com was originally registered back in 1999! So you may need to check out your domain look up code.

*no offence to you, but I work for a registrar by day and get staff rates!

<comment><USER13> Yeah, i saw "carlover.com" in green and thought "you've got to be kidding, i'd buy that in a heartbeat" (I love cars).

Unfortunately, it _was_ kidding.

<comment><AUTHOR> Wordoid.com checks domain availability by querying a DNS server. This is not completely accurate, since some domains don't have DNS records. The right way is to query a whois server. That's tough, because i don't know of any whois servers that would allow me send bulk queries.

<comment><USER13> Could do it yourself - <https://www.arin.net/resources/request/bulkwhois.html>

</comment></comment></comment></comment><comment><USER14> Great idea! Few recommendations:

Move the search box to a more prominent position, either to the top of right column or above the domain name list. Like someone else said, move the "Go" button next to the search box so there's a smooth transition.

I'd remove the box from the main page that lets the user specify "Ends with..." or "Begins with" and instead, once they've searched, give them the option to narrow down the search results (ie only show the ends with/begins options on search result pages).

Don't show domains that people have to buy. You won't get many people to click them and it adds clutter to the results.

Put more results on the page, as it facilitates easier browsing.

In the search results, you don't need a column for the wordoid and another for the domain name. Choose one or the other. I would choose the one that ends with ".com", as it will immediately be clear to new visitors to the site. If you go the other route and just display the word, put up a small notice saying "All words are .com" or something to that effect.

You could also make the list of domains links and have the links point to GoDaddy. (Again, less clutter).

I'm not sure how much the 'Common', 'Scarse', 'Unique' labels help visitors. Consider removing it.

Add an option to filter by length, as a lot of people seek out short names.

I like the site and wish you the best of luck. I created Domain Pigeon, which is very similar to this. If you ever want to chat about ideas or monetization numbers, you can find my contact info in my profile.

</comment><comment><USER15> Not to be a grammar/spelling nazi, but "scarse" should be spelled "scarce". (I suppose you could say it's just another wordoid though.)

The results are nice.

<comment><AUTHOR> Thanks for pointing this out! I should have checked it twice...

</comment></comment><comment><USER16> Very nice, I've been looking for something like this that actually works and isn't trivial. I got some really nice results.

First (nitpick point): You've got a misspelling in the page: scarse instead of "scarce" underneath the bars that show frequency.

The UI on the right is a bit confusing and busy. I suggest removing all the text around each of the options. I might then put them at the top of the screen with the "go" button. Move the descriptive text to a little popup (more info/?/help/whatever) link next to each of the options and shove all the text in there. Something like:

Languagae (more info): []English []Spanish []French []Italian

is going to be nice and clean.

My gut feeling is that most people are not going to read the text right away and they are just going to play with it and see what happens. This is why I suggest a clean UI so they can easily play, and give them ways to discover what the options do. You don't want to put speed bumps in front of users and force them to comprehend everything out of the gate.

Another usability point: I got stuck once I typed a pattern in. I tried to delete the pattern (to go back to random mode), but the site kept using the pattern. I then realized that instead of deleting the pattern, I had to change the dropdown menu to be "Create random wordroids". This leaves the text in the pattern box but does revert to the random setting. I would re-work this with some ajax or something so that it's not so confusing.

<comment><AUTHOR> Thank you for your extensive feedback, JunkDNA! I will take your suggestions into account while making the webapp better.

</comment></comment><comment><USER17> The interface is weird. The form fields are on the right and the submit button is at the top left, so you have to move your mouse across the screen for each query.

<comment><USER18> Yes - people do not read the right bar downwards and then go back to the top to 'Go' - it is a strange workflow.

Move the right column to the left I think.

</comment></comment><comment><USER19> This is a really nice naming app. I've looked at a lot of them and this has produced some of the best names I've ever seen. Congrats!

<comment><USER20> Yeah, I was a fan of <http://domainpigeon.com/> for a while, but that got a bit too restricted for me (as it became more commercial), not to mention a bit unwieldy to browse through. Bookmarked!

</comment></comment><comment><USER21> Hi!

Thanks for a useful resource.

If you change your DNS lookup method, I think you'll have fewer false positives where you list domains as being available, when they actually aren't.

For example: readia.com is not available, but the wordoid site says it is.

If you do a DNS lookup at the .com core servers, rather than your local resolver, you'll get a list of NS servers for the domain - if it's blank there, then you know the entry doesn't exist.

The current problem is occurring because your resolver library is trying to walk the DNS tree all the way to the DNS servers that are supposed to manage the domain. When those servers are down or unresponsive, wordoid is marking the domain as "available" - even when it's not.

Here's an example that I think demonstrates the problem, and a potential way around it:

dig ns readia.com. @a.gtld-servers.net. ... ;; ->>HEADER<<\- opcode: QUERY, status: NOERROR, id: 22290

Note that it indicates no error.

For a nonexistant domain the results are different. The NXDomain means "no such domain". dig ns this-really-does-not-exist-at-all-1321.com. @a.gtld- servers.net. ;; ->>HEADER<<\- opcode: QUERY, status: NXDOMAIN, id: 43679

Of course, you'll need to switch between the relevant gtld-servers so that you're a good network citizen, and cache results. See "dig ns com." for a current list of GTLD servers.

Also, I'd like to echo the comments of other readers - if you place a "go" button near the input form, rather on the top left, it'll improve the user- interface significantly.

Thanks again, and I hope the above helps you.

Oskar Pearson

</comment><comment><USER3> The 'Pattern' option on the side of the page is confusing. When you type in a pattern, it isn't apparent that you should click the 'Go' button at the top left of the page. Furthermore, when you type in a pattern and click 'Go', the default is to produce random Wordoids, not Wordoids containing the pattern.

The pagination at the bottom of the list doesn't give any indication of how many Wordoids were generated, which would be nice. Also, as others here have pointed out, the distinction between 'order' and 'buy' is unclear.

Wordoid is incredibly useful, great job!

<comment><AUTHOR> Well, it appears that the sidebar is confusing and non user-friendly. I will work on this more.

</comment></comment><comment><USER22> I was highly amused by searching for wordoids containing 'fuck'.

On a more serious note, I am trying to find a business name with a partner, and would have liked a link to a given page of results, so that I can share them.

<comment><AUTHOR> Thank you for the idea! I like it. Added to my todo list.

</comment></comment><comment><USER23> Nice work. This is a useful service and I'm bookmarking it since you've provided some neat naming ideas.

Only gripe, mentioned by others, is that I was a little confused by (a) the custom settings on the side and enabling them properly and (b) I initially missed the pagination/next button at the bottom - probably b/c it's below-the- fold. You should make that clearer, I initially assumed I only got 10 results back. Maybe add a results count at the top of the page and clear next/previous buttons at the top as well as the bottom.

Good luck!

</comment><comment><USER24> For some reason, the redirect links are broken for me in Safari. I get the message:

Safari can't open the page "[http://wordoid.com/RegistrarRedirect.aspx?registrar=godaddy&...](http://wordoid.com/RegistrarRedirect.aspx?registrar=godaddy&domain=example.com") because it's an invalid address.

For some reason (doesn't make sense to me) it seems that Safari doesn't like the keyword 'domain' in the query parameters, because changing that to something else actually sends the request.

</comment><comment><USER25> I got way more interesting results by switching to "Almost Natural".

<comment><AUTHOR> They really are! I personally like the combination of French and Spanish in "Almost Natural" mode.

</comment></comment><comment><USER26> Nice. Does this use a Markov-like algorithm for word generation?

<comment><AUTHOR> It does.

</comment></comment><comment><USER27> It doesn't seem to be working for me. I click on the "Go" and nothing happens.

On second thought, I see the tiny little clock spinning ever so slowly in the corner. I suggest making that a whole lot bigger and more obvious if it routinely takes this long to generate any results.

Must be something to do with my proxy here at work: I'm not getting any results -- even after a couple minutes and tries in different browsers.

</comment><comment><USER28> Very nice, good for brainstorming if you have a word or concept in mind. Good job.

(Second the 'went off and bought via my own registrar' though :P)

</comment><comment><USER29> doesn't seem to work at all for me - Chrome 126.96.36.199

<comment><AUTHOR> tripngroove, could you please elaborate more on this?

</comment></comment><comment><USER30> This is seriously cool. Great idea. Interface is a bit odd and should use some tweaking, but it didn't take me long to figure out. The look is alright otherwise, and I like the name.

One thing: The purpose of the site appears to be slightly confusing at first. Is this a site specifically for finding a domain name? Does it have a broader purpose? I don't know...

</comment><comment><USER31> I like it. It wasn't immediately obvious to me what some of the features did though - the search button and the unique/common graph next to it for example. I'm also a little disapointed it won't generate names in Klingon - after all, it offers to! :)

<comment><AUTHOR> I use it to show that no language is selected and avoid boring error messages. But may be I will add Klingon some day...

</comment></comment><comment><USER32> It's nice. It reminds me of domain pigeon, but the words it creates seem a lot more natural.

</comment><comment><USER33> Anxious to try this out. I just get a blank list of numbers in Safari, Firefox, and Chrome on Mac. Firebug tells me you're making an Ajax request once a second, seems... odd?

Clicking Go! seems to do nothing.

</comment><comment><USER30> One more point: While it is trying to figure out if a result is unique/scarce/common/rare/..., it says "Searching..." underneath. Wouldn't something like "Analyzing..." be more relevant?

</comment><comment><USER34> Great! Let me filter is by part-of-speech. Just do a rough guess.

For example, I may only want VERB wordoids.

Also, you should measure how easy and unambiguous the SPELLING is.

</comment><comment><USER35> Great tool. I heart it.

Will be nice to see more languages thrown into the mix. Sometimes you want to get out of english to explore more options. Will definitely use it more.

</comment><comment><USER36> Brilliant, I love it!

Would be interesting to hear whether you use a purely linguistic approach or some statistical information about "natural" frequencies as well.

</comment><comment><USER37> I'd examine relocating the buttons, or adding more to the top. I tended to just use the Go button over and over, instead of moving the cursor down to the Next button.

</comment><comment><USER38> Jorgem,

NameCheap is working on an affiliate program. We will keep you posted for sure via Twitter, newsletters, and our website.

</comment><comment><USER39> This rocks - exactly what I've been looking for.

<comment><AUTHOR> I'm happy you like it!

</comment></comment><comment><USER40> A feature I would like is to be able to filter out words according to whether they're scarce, rare, unique or common.

</comment><comment><USER41> I like it but it wasn't immediately obvious how to use it. Perhaps have something pointing at the right bar?

</comment><comment><USER42> Interesting concept, terrible usability.

</comment><comment><USER43> Useful site! I'd prefer if it generated more than 10 at a time by default.

</comment><comment><USER44> It would be good if you could filter out already taken names.

</comment><comment><USER45> Wow, it's like domain pigeon only way better. Awesome.

<comment><USER14> How so? :)

</comment></comment><comment><USER46> Doesn't work for me. I click go and nothing happens.

</comment><comment><USER47> Good results both in English and Italian</comment>