To add to this & the Jobs interview - an oil industry proverb: a healthy oil company has a geologist in charge, a mature one has an engineer in charge, a declining one has an accountant in charge, and a dying one has a lawyer in charge.
The spotify app has become so ridiculously bad I can't use it anymore. I found out about Zotify [1], which can rip my entire collection from spotify. The API rate limits anything faster than real time listening though, so it'll take a few weeks to download everything.
I find this part inspiring, regarding how to "respect the opportunity":
Practically, what this means is to first do the work that is given to
you. But once that's under control, to reach out into the vast Google
network, to learn what's being planned and invented, to coalesce a
clear image of the future, to give it shape through docs and demos, to
find the leaders whose goals align with this image, and to sell the
idea as persistently as you can.
The current edition of the "kit" is just a pre-soldered PCB, a plastic case, and some screws, it's basically a complete product.
The original DIY basic or pro kit are also close to complete - basically dropping some dev boards on 0.1" headers onto the PCB (and a USB-C connector, and 1.25mm pitch PM sensor cable, slightly harder).
You can also get just the bare sensor from a reputable distributor for $40:
Or get the same sensor from overseas for about $12.
I just built the AirGradient DIY Pro kit (no longer listed for sale on the website?), it's remarkable how PM and CO2 spike through the whole house when we cook on our natural gas stove - been waffling on that induction cooktop, but it's probably time! Still need to get the TVOC/NOx module to add to it...
I've never seen a cold and calculated layoff. It's always been exasperated irrational arm-waving risk mitigation. The "good" people aren't kept - instead it's the ones that can navigate the political waters.
For every one competent executive there seems to be 3 deluded narcissistic idiots who will slash and burn people who are overqualified and under-utilized for the positions they've been incompetently assigned.
Now before you think I'm a victim of layoffs, I'm actually the political navigator. I constantly survive layoffs as I see the most talented people get let go and the best teams get broken up and reassigned, it's nuts.
One of the best techniques is to get yourself into what I call a "management island" - essentially you have either 0 or many bosses, just not 1. The next one is to be associated with a small bet - essentially a cheap investment that may yield a great long-term payoff, preferably related to the company cash cow. A third technique is to not attend too many events. Vagueness works in your favor. People should know generally but not specifically what you do. With details comes critiques so keep it ambiguous by staying quiet.
If you survive a layoff then you must not let a good crisis go to waste. Use the fog of the firing and the power vacuum to resituate yourself into this political dynamic as the dust settles. Of course these techniques only work at large companies.
I learned all of these techniques from years in management. There's more but that's a good start
I use a roughly $6 HDMI capture dongle <- a $10 RCA to HDMI adapter <- an old VCR, and OBS is the capture software I use. Comes out pretty well, though you do basically end up watching each tape doing it.
It's simple and fast to tie (with a little practice for muscle memory), and with an extra turn has exceptional friction preventing loop collapse in some situations where even a bowline would have an issue. However, by relieving tension on one side of the knot, like a taut-line hitch it can slide.
I use it for its common application of tensioning, but I also find it useful for cinching. It can go anywhere a cord lock might have been useful in but a few seconds.
Your mention of modular arithmetic makes me draw a connection between this story and the way I think about ceiling fan pull chains.
Suppose the fan is clearly starting on high and you want to turn it off, but you don't know if the order of settings is "high-low-off", or "high-medium-low-off" (three states or four).
It's often difficult to tell if the fan is coasting off or just spinning down to low. If you get it wrong and pull one time too many, it goes back to high and you have to start over.
Therefore I always pull fan chains eleven (11) times to turn them off, so that I don't have to know if it's a three or four state fan. (Also works for on-off pull chains.) Pulling the chain 59 times would extend this technique to cover five-state fans, but I've never encountered one.
Another great related feature is how easy it is to “print” to Preview
BTW, if you are trying to save a protected PDF from Adobe reader that won't let you save it in an unprotected format that's compatible with Preview, there is "print" document trick you can try since Adobe Reader blocks the system print dialog: pause the queue for your printer (if you don't have a printer, just "install" a network postscript printer), and print the document. The document is then saved to a non-secured temp PDF file in /var/spool/cups, to a filename starting with "d" (ls -l -t to find the most recent file). That file is normally deleted after being sent to the printer, but my pausing the print queue, the file is there long enough to copy somewhere. Rename the document, and you're good to go.
This is a trick from the Mac OS X Hints days, and still works, as of at least Catalina.
In Hasura, you authenticate externally -- can be custom API endpoint that signs a JWT/auth webhook, or an auth provider like Auth0, Okta, Firebase, Keycloak, etc. Doesn't matter, just have to return some claims values.
You can then use these claims values in your authorization (permissions) layer.
IE, when a user logs in, you can sign a claim with "X-Hasura-User-ID" = 1, and "X-Hasura-Org-ID" = 5, and then put rules on tables like:
> "Role USER can SELECT rows in table 'user' WHEN X-Hasura-User-ID = user.id"
> "Role USER can SELECT rows in table 'organization' WHEN X-Hasura-Org-Id = organization.id"
There's more depth to it than this, but this is the gist of it.
This is an inspiring series of writing. After reading the intro, I expected to read the first and last post as suggested by the author for 'impatient' people like me.
However, after reading the first post, I'm wondering, should I read one post a day, at the tempo the author has written, and see if I can grok all (or some) of what they have?
Yes, yes I should.
There's something particularly impressive about any creator who comfortably exposes their journey, not only their destination. This is something I'm trying to work on, being okay with incompleteness. Maybe it's something we all struggle with.
It is, though I think he mentions advisers specifically in a different essay.
“Playing house” is something everyone interested in or already working on a startup should familiarize themselves with, be able to point out a teammate And seek to avoid.
Playing House activities are a hallmark of the rookie entrepreneur. I made these mistakes myself when I founded Gliph.
One reason to be particularly careful about this is there’s an entire class of professionals who do nothing but look for people playing house and offer the services for equity or cash that are not relevant to what make startups go.
They often hang around local non-valley startup incubators or angel groups. They are semi-retired people or in-between work themselves.
Lawyers love this type of “entrepreneur.” Because the meetings and attention drive billable hours and there’s always tax and legal work That can be found to be done.
None of these people have no idea what your users want. You’re supposed to figure that out.
If they have some gateway into your initial user base, they probably should be on the team and committed. Otherwise you should work on a different problem.
There are other ancillary activities to playing house that will disrupt your startup’s ability to succeed.
Listen to the podcast episode with Michael Seibel on the ycombinator podcast series. These problems often Are created by non-technical founders more often. Early stage, premoney, f&f or angel funded are the most vulnerable.
> If you apply for a $10k loan from a bank then, once the loan is approved, the bank will simultaneously:
- increase your current account balance by $10k (credit your current account)
- increase your loan account balance by $10k (debit your loan account)
That $10k deposit appeared from nowhere. You didn't 'put the deposit in', and it wasn't transferred from another customer or another bank. And the bank does not need to have $10k sourced from somewhere else.
This is not correct. A bank lends against its cash assets, not against nothing.
Bank accounting works like so: when you deposit $1 at the bank, the bank’s assets increase by $1 (the $1 you just gave it), and its liabilities also increase by $1 (the bank owes you your dollar back when you want it). A bank’s loans are financed by its assets; each dollar it lends is a dollar taken from the asset side of its balance sheet. When a bank lends you $1, it (1) decrements its asset balance by $1, (2) increments your bank account by $1, (3) creates a new asset representing a $1 loan on its own balance sheet, and (4) creates a new liability for you representing a loan of $1 owed.
Point is, a bank does not create money from absolutely nothing when making loans in the way you describe. All loans are financed by the bank’s assets, and a bank cannot originate a larger value of loans than the value of its cash assets. Bank “money-creation” refers to the fact that the total bank account balances in the economy increase when a bank makes a loan; this happens after what I described in the previous paragraph, since the $1 loan now increments your bank account, while nobody else’s bank account balance decreases.
(To see how this works in more detail, imagine the process begins with Alice depositing a one-dollar bill at the bank, and then the bank loaning Bob one dollar. Keep track of the distinction between who has the one-dollar bill and who has a one-dollar bank account balance. The loan proceeds as follows: first the bank gives Bob the one-dollar bill it took from Alice as a deposit, then Bob turns right around and deposits the one-dollar bill back at the bank. The result is that Alice and Bob now both have $1 bank account balances after the loan is made, whereas only Alice did before; the bank still has the one-dollar bill. Summing either bank account balances alone or balances plus dollar bills shows $1 more after the loan was made.)
Ventilators for covid19 seem to be mostly for inflammation and fluid in the lungs (aka pneumonia), not lung or chest paralysis.
If you need a ventilator due to inflammation or fluid build up, you can do other things to address those issues.
If you are doing home care for serious lung issues, a downside of mechanical intervention is that you probably don't know how to adequately sterilize your equipment. This means nasty stuff grows on the equipment and then this nasty stuff gets delivered directly into the lungs.
So I'm not thrilled to pieces to see the emphasis on "ooh, shiny!" homemade technical solutions in place of non-invasive home care.
You can do lung clearance without mechanical intervention. This can make a ventilator unnecessary.
You can do lung clearance easily on your own in the shower by standing with your feet shoulder-width apart or a bit wider, bending over as far as you can and coughing hard.
If you bring up a lot of fluid from the lungs, it looks and feels a whole lot like vomiting. My sons and I call it "puking up a lung."
Inflammation can be combated with commonly available non drug remedies, like caffeine, lettuce, avoiding pro inflammatory foods (avoid peanut oil like the devil himself made it for you, limit or avoid bacon as it is hard on the lungs).
Etc.
Please see my previous remarks about best sleeping positions, etc.
I am very concerned that homemade ventilators are going to become a source of secondary infection and this secondary infection will be worse than covid19 because it will be bacterial or fungal and it will be antibiotic resistant.
If I had any idea how on Earth to start a counter movement, I would be all over it. I have no idea how to do that, so I occasionally leave a comment on HN giving some of my thoughts, which isn't likely to exactly catch fire. This is today's comment in that vein.
That's brick-and-mortar: personal service, ready in 30 minutes. Around 8000 yen, frames and lenses. (Not the thinnest lens, no special coating, but very good.)
> You do need your pupillary distance, but you either measure this yourself with the help of a friend
I have a fool-proof way to do this yourself.
Use a mirror and a ruler. Place the ruler on the mirror and stare with your left eye into that same eye's mirror image, such that the ruler's 0 tick is centered on the pupil. Then, open your right eye and close the left. Stare into your right eye across the ruler and note the millimeters. Flip back to the left eye to make sure you haven't moved from zero.
This is dead accurate. Staring into your own eye in the mirror means you have a perpendicular line from either eye to the ruler.
We're in a similar place -- finished our first priced round.
Comments:
Blatant unfairness: yes, warm intros are required. Yes, this is unfair. However, the onus is on you to make this happen. If you want to found a startup, put your time in to building your network. If you're at a startup now, get intros to the VCs. Ask to go to VC meetings.
When you're building the network of people you're going to ask for angel cash, do the same. Lots of them will be happy to give you those warm intros. So start now building a network of people you can ask for $10-$25k. This wasn't obvious to me, but an intro to a vc from an angel who has invested counts as a great intro.
The same network will get you into one of the good lawyers (cooley, sonsini, gunderson) with a warm intro who will also do a deferred fee deal for $15-$25k. You want this.
The other thing that is unfair is, at least in b2b, the more customers you have the easier a raise will be. How do you get those first customers when you have nothing except a site that breaks all the time and a tiny team? That's your problem; make it happen.
Passionate origin story: we build a b2b tech. Most VCs seemed happy with
1 - we understood this problem from working on/near it
2 - we're building a solution
Oh, and read the book _venture deals_ by brad feld and jason mendelson [1]. Seriously. It's extraordinarily valuable.
Seriously consider doing the YC pre-YC program. It's all funnel for YC, but the info is good. Though it can be summed up (only somewhat facetiously) as, "Have you talked to customers yet? Maybe you should talk to customers. If you've talked to customers, talk to more! If you've talked to more customers, talk to even more! And after that... talk to some customers!"
Understand that the seed and A all want 25%; plan accordingly. Within that range, they are less price sensitive.
If you have questions, I'm happy to answer them, but I'm busy (the startup experience is everyone in your life is grumpy at you for flaking on them) so no promises on response time.
Ok, but there are a bunch of reasons why I think you should actively avoid "markets best served by hourly work":
* It positions you against the lowest-quality cheapest providers.
* It misaligns your incentives, so that you're penalized for doing a better job.
* It totally hides the cost of ramp-up and ramp-down (if you think clients push back on daily or project rates, wait until you charge them for 2 hours of "getting in flow").
* It forces you to be vigilant about time tracking lest you accidentally undercharge customers.
* Not to mention, with virtually any client worth doing business with, you (the consultant) are much more sensitive to the cost of a project than the customer is; it is a small miracle that the customer can get a programming project completed at all without potentially hiring and then firing 3 different people. So why is all the burden on you? Why is any of the burden on you? Key consulting idea: it's not the customer's money they're spending.
* It inclines you towards finicky accounting, the kind that charges a customer for a 45 minute phone conversation.
* It conditions your customers to take a fine-tooth-comb approach to project plans and invoices.
* Not to mention: it generates more invoices.
* It forces you to negotiate with clients in the worst possible numeric domain: where small deltas to proposed rates disproportionately impact the final cost.
* It obscures the final cost of projects in ways that make clients defensive, so that their immediate thought is "oh shit this is going to add up to lots of hours we better be careful".
* For that matter, it inclines your projects towards the small and away from anything ambitious.
* It impedes your own flexibility, so that you tend to miss opportunities to interleave projects or for that matter take an occasional long lunch.
* It forces you to account for every waking hour of your day in a way that daily rates don't, when we all know that only a small subset of your work hours are truly productive.
* It makes it harder for you to reasonable toss freebie work to your best clients without damaging the expected value of your time; for instance, I can cab over to a client in Chicago and spend 2 hours looking at a design with them for free without creating the appearance that my bill rate is arbitrary.
PG JSON implementation is solid and supports nearly everything you want from a document database, with the added bonus of joins, queries, ACID, and tooling. However, syntax can be awkward at times -
# Find a row by JSON property value
select * from person where details->>'name' ilike '%james%'
# check for property existence
select * from person where details ? 'is_hidden'
# Override a single property in a JSON field -
update person set details = details || '{"phone":"911"}'
# Alt increment existing value
update person set details = jsonb_set(details, '{views}', (details->'views')+1)
Just to expand a little bit upon the sibling comment.
Let's say you need a function that maintains internal state. Now, in non-pure languages, you could that by simply referring to some global variable, but let's agree that's bad. So how can you model internal state purely?
Simple, your function takes the current state and produces a new state, along with its result. So, a pure function like:
f(String) => Int
turns into the stateful function:
f(String) => (State => [Int, State])
I.e. a function that returns a function that takes in a state and produces a result and a new state.
Cool, but now let's say we have another function g:
g(Int) => (State => [Double, State])
Let's now say we want to compose those two functions:
let result = g(f("5"));
However, this won't work, becase f produces (State => [Int, State]) but g expects Int.
So, here's bind for the State monad (implementation is not important):
> Why do I need a monad then, if there are similar constructs in other languages that don't need the understanding of monad? Why the complexity? What do I get from monads?
They remove the need to type the same shit over and over again. With a list monad you avoid having to write the loop constructs, for the Option/Maybe monad (optional value) you avoid having to write if/then/else, for the Either/Choice monad you avoid having to write if/then/else and manually propagating an error value on failure, for the State monad you avoid having to pass a context value through as an argument to every function, for the Try monad you get exception handling and error propagation like the Either/Choice monad, with the Writer monad you are able to do logging without a global logging system or having to manually pass through a logging context, etc.
Ultimately they're there to reduce boilerplate and to help write more composable and reliable code. There are other benefits, but this encapsulation and abstraction of common patterns is what most programmers strive for, no matter what language they use, so I feel it's important to put them in that context.
Let me give you a very simple example. I'm going to use C# because it's been a long time since I've done any Haskell and I'll probably get it wrong.
I'm going to create a monad called NoNull. If at any point it sees a value that is null then it will stop the computation and return without completing. It's a slightly pointless example because C# has the null propagating operator, but conceptually it should be easy for any programmer to grasp that using null is bad, so being able to 'early out' of a computation when you get a null value is desirable.
First I'll define the type:
public class NoNull<A> where A : class
{
public readonly A Value;
public NoNull(A value) =>
Value = value;
public static NoNull<A> Return(A value) =>
new NoNull<A>(value);
public NoNull<B> Bind<B>(Func<A, NoNull<B>> bind) where B : class =>
Value is null
? NoNull<B>.Return(null)
: bind(Value);
public NoNull<B> Select<B>(Func<A, B> map) where B : class =>
Bind(a => NoNull<B>.Return(map(a)));
public NoNull<C> SelectMany<B, C>(Func<A, NoNull<B>> bind, Func<A, B, C> project)
where B : class
where C : class =>
Bind(bind).Select(b => project(Value, b));
}
It's a class that has a single field called Value. The two functions to care about are:
Return - Which constructs the NoNull monad
Bind - Which is the guts of the monad, bind does the work
Select and SelectMany are there to make it work with LINQ. I have implemented them in terms of Bind.
As you can probably see Bind is encapsulating the test for null, and if null is found then the result is Return(null), it doesn't run the `bind` delegate.
Next we'll create some NoNull monadic strings:
var w = NoNull<string>.Return("hello");
var x = NoNull<string>.Return(", ");
var y = NoNull<string>.Return("world");
var z = NoNull<string>.Return(null);
The last one contains null, the bad value.
I can now use those values like so:
var result = from a in w
from b in x
from c in y
select a + b + c;
Notice there's no checks for null, the monad does that work for us.
In this instance, result.Value is equal to "hello, world".
Now if I inject a bad value into our monadic computation:
var result = from a in w
from b in x
from c in y
from d in z // <--- this is null
select a + b + c + d;
Then result.Value is equal to null and the `a + b + c + d` didn't run at all.
The alternative is this:
string w = "hello";
string x = ", ";
string y = "world";
string z = null;
string result = null;
if (w != null)
{
if (x != null)
{
if (y != null)
{
if (z != null)
{
result = w + x + y + z;
}
}
}
}
Where the programmer constantly has to do the work that the monad will do for free. I've nested those if statements to try and give you the impression of what the series of 'from' expressions are in the example above (in Haskell it's known as 'do notation'). Each 'from' creates a context over the whole of the rest of the expression.
For the avoidance of doubt about the nesting, I could have written it thus:
var result = w.Bind(a =>
x.Bind(b =>
y.Bind(c =>
z.Bind(d =>
NoNull<string>.Return(a + b + c + d)))));
Here [1] is an example of a Parser monad in action in C# (it's part of a parser that parses C# source that I use to generate API reference docs for my github projects [2]). This runs code 'in the gaps' between each 'from' statement. What it does in those gaps is check if the parser above it failed, and if so it bails out with an appropriate error message based on what it expected. But you don't see any if(result.IsFaulted) ... code anywhere, or maintenance of the position of the parser in the input stream, because that is encapsulated in the Parser monad. It makes the code very clear (I think) in that it's not cluttered with the regular scaffolding of control structures that you usually see in imperative languages.
What's really quite beautiful about monads is the way they compose, and I think this is especially beautiful with parser combinators. A Parser<Char> which parses a single character has the same interface as a Parser<SourceFile> which parses an entire source file. Being able to build simple parsers and then combine them into more complex ones is just a joy to do. Clearly parsing isn't unique to monads, but there's an elegance to it (and monads in general) which I think is hard to resist.