HN user

drostie

4,724 karma

Hi, my name is Chris Drost. I'm an application developer at U.S. Engineering Company in Kansas City, MO. If you're a talented software engineer in the KC region, hit me up -- we may be hiring.

I am @crdrost on Twitter and Facebook. I almost never check my Facebook.

I have an M.Sc. in Applied Physics from the TU Delft in the Netherlands. I am from Ithaca, NY originally.

You should listen to more Troubled Hubble.

    Don't you forget the, the image in your retina
    To foresee the future, and find a use for
    Them telling me, everything, 
      that would happen to me anyway.

    If it isn't science, it doesn't exist;
    We make our own problems and blame them on
    Birds and bees, but we ain't seen nothin' yet:
    and don't you ever forget it.
Also, more Glaze.
    Every night I wake up,
    Thinking there's something missing in my heart:
        a canvas for the art.
    Every day I hear the sound of whirring fans,
    But nothing more:
        another scene yet to be scored.
    
    You're the empress, I'm the king:
        together we will rule this world
    You'll paint the scene, I'll write the melody:
        we will rule this world.
Maybe also some '90s stuff.
    And of course you can't become, 
    If you only say what you would have done:
    So I missed a million miles of fun.
Email me by my HN username @zoho.com or my twitter handle @gmail.com.
Posts40
Comments1,051
View on HN
gist.github.com 8y ago

Itero-recursive algorithms

drostie
1pts0
www.lkozma.net 8y ago

A paper/pencil game (2007)

drostie
1pts0
github.com 9y ago

Show HN: Kells, an abridged form of Haskell for building DSLs in JS

drostie
6pts0
gist.github.com 10y ago

In ES6 async code can already be written synchronously with generators and yield

drostie
1pts0
www.charlotteis.co.uk 10y ago

Open Open Source

drostie
1pts0
www.coindesk.com 10y ago

Complaints hit “record levels” at Blockchain amid confirmation delays

drostie
1pts0
walkercoderanger.com 10y ago

Advice for Open-Source Projects (2015)

drostie
3pts0
physics.stackexchange.com 10y ago

Can we tell when an established theory is wrong?

drostie
1pts0
medium.com 10y ago

OK, so you want to learn how to code

drostie
2pts0
james-iry.blogspot.com 10y ago

Erlang Style Actors Are All About Locking (2009)

drostie
3pts0
www.cambus.net 10y ago

Decommissioning a free public API

drostie
2pts0
blog.ezyang.com 10y ago

Is no-reinstall Cabal coming to GHC 8.0?

drostie
1pts0
blog.ezyang.com 10y ago

Help us beta test a version of Haskell's cabal that fixes “dependency hell”

drostie
2pts0
www.fastcompany.com 10y ago

How Giving Up Refined Sugar Changed My Brain

drostie
1pts0
bitquabit.com 11y ago

Abandon your DVCS and return to sanity

drostie
331pts310
symfony.com 11y ago

Symfony 2.6.4 released

drostie
2pts0
www.theatlantic.com 11y ago

How Patient Suicide Affects Psychiatrists

drostie
2pts0
www.pbs.org 11y ago

Deep-Space Climate Observatory (warehoused in 2001) will launch on Jan 31

drostie
3pts0
community.zimbra.com 11y ago

POODLE and SSLv3 (advice: disable SSLv3 on email servers)

drostie
2pts0
www.cryptamail.com 11y ago

CryptaMail – Secure decentralized email built on top of a cryptocurrency

drostie
3pts3
github.com 12y ago

Show HN: nermal, the cutest secure JavaScript authenticated encryption container

drostie
2pts0
blog.archive.org 12y ago

Celebrate at the Internet Archive, 10/24

drostie
1pts0
flippinawesome.org 13y ago

JavaScript Inheritance – How To Shoot Yourself In the Foot With Prototypes

drostie
3pts0
www.circuitlab.com 13y ago

CircuitLab - Draw circuit diagrams and simulate what they do

drostie
3pts0
www.nytimes.com 13y ago

Universe as an Infant: Fatter Than Expected and Kind of Lumpy

drostie
1pts0
openindiana.org 13y ago

Illumos/OpenSolaris: "I needed to live 6 weeks in my old Mercedes."

drostie
1pts0
www.dailymail.co.uk 13y ago

Hundreds of words to avoid using online if you don't want the US to spy on you

drostie
1pts0
www.lightbluetouchpaper.org 13y ago

How much has password cracking improved?

drostie
3pts0
www.guardian.co.uk 13y ago

Experience: a head injury made me a musical prodigy

drostie
2pts0
creativecommons.org 13y ago

California passes groundbreaking open textbook legislation

drostie
283pts73

I like the idea but find that an overstatement that trivializes the nature of technical debt: at some level one is talking about things that "pay off now" but require "interest payments" in the future" and while one can kind of squeeze the line `for (let i = 0; i < array.length; i++) {` into that framework, experience says that that line by itself almost never requires a maintenance debt payment; if you have a list then you almost certainly want to iterate through it and refractors are driven by the size of the list, not by the bugginess of the looping construct...

I think what's really at stake is that code and data are a sort of inventory: they are not what you are selling, but they get turned into what you are selling. Inventory always has a carrying cost, and generally people underestimate that because they are only looking at the direct cost of storage, not how the presence of the inventory itself gets in the way, makes getting to other things harder, makes bottlenecks harder to see.

And that's where you see that debt is a wrong metaphor, because debt has the particular property that you can pay all of it off and that would be a good thing. By contrast inventory is a good thing in the right place: It means that if one thing stops working, the system can still continue for a while. Really operating with zero inventory everywhere is possible, and it's not done because it would drive you out of business. Similarly, deleting all of your code is not accessible in the way that getting rid of all of your debts is.

Designing an API to have a separate messaging later from its business layer from its data management layer from its data fetching layer is a technical debt; the fact that any change in the system now needs to be distributed across 10 different places in the code base is your interest payment. I would argue that you would like to derive all of these from some shared source of truth to remove those interest payments, and when you do, I no longer think that it's a bad thing for you to have a homebrew HTTP framework that has those separations in its internal functions.

This is actually really interesting and mirrors a more general effort that I am pursuing[1] to build runtime representations of type in TypeScript, though my context is not so much GraphQL but rather just a more traditional HTTP API.

It looks like you try to keep it so that the runtime type object itself has the correct TypeScript type? That is, I would expect that under the hood you either have `types.number = 0`, `types.string = ''`, and so on and then you just use `typeof runtimeTypeObject` to derive this, or something more sinister like `types.number = ('number' as any) as number`. Either way that's fairly clever and I like it. I probably won't do it that way in `tasso` because one of my abstract points of power is that `tasso` should be able to validate that a given type object is a valid `tasso` schema, so there should be a metaschema. But it is really nice to have this thing saying just `typeof runtimeTypeObject` and not `ValueOfSingleType<typeof runtimeTypeObject>` to derive, from the schema's type, the instances' type.

I may steal one thing for `tasso` from this library, and that is the way your `constant()` works without specifying type metadata; I was under the impression that even with the `<t extends string>` TypeScript would still say "well `const x = constant('abc')` doesn't say anything else about `'abc'` so I am going to infer that it is a `string` and then string does extend string so `x` has type `string`," much like it does when you just write `const x = 'abc'`. I didn't realize that you can "hint" that you want the more generic type for the thing. In tasso this manifests when you are writing self-recursive schemas, like

    // the following line is a sort of hack
    const refs = tasso.refs<'cell' | 'list'>();
    // but then we can write stuff like this
    const schema = {
      cell: tasso.number,
      list: tasso.maybe(tasso.object({
        head: refs.cell,
        rest: refs.list
      }))
    };
It will be nice to replace that with `tasso.refs('cell')` and `tasso.refs('list')` without that "refs object", I think.

[1] https://github.com/crdrost/tasso

Hm. I will have to retry. You're right that this is my work laptop and sometimes Sophos does weird crap. Sorry for alarming you without checking downforeveryoneorjustme first.

I have read the source; indeed reading the source of redux-thunk was necessary for me to conclude it was pointless. I like everyone else thought that it was doing something more than `go = fn => fn()` does.

The code that I wrote you is logic which needs access to `dispatch` and `getState` when it runs, but it is not bound to specific references of `dispatch` and `getState`. It does not use your hack of importing a store from a global location, so it does not have problems with (A) or (B).

You cannot avoid grabbing that reference to props.dispatch either way. The crux of the argument that redux-thunk is just syntactic sugar, is that dispatch is already in scope whenever it is used and can be passed as an argument or a closure.

I agree somewhat with refactoring async logic into its own component when one wants to reuse it and make it portable. The question is just, should you pass `dispatch` and/or `getState` as an argument to that function? Or should you curry that dependency to a subfunction and pass that function as an argument to `dispatch`?

I opine that the latter is objectively worse than the former. You have `dispatch`: hand it directly to the function, let people know that this function is not an actual action but an asynchronous process. We are talking about a syntactic sugar, in other words, that doesn't make anything sweeter.

I'm actually refreshed to be reminded that the Redux store is a closure, I had forgotten since I first read the Redux code several months ago. So then it's even easier; one never has to bind anything.

I will try to ping you on Discord later tonight; there is a specific reason that I am preferring asynchronous messaging systems at the moment.

I mean it is quite possible that as "originally" originally understood in the late 1970s, the model did not have subscribers, but it was a part of the system as early as Smalltalk-80.

For some references you could find e.g. http://wiki.c2.com/?ModelViewControllerHistory

The dependency (addDependent:, removeDependent:, etc.) and change broadcast mechanisms (self changed and variations) made their first appearance in support of MVC (and in fact were rarely used outside of MVC). View classes were expected to register themselves as dependents of their models and respond to change messages, either by entirely redisplaying the model or perhaps by doing a more intelligent selective redisplay.

or (PDF Warning) http://www.math.sfedu.ru/smalltalk/gui/mvc.pdf :

Because only the model can track all changes to its state, the model must have some communication link to the view. To fill this need, a global mechanism in Object is provided to keep track of dependencies such as those between a model and its view. This mechanism uses an IdentityDictionary called DependentFields (a class variable of Object) which simply records all existing dependencies. The keys in this dictionary are all the objects that have registered dependencies; the value associated with each key is a list of the objects which depend upon the key. In addition to this general mechanism, the class Model provides a more efficient mechanism for managing dependents. When you create new classes that are intended to function as active models in an MVC triad, you should make them subclasses of Model. Models in this hierarchy retain their dependents in an instance variable (dependents) which holds either nil, a single dependent object, or an instance of DependentsCollection. Views rely on these dependence mechanisms to notify them of changes in the model. When a new view is given its model, it registers itself as a dependent of that model. When the view is released, it removes itself as a dependent.

Like, I'm not getting this out of nowhere; at one point I inspected the code in the Model object and that's how it works...

Hi! I would love to read your articles and discuss this further but right now your blog is not viewable by Chrome, Firefox, or Edge. Firefox gives the most descriptive error string as SSL_ERROR_RX_RECORD_TOO_LONG.

Multiplexing two models together to my mind just constructs a new model whose values are tuples of the existing models and which subscribes to both of those models in order to notify its own subscribers whenever either side of those tuples change. If you do this, you can have a bunch of local stores and still say "this component's value changes whenever either of those values change." The key is that "normal" models accept a set(value) message to set their value to something, and you might play around with "dict" models which accept insert(key, value), deleteAt(key) messages, but a multiplex model would not be easily able to abstract over all the different possible messages to send upstream and so the easiest approach is just to make multiplexes nonresponsive -- you can't "dispatch" to them, in Redux terms.

redux-thunk is nice in that it helps keep people from making the mistake of sending otherwise-no-op actions to the store which then, inside a reducer as side-effects, do a bunch of async I/O to compute events that eventually make it back to the store. I would broadly agree with that.

My basic beef with redux-thunk is that it's unnecessary and complicates what would otherwise be a type signature that has no reference to I/O, which I regard as a good thing. Developers ought to know that, to quote one of the Austin Powers movies, "you had the mojo all along." It's a sort of talisman that you are using for purely psychological reasons to reassure developers and to coax them to doing updates outside of the reducers, but it's OK because "it's in `dispatch()` so it must be a Redux thing so we'll make it work." But such a talisman is unnecessary.

Like, here's what you've got (in the readme):

    function makeASandwichWithSecretSauce(forPerson) {
      return function (dispatch) {
        return fetchSecretSauce().then(
          sauce => dispatch(makeASandwich(forPerson, sauce)),
          error => dispatch(apologize('The Sandwich Shop', forPerson, error))
        );
      };
    }
    store.dispatch(
      makeASandwichWithSecretSauce('Me')
    );
Here it is with simpler type signatures:
    function makeASandwichWithSecretSauce(forPerson, dispatch) {
      return fetchSecretSauce().then(
        sauce => dispatch(makeASandwich(forPerson, sauce)),
        error => dispatch(apologize('The Sandwich Shop', forPerson, error))
      );
    }
    makeASandwichWithSecretSauce('Me', msg => store.dispatch(msg));
The indirection here wouldn't even be necessary if Redux core just preventatively declared when creating a store that
    store.dispatch = Store.prototype.dispatch.bind(store);
    store.getState = Store.prototype.getState.bind(store);
which I mean maybe you do; I don't know.

The absolute most important thing to understand about models as they were originally intended, is that they are not descriptions of a data model per se.

This is not to say that data modeling is not important, or that your model won’t have a similar shape as your data model; it will. But that is not the original point.

In MVC as it was originally understood, a model is a list of subscribers. You can add yourself to that list, you can remove yourself from that list, and whenever a “value” changes, if you are on that list, you get a notification that the value has changed. You have a couple of different designs of these, depending on whether you want to send a current-state message as a notification on subscription, or just give everybody read access to the current state. The latter commits you to initializing your models in ways that indicate the absence or staleness of data (someone loads your app, you need to send out a network request to get a new thing) but also allows you to use variable scope to augment how much multiplexing and state tracking you need.

Models vary from data models in having view-relevant data. So for example you switch from the type

    const urlList = new Model<UrlRow[]>([])
to the type
    type Fetching<x> = { state: "init" }
      | { state: "loaded", data: x },
      | { state: "fetching", staleData: x },
      | { state: "fetch error", staleData: null | x }
    const urlList = new Model<Fetching<UrlRow[]>>({
      state: "init"
    })
Notice that these Fetching indicator statuses are a part of the data model for the UI, not the underlying data model that exists at the database level.

If this begins to feel a lot like React and Redux, that is because there is a shared lineage there. React originally made its splash as “the V in MVC” but its setState/state system, while it doesn't contain a subscriber list, effectively does something equivalent by insisting on destroying anything that has the old values and then superficially identifying things which appeared to remain the same from moment to moment, with the basic model then being a “subscription tree.”

Redux of course takes this from being a tree to being something more generic by making the store global... I think that models should not be app-global the way that Redux likes (it does not want to solve the problem of multiplexing models, which is understandable but it turns out to be a much simpler problem than you'd think) and that the pattern of reducers is more verbose than one generally needs, but I love the time travel browser features that Redux gives me. Somehow Redux has encouraged abominations like redux-thunk which complect separate concerns into the same dispatch function unnecessarily. But the fundamental workings involve that same basic structure: a subscriber list.

Maybe somewhat. I think you can offer a simple explanation, but it depends a little on how you have already set up the problem.

Here's the problem setup: So we want to share a secret byte (178) among Alice, Bob, and Carol, so that we need all 3 of them to contribute to it. Three points defines a parabola so we choose two more random bytes: [38, 68], our polynomial is y = 178 + 38x + 68x². We then give Alice the point (1, 284), Bob the point (2, 526), and Carol the point (3, 904).

Now supposing that we have compromised both Bob and Carol's points we know that we have the two equations,

   9a + 3b + c = 904
   4a + 2b + c = 526
We can then eliminate b to get:
   6a - c = 230
which we can rearrange as
   c = 6a - 230.
Since `a` cannot be a fraction, we must be able to cut down the number of possibilities for c to just 42 possibilities, {4, 10, 16, 22, 28, ...}, since they must be separated by sixes. I'm not 100% sure but I think this factor grows like n!/(n-k)! for "I have compromised k of n secrets, by what factor have I reduced the search space?"

Here's how modular arithmetic solves this: It turns out that modulo a prime, all fractions are also whole numbers. That is, if I am working modulo the prime 13, I will find that I can divide 7/5 to find 4. Remember what division means, it inverts multiplication: I can find that 5 × 4 = 20 and then that 20 = 13 + 7, so they are at the same place "on the clock". In fact it suffices to just find 1/5 and multiply by 7, so you can find that 1/5 is 8 in the mod-13 ring, 8 × 5 = 40 = 39 + 1. You can also find that 1/6 is 11, so 6 × 11 = 66 = 65 + 1.

The proof that this must be the case is that if you take

    [1, 2, ..., p-1].map(x => (x * n) % p)
this list cannot repeat itself: if it did, the resulting `x1 - x2` would divide `p`, by the distributive law of multiplication. It also is confined to only contain the numbers 1 through p-1, and so it must contain all of them exactly once: so if it doesn't repeat itself, it has to have a 1 in there somewhere.

That's kind of a brute force argument so you may want to also mention that there are two efficient ways to find these, one is called the "Extended Euclidean algorithm" (do a GCD computation to find that the GCD=1, but you can take the dividends that you discarded and cleverly assemble them to recover the constants from Bezout's identity, which in this case gives you the modular inverse) and the other is called "Fermat's little theorem" (since a^(p-1) % p == 1 for prime p, raise something to the p-2 power. Using exponentiation by squaring you only need ~log p multiplications that each take no more than ~log p time.

It's possible but unlikely.

MPL, for folks who aren't aware, is a successor to the CDDL seen in Solaris etc. and is a per-file copyleft, thus having a nicer legal structure while getting the same rough benefits of GPL or at least LGPL. The idea is “any modifications to this file must also be open-sourced under MPL, but you can package this file with proprietary other files that are not MPL and integrate them into a larger proprietary thing as long as your modifications to this file alone are open-sourced.” The goal is to protect weakly from Microsoft-esque “embrace, extend, extinguish” as GPL does but enable commercial integration the way BSD does.

In practice nobody seems to be all that pissed at Mozilla because of their license; the MPLv2 added GPL compatibility so the GPLers are mostly able to use MPL software and it gives a nod towards the stronger copyleft they like; commercial applications which just use the software as a library don't mind.

Right. The important thing about the Clay Mathematics Millenium Prize is that it is a set of well-chosen SMART-ish goals. They want to incentivize work on really hard fields of mathematics but they have tried to do this by choosing results that are each not too intimidating. The Navier-Stokes prize, for example, allows you to assume all of the nicest features of Navier-Stokes problems in practice -- basically all of the fluid flows are well below supersonic and are occurring in highly homogeneous, nice fluids -- and ask the most basic mathematical question: does a smooth solution to these equations always exist? That question by itself is not so important, but it's specific and measurable. But it's a bit of a "reach" -- you would have to have some cutting insight about turbulence in order to answer this question one way or the other. That cutting insight is what they're trying to incentivize.

P vs NP is the same: if solutions to a problem are easy to check, is there always some better way to analyze the mechanics of the checker to make those solutions easy to find, so that we aren't stuck with brute-forcing it? Whether the answer goes one way or the other, the point is that solving the problem would have to provide some insight to the effect of "here is a periodic table of elements for all of the 'easy' algorithms -- and here are the properties of all the 'molecules' made by combining those building blocks." And only once someone advances our understanding with those cutting insights can we say "yes we can always reach into the verification mechanism to understand it well enough to build a better-than-brute-force algorithm" or "no, here is such a thing that algorithms cannot do, it's not just that I am not smart enough to find a way for them to do this -- they are fundamentally incapable of doing it faster."

I mean the biggest thing was Kuhn coming along and saying "experimentally, it doesn't work that way."

What I mean is, people don't find an experiment about nanostructures that doesn't work and start going "hey I think I have disproved quantum mechanics!". Even when the OPERA faster-than-light neutrino debacle was going on, physicists were largely saying "We are pretty sure that there is some mistake in either the model or the experiment such that these neutrinos are not moving faster than the speed of light." In fact the objection goes a little further than that: according to Newtonian mechanics, geocentrism is perfectly admissible. There is absolutely nothing wrong with constructing a geocentric frame of reference and doing Fourier expansions of the motions of planetary bodies. No experiment has disproven it because it's just a mathematical choice of accelerated reference frame to analyze the motion of the planets. According to unmodified Popper, each of the first two should have led to a rejection of the scientific principles which led to them, while the latter would mean that geocentrism and heliocentrism are pseudoscience and there was never any scientific switch between them -- all of that sounds wrong.

So Kuhn introduced the idea that there is a separation of science into two parts, "theory" and "model". A scientific theory like quantum mechanics or heliocentrism is a platform for building models and deciding what questions are worth asking and how one goes about asking them. They are a "platform for computation" in a sense, and most of them are "Turing complete," there is nothing that they can't model somehow. So classical mechanics turns out to be able to do something with quantum mechanics if we use something like Bohm's pilot wave theory. And Couder and Fort's droplets on a vibrating oil bath show an experimental realization of particles which nevertheless diffract in a classically explicable way, underscoring this point. Kuhn said that theories need to be abandoned during some sort of "scientific revolution" but was very hazy on how exactly that happened. But he was a huge fan of Popper and wanted to say that Popper was fundamentally right about the way that we model systems, discarding models immediately when they do not fit experiment and coming up with better models.

Kuhn picked up a lot of flak because one of the things Popper's works were trying to do was to discredit things like psychiatry and astrology as being "pseudoscience" rather than real science because they could explain everything and thus never stuck their neck out -- thus Kuhn's work seemed to need some extra structure about the manner that we actually conduct such a revolution, otherwise astrology might not be a pseudoscience but an "eventual science" or so: if theories are just some sort of aesthetic agreement on behalf of the existing scientists then what stops us all from deciding that we rather like reading our weekly horoscopes?

This challenge was to my mind best resolved by the "research programmes" idea of Imre Lakatos. He philosophizes that theory choice -- fundamental progress in science -- is best seen as motivated by lazy grad students. Like, laziness is a virtue on this account: grad students have to make a contribution to the published literature that excites their peers and makes a name for themselves, and they do not have much time to do it.

So, why do people use the Copenhagen interpretation for everything if very few people philosophically accept its ontology? Because it is mathematically equivalent to all of the other interpretations but is astonishingly easy to use, just "yeah the wavefunction collapsed so now this is reality, I don't strictly have to care about that collapse happening across spacetime instantaneously because that's not observable anyways, so here are my experimental results." Lazy grad students will choose that ten times out of ten over coming up with the correct pilot-wave mechanics and simulating it. Why did heliocentrism win if Newtonian mechanics says that geocentrism is 100% experimentally valid? Because the heliocentric models are easier to build and reason about with straight mechanics, and lazy grad students will take Newton's law of gravity any day over those epicycles.

You can in some respects view this as Occam's razor but Occam's razor is painfully ill-specified. A better view of it is that it's a survival-of-the-fittest, a theory of scientific evolution. So, theories are "genes" which make it easier or harder to publish interesting discoveries that are modeled with those theories in scientific journals. Based on others reading those papers and extending those results in various ways, theories "reproduce" and the ones that reproduce most effectively are the ones that best adapt to their (ever-changing) environment.

No, when they talk about watts per kilogram I am pretty sure that they mean these were absorbed. Like they literally built 21 big microwaves, 7 for mice and 14 for rats, and then turned them on: it's no different than your microwave at home, the waves bounce around the walls until they find some water to call home. They're presumably not concerned with any microwaves that escaped the resonator.

I don't think TypeScript has a native GUID type, but if I am wrong about that please tell me as it will make my code more type-safe.

The `string` type here comes from a mapping that the router is using. That is, the router ultimately type-evaluates a `ValueOfType<{type: 'guid'}>` to `string`. But because it's a runtime object, the router can also, at runtime, validate that URL param, "did they actually give me a UUID?" -- and sanitize it, e.g. "convert all UUIDs to lowercase."

(In fact the benefit of having this TypeScript type at runtime is even bigger than that. With Express.js, the router can rewrite the route param so that the route doesn't even match if you don't provide a UUID, which matters because there is often a lot of accidental ambiguity in HTTP APIs -- but here you can embed the UUID regex into Express paths. The router can then also do some other trickery like confirm at initial load time that all params in URLs match params in this `params` dict, and it can convert all of its routes to OpenAPI/Swagger docs so that you can define another route which just gives you your OpenAPI JSON. Literally in what I have written the above would be a type error because the `Router` class would complain that `params` has the wrong type because the `objectguid` descriptor needs a key called `doc` which is a string for parameter documentation for OpenAPI.)

I've been well. Landed a software job with a company called IntegriShield doing a sort of internet rent-a-cop work, now am writing apps for a mechanical contractor called US Engineering -- turns out the construction business always runs on razor-thin margins which is kinda nice because, like, reducing cost by 1% when construction margins are only ~5% causes a 20% improvement in net profit.

This is great work, and I think you're burying one lede, which is that it looks like you've embedded a declarative permissions model in this thing, and I built one of those and the time saved can be huge when authorization is handled at the model level rather than everywhere in the business logic.

Hey Koen, congrats on you and Corno making front-page on HN!

I can definitely confirm for others reading this that it indeed has been something like 10 years in the making; I was working with a prototype of it 8-9 years ago and found those data models so nice that I actually reimplemented the core idea in a repository on GitHub, though it didn't really go anywhere except for my own web site. I have also been able to reimplement it in TypeScript more recently, so that there is a non-Turing-complete subset of algebraic data types (though maybe I'll be able to add a fixpoint operator, who knows) as runtime objects with highly specific TypeScript types that are inferred from the functions you use to construct them. So then a parametric TypeScript construct,

    ValueOfType<typeof mySchema> 
embraces values that match the schema that you just specified. You can use this trick to write functions like
    myHTTPRouter.get('/objects/by-id/:objectguid', {
      params: {
        objectguid: {
          type: 'guid'
        }
      },
      async handler(params) {
        // inside of here, params has type {objectguid: string},
        // and VSCode knows this, because params is ValueOfType<schema> where
        // the schema is specified in the `params` key above.
        return response.json({success: true})
      }
    })
It's a really fun perspective on programming to have these schemas available at both runtime and compile-time, very DRY.

Right, I wouldn't dispute that. If I wanted to rewrite the 15k lines of code in this application (which is what, 500 pages printed? two books?) I would probably use react+redux and could maybe even eliminate half of the code when I was rewriting it.

The problem is that that still comes out to ~250 printed pages, so one book, so that's an investment of 2 months to create no obvious business value, and I think if I could take that I would actually be part of that 1%. But the point of my post was just to give an example of "we can make smaller architectural decisions all the time to clean out crap and make our lives easier," and nobody is going to look the ~2 hours you spend cleaning as wasted time since it causes them to get a more-correct product sooner.

Another example: I remember at IntegriShield we had an API written in PHP, and one of my favorite little things I had written was a data model. ORMs are not hard to find in PHP but because the data model we were using was JSON we could express inside of that data model a declarative security model for the data and it would get written into the SQL queries: you say "Give me all of the groups!" and it rewrites that to, "I will give you all of the groups that you can see." The logic for the group-editor does not need to explicitly handle the checks for "can this person really edit that group?" because the data model will check it for them, "UPDATE groups SET values WHERE id = (the group you are editing) AND (user can edit the group)."

Adding the first security type was maybe half a day's work threading stuff through the SQL generator? Adding subsequent new checks took more time but was incremental so each of them might have delayed their projects 1-2 hours. But the net result must have saved a tremendous amount of programming. I have always had that latitude to create structure, if I want it.

That said, I have been pretty lucky with the places I've been privileged to work, so maybe I'm already part of the 1% and this is not representative.

I am not sure if I am in the 1% or if you are wrong in a foundational sense of “you have the latitude if you'll use it.”

Like, in the past week I had to add a feature to a front end that is heavily based on jQuery and its ecosystem, so lots of variables that are module-local but otherwise global, and every modification to that globalish state needs to update all of it consistently. I introduced maybe 80 lines of code and comments to define a Model as an immutable value with a list of subscribers to notify when that value changes, a Set method to change the value and update the subscribers, methods to subscribe and unsubscribe easily, and another function which multiplexes a bunch of models into one model of the tuples of values.

The result plays nice with that jQuery globalish code but it's terser and more organized, “define the state, define how updates must covary in one place.” But I can also see that it is not quite structured enough: it lacks functional dependencies which would structure the state more, “you select a ClientCompany in this drop-down and that wants to update the ProductList because each ClientCompany owns its own ProductList,” not because there happens to be a subscriber which has that responsibility. Also means that there is a sort of eventual consistency in the UI which was always there but now I may have an approach to remove it.

So I think that I have a good deal of latitude to try new high-level structures for my code, but it's possible that I just happen to be in a lucky place where I have that freedom.

It's only a little bit off. To get the true hydrodynamic analog to a capacitor, connect the bars of two big pistons together so that volume accumulated in one comes at the expense of the other, then hit the bar with a spring so that its motion comes with some energy cost that can oppose a constant pressure.

The point is that this component alone ties flow to accumulation, whereas generally your other components (resistors=thin pipes, wires=thick pipes, batteries=Archimedes screws, inductors=turbines connected to flywheels) do not accumulate volumes of water inside of them. Flow needs to make sense even without accumulation due to flow-balance, just like force needs to make sense even in situations where velocity stays constant due to force-balance.

It's ok, if I didn't have a Master's in the field I would probably have similarly down voted you.

The problem is mainly that the criticism you are making is not great for pedagogy. What is being called “charge” is probably something like “disposition to accumulate charge” or so, in the same way that force is not actually mass times acceleration, but it's mass times a disposition to accelerate, so that you can do things like measure my weight-force even though I’m not falling through the floor.

The dispositional truth of the matter is fundamentally more cognitively complex to teach than the simple rule that you get when you say that everything does what it's disposed to do, and so everybody has memorized the version of the definitions that has no dispositions, and gets very confused when you point out that aspect of those definitions.

They are not wrong. In the Maxwell equations both come in as fundamentally different terms.

The claim is that current density J is different from the time rate of change of charge density dρ/dt.

That is not to say they are unrelated; they are related by the continuity equation,

    dρ/dt = -∇·J.
The distinction is real, because what you are calling current in the one case is actually a spatial derivative of current, as indicated by the ∇.

I would actually go a step further than this and say that current is actually properly defined as the source of magnetic field. On the conventional definition of current, it is physically impossible for current to flow through a capacitor, but we speak of that all the time. So the True Current Density is just

    J + ε dE/dt
in SI units. Actually taking that seriously, however, does require to committing to language which sometimes seems a little awkward, like saying electromagnetic radiation involves an AC current oscillation that propagates through empty space transverse to its oscillation.
Absolute Hot 8 years ago

I mean it's not just one system, but the idea is what I just said.

The classical example is if you have a bunch of magnetic moments in a magnetic field and they do not interact with each other: then stuffing energy into the system requires aligning them against the magnetic field, and this makes the state more ordered. The problem is that these moments are generally in thermal contact with some apparatus that keeps them in place or vibrational degrees of freedom of their centers of mass or so. But you can get this thing to happen in magnetic resonance setups.

Negative temperature states pop up in a lot of strange places, the two that I know more closely are that lasing has this property of "as I dump more energy into the system I get more bosons in the lasing state" and Onsager in 1949 published a little article called “Statistical Hydrodynamics” which sort of went viral for the time, it points out that there is a way to view the instability of turbulent systems as due to negative temperature regimes of the vortices in those systems.

Absolute Hot 8 years ago

It's technically not 100% defined. See my comment below for more details about degrees of freedom and energy.

Suppose you have a system with 100 degrees of freedom and 2 units of energy, spread out as (0.01, 0.01, ..., 0.01, 1.01). A bunch of its energy is in one of those hundred degrees of freedom. You can assign it two different temperatures: the temperature 0.01, which would describe how energy will right now flow into the system if you connect it to another system with a bunch of degrees of freedom with their own thermal energy (assuming that the 1.01 degree of freedom is "internal" and doesn't interact directly with the outside world), and the temperature 0.02, which would describe how energy will eventually be spread out and hence how it would eventually share freedom with the outside world.

Temperature is ultimately defined in terms of how our uncertainty about the microscopic state a system is in changes as we add energy to that system. The higher this rate of change of uncertainty, the lower the temperature is -- this is why when you connect two systems of different temperatures, in the process of us becoming more uncertain about the fundamental state of the world, energy "spontaneously" flows from the higher temperature to the lower temperature: the certainty gained from stealing energy from the higher-T one is more than compensated by uncertainty created from pouring that same energy into the lower-T one. (In fact there is a family of systems of "negative temperature" which become less uncertain as you add more energy to them: they are "hotter than the hottest possible temperature" because they will gladly give their energy to any "normal" system in the process of us becoming more uncertain about the world.)

The problem is that if we're certain that some degree of freedom has a given amount of energy that's "special", we have a bunch of different definitions of "temperature" depending on how "adding energy to the system" distributes between the "special" degree of freedom and the "thermal" degrees of freedom.

So the usual process is to just totally separate those degrees of freedom as separate systems, the "thermal" ones have a temperature, the "special" ones do not.

Absolute Hot 8 years ago

It's not just an analogy, and it contains the essence of the story, but it's also not the whole story.

In physics we talk about the "degrees of freedom" of a system -- this is just the count of all of the independent ways that it can move. For each degree of freedom of a system you can calculate the average energy in that degree of freedom. By the equipartition theorem, at thermal equilibrium, all the degrees of freedom will have the same average energy, which will be T (if you measure temperature in units of energy).

So if you think about dropping a bouncy ball in a tube and it bounces until it slowly comes to rest, it has these degrees of freedom -- the internal degrees of freedom of the atoms of the ball, the internal degrees of freedom of the atoms of the floor/tube -- and then two really obvious degrees of freedom, the center-of-mass position of the ball, which gains an energy scale due to the gravitational force, and the center-of-mass momentum of the ball, which trades energy with this position degree-of-freedom.

Statistical mechanics says that as this system progresses, the location of the energy will slowly become more uncertain until it is on-average-evenly distributed across all of the degrees of freedom. That's why it bounces lower and lower: there is so much energy in the two "main" degrees of freedom -- maybe half a joule? -- whereas in the vibrations there is something closer to 10^-21 J of energy at room temperature.

But the flip side of dissipation is always fluctuation -- this is in fact the subject of a major theorem! So the fact that this can randomly lose energy to these other degrees of freedom means that those degrees of freedom are also randomly kicking the ball. As you can imagine with ~20 orders of magnitude difference between the two, they don't kick this ball by all that much. But you have a lot of experience with a lot more tiny balls that are bouncing off the ground all the time. Take a deep breath. There they are.

If everything were to come to its minimum energy configuration, why are these air molecules so stubbornly not falling to the floor? Well, they are trying to! But they are so light that they are being kicked back upwards by these random thermal kicks, so high that they can in principle go the many kilometers to the uppermost atmosphere.

(Of course if they could go all that way in a single kick then air would have to be so non-interactive that we could not use it to talk to each other... the mean free path in air is actually about 68 nm, so in practice every air atom is getting its random thermal kicks from other nearby air atoms. But the ultimate origin of these random thermal kicks is the random kicks of the floor on the few hundred nanometers of air sitting above it, and that energy comes from the Sun and is mostly conserved as these atoms collide with each other -- but a tiny bit is often converted to little photons of infrared light that sometimes escape the atmosphere.)

With that said as others have noticed, the free-particle energy relation in special relativity is E = γ m c². Famously, at rest, this factor γ = 1/√(1 − (v/c)²) is 1 and the energy of a particle at rest is E = m c². But as v gets closer and closer to c, v → c, this energy grows without boundary, E → ∞. So there is no finite temperature where a kinetic degree of freedom would exceed the speed of light. Indeed you can solve for v, as 1/γ² = 1 − (v/c)². So the velocity corresponding to any given total energy is v = c √(1 − (mc²/E)²). For a rest particle with E = mc² this is v = 0 as you would expect; or when the kinetic energy first gets to mc² we would have E = 2mc² and thus v = c √(3/4) = 0.866 c.

Potato paradox 8 years ago

One faces a similar problem with thinking about how much time is saved to go a certain distance: velocity is measured in meters per second, not "slowness" in seconds per meter.

Thus speeding by 10 miles per hour makes much more difference in your time if it happens at 20mph (3 minutes per mile -> 2 minutes per mile) than if it happens at 60mph (1 minute per mile -> 0.86 minutes per mile).

This can sometimes be erased because one typically (at least in the US) spends more time at the highway speed, but if we're talking about you need to spend 10 minutes getting on the highway, 30 minutes driving on it, and 10 minutes getting off it, then even allowing for 5 minutes of the city driving to be non-speedable (it's spent stuck at three traffic lights, say), you can save 5 minutes of time by speeding 10mph on the only 5 miles of city streets, but only 4 minutes of time by speeding 10 mph on the 30 miles of highway. You're speeding the same amount for 6 times the distance and something over twice the time, but because your average speed was higher it simply doesn't buy you as much.

Working out the numbers also helps you realize that speeding on the highway to get a substantial amount of time is, while not pointless, more unsafe than you think. Even under great circumstances, like if you are facing 40 minutes of driving -- if we're talking about a 70mph highway and you are 15 minutes late while you think 5 minutes late is still socially acceptable, you need to cut 10 minutes and thus average 4/3 * 70mph = 93.3 mph to make that happen. That means that to handle the moments where you are stuck behind two cars both going 10 over the limit at 80mph, you will need to at times be going 30 over the limit. And that's with a relatively long commute! If it's a 20 minute commute you have to drive this recklessly just to shave 5 minutes.

No, there isn't.

Words change meaning because your present-eyes are different from past-eyes.

The gun symbol has changed meaning because your present client is different from past clients.

What kind of writing system allows people to change your words after you've written them?

File this away under "myths programmers believe about language," with some bullet points like,

- A word or symbol will always have one meaning.

- Okay, but at least those meanings will stay the same over the next decade.

- The next year?!