HNHacker News
TopNewBestAskShowJobs

zenhack

684 karma · joined June 20, 2017

[ my public key: https://keybase.io/isd; my proof: https://keybase.io/isd/sigs/sp25K1JliIwzg06OIG9xoMjX6G7YxK3taKIPr-hp2MI ]
submissionscomments
zenhack··on The myth of “joins don't scale”
I question the sensibility of having the primary interface to a database be a query language as such; It's a pain to work with programmatically. I agree with the notion of starting from relational algebra, but rather than the interface being a human-oriented textual syntax, the protocol should be defined in terms of some widely supported serialization format (take your pick). This makes it easier to write query-builder libraries, which the humans can use. You really don't want to be doing string substitution to put queries together.
zenhack··on The myth of “joins don't scale”
> they'd launch maybe a couple years later

If at all; probably obvious, but important to point out that in a startup environment this kind of mistake could just outright kill the company.

I work on an open source project (Sandstorm[1]) that was started by a now-defunct startup. There's a repo that's unmaintained at this point (It might still work?) containing a high-scalability backend that had been used to manage Sandstorm Inc's hosted offering. Apparently they never got to the scale where they couldn't have thrown one giant server at it and been fine, and it pulled a lot of resources away from other (ultimately more important) development tasks.

...and now I'm stuck developing against mongo for no good reason :P

[1]: https://sandstorm.io

zenhack··on The stable marriage problem and modern dating
Yeah, I'm willing to let this slide coming from regular folk in everyday conversations, but when you're writing a blog post about algorithms and you just said it was O(n^2)... this is a situation where I think it's reasonable to expect someone to hold to the technical meaning of a term.
zenhack··on Brython – A Python 3 implementation for client-side web programming
As someone who's done a lot of python and a fair bit of JavaScript, I'll agree with the preference for the python ecosystem. I guess my perception of the difference is a quantity vs quality thing. My experience has been that python packages tend to be more stable, better documented, and frankly more reasonable in scope. There's less framework churn (Django has been around for what feels like forever, as have lighter solutions like Flask) and libraries tend to include enough functionality to seem with adding a dependency for; the number of transitive dependencies on a typical JS project is alarming. Also much less of the ecosystem feels like it's just trying to make up for an absent standard library. You don't see stuff like underscore in python land.

Both languages suffer from patchwork build infrastructure; interpreted languages are great when you have one file and no dependencies, but as soon as you grow a bit beyond that rules about where to find modules make things complicated. Both languages have developed tooling around this that suffers from being an afterthought, and I'm not sure which is worse.

zenhack··on Dynamic linking
> an AUR helper to make that transparent is standard kit for anyone using the box as a workstation

Fwiw, I've been using arch as my daily driver continuously for 14 years and haven't ever really felt the strong need for an AUR helper.

zenhack··on An even worse anti-encryption bill than EARN IT
> The plains states had to kick the natives out

...and the rest of the states...

zenhack··on I Just Hit $100k/year On GitHub Sponsors
I seem to be in the most expensive state in the country for that. That's rent & food for a month.

But it's a one-time fee, so you're probably still right in general, but for the moment I'm mostly coasting on savings & sponsorships, focusing on the stuff I care about while I have the breathing room. I might consider being a bit more organized if/when I ramp up business again and am considering looking for new clients.

zenhack··on I Just Hit $100k/year On GitHub Sponsors
Yeah, we have an active person in the Sandstorm community from Finland who maintains Wekan[1]. I didn't previously know the specifics, but he's had to tell a lot of people "sorry, I can't accept donations" too.

It's so much easier in the US. If you're an individual it's going to be taxable income, but there's no up-front paperwork to do (for that matter, you don't have to "set up" a sole proprietorship here either -- that's just what the tax code calls "some rando doing business by themself"). I've done contract work for years, have a bit of my income coming in through GitHub sponsors now.

Now, if we could only get health care covered for folks who don't have an employer...

---

> I host a free project myself and I've had to set up a business (sole proprietorship) and sell things in order to get money for server costs.

What's your side project? Speaking of Sandstorm, I'm wondering if it might be relevant; dealing with the problem of developers needing to monetize things in order to cover hosting costs was one of the motivations for the project:

https://sandstorm.io/news/2014-07-21-open-source-web-apps-re...

[1]: https://github.com/wekan/wekan/

zenhack··on I Just Hit $100k/year On GitHub Sponsors
It may depend on what country you're in, but in the US if you're just some rando, "donations" are still taxable income. The form GitHub sends you for filling purposes is the same one used for contractors.
zenhack··on Rust's Huge Compilation Units
Can you expand on that? What about the culture would make this problematic for Rust specficially?

It does seem like Rust is just enforcing the rough consensus in the Haskell community re: best practices.

zenhack··on How is NSA breaking so much crypto? (2015)
It's not an either/or; we should be doing both.
zenhack··on State of Linux Desktop Security
I'm dubious of some of these -- the code signing thing strikes me as not that compelling for reasons other comments have already pointed out. Others are very valid.

But more than "how are we doing vs Apple and Microsoft?" I'd kinda prefer to set the bar a bit higher. Desktop operating systems (all of them, at least with actual users) are just completely architecturally backwards for the reality of our modern security landscape, and what users need from their system. Protection boundaries are still mostly between different users. for most systems that's borderline useless, as there's only one user. Meanwhile every app runs with the full authority of the user and can do anything they can do.

Smartphones are a little better; Android equates "user" with "app" which is at least vaguely useful. But the permissions you end up with are still too coarse grained.

There are better designs out there. For example: web pages can ask the user for a file without getting access to everything the user owns (or at least in the case of Android, all of their files). Why can't native apps do this?

zenhack··on The Next Step for Generics
Fair enough; I suppose I was oversimplifying. I think the broader point I was trying to make (in addition to the specific downsides I mentioned) still holds though.

The Template Haskell paper has some interesting things to say on the nature of C++ templates:

https://www.microsoft.com/en-us/research/wp-content/uploads/...

zenhack··on The Next Step for Generics
I'm sympathetic to being somewhat impatient; I'd really like to have generics in Go years ago too. But I'm also glad they didn't just plow ahead with the first draft of the proposal that came out; the way contracts worked was horrible, and the slow deliberative process means that we don't actually have to deal with those mistakes. Unfortunately, good design takes time.
zenhack··on The Next Step for Generics
Macros are not a substitute for parametric polymorphism ("generics"). With lisp-style macros you could easily implement something like C++ templates, but that's different in at least one critical way: with C++ templates, the templates are expanded before typechecking, whereas with proper generics, typechecking happens while the type parameters are still opaque. The former has several disadvantages:

- It gets you really garbage error messages, because the type errors are usually about something in the body of the template, wherever it tries to do something that the type you substituted doesn't support, rather at the offending call site.

- It hurts compile times (above and beyond proper generics), since you need to type check the generic function at every call site, rather than just once.

- It makes it easy to break interfaces, because exactly what is required of a type parameter isn't written down anywhere -- it's just whatever the body tries to do with it.

(Though it is also true that generics are certainly not a full substitute for macros. I would welcome some mechanism for doing codegen that didn't complicate the build system and was a bit lighter weight than what we have now).

zenhack··on Generics and Compile-Time in Rust
It is certainly possible to still monorphize some cases, but the point is it can't work as a comprehensive strategy like it does in rust; it's an optimization that applies in some cases.
zenhack··on Generics and Compile-Time in Rust
The comment I originally replied to linked to a blog post arguing that in Haskell, the practice of wrapping type classes (which Rust calls traits) in an existential is an antipattern, because rather than using fancy type system features, you could just use a record with some functions in it, which is simpler and more direct.

But dyn impl is a trait wrapped in an existential. There's no concrete type a -> b, only a trait for types that can be 'called.' So to pass an arbitrary function around in a record/struct you need to do the very thing the post is saying is an antipattern (in Haskell). So the argument doesn't really apply to Rust because there isn't a simpler more direct way to achieve the same thing.

zenhack··on Generics and Compile-Time in Rust
I was mostly talking about the type level; I certainly didn't mean to imply that Rust didn't have lambdas if that's what you're getting at. But there is no general type of Rust lambdas that take an A and return a B other than the trait object type `dyn impl Fn(A) -> B` (Or FnMut or FnOnce); the concrete type will depend on what variables it captures.

Also, there's a lot of disagreement about exactly what the distinctions between `lambda`, `closure`, `anonymous function` and friends mean. The interpretation of `closure` I'm interested in is basically a bundle of code and data, which can be treated abstractly in a first class way. That could be something that appears as a lambda capturing variables in the text of your program or as an object in a more OO setting which, albeit more verbose for a single function, has a similar level of power of abstraction.

Either way, part of that power is being able to write code that can work with the interface (irrespective of the shape of the enclosed data), and do things like store differing implementations in lists/vecs etc. The only mechanism Rust provides to do that is trait objects.

zenhack··on Generics and Compile-Time in Rust
Also worth noting that Haskell's type system is too powerful for monomorphization to work as an implementation strategy for generics in all cases. In particular, polyorphic recursion[1] means that attempting to just monomorphize anything wouldn't necessarily terminate.

Higher rank types also break this, as you can define things like:

newtype GenericThing = GenericThing (forall a. [a] -> a)

doManyGenericThings :: [GenericThing] -> [a] -> [a]

doManyGenericThings things list = map (\GenericThing f -> f list) things

Here, `doManyGenericThings` takes a list of generic functions, and applies each of them to its argument. You can't just monomorphize it, because you'd have to somehow also monomorphize every argument it is ever passed, which is a dynamic property that you can't know in advance (and again, may not be a finite set).

[1]: https://en.wikipedia.org/wiki/Polymorphic_recursion

zenhack··on Generics and Compile-Time in Rust
The difference is that the author's suggestion as to what to do instead doesn't work in Rust. In Haskell there's no need to use a type class/trait here at all; you can just use a record. We could try to do the same thing in Rust with a struct:

struct EventHandler { handle_start_event: fn(), handle_completion_event: fn(), }

...but this differs in a key way from the haskell example: Rust's `fn` is not a closure, it's just a pointer to some code, and you can't construct them dynamically. If you want to pass around a _closure_, you need ...a trait object.

Something like:

struct EventHandler { handle_start_event: Box<dyn impl Fn()>, handle_start_event: Box<dyn impl Fn()>, }

...but that's exactly the pattern the author of that post is suggesting getting away from.

I agree with the author's point, but it doesn't really apply to Rust because there isn't actually a simpler way to do it. And I think that's part of what the OP was getting at -- Trait objects are the closest thing Rust has to proper closures, and they're a bit awkward.

Note that I'm still something of a newbie at Rust, and don't feel like I can really say much about the day to day experience of using (or avoiding) trait objects due to limited experience.

zenhack··on Looking Back at Postgres
I'm curious to the particulars (I have no opinion on the technical merits of Microsoft's offering as I've never tried it). What specifically does it do better?
zenhack··on Finally, I Closed My LinkedIn
Fwiw, I still get recruiter emails now and then years after having shut off my LinkedIn account. If they mention how they found me, it's usually through GitHub.

...not that I've ever had anything useful come from talking to a recruiter. The useful bits have always come through my existing personal network more directly, or through meatspace networking. I shut down my LinkedIn because I basically started to view recruiter emails as spam.

zenhack··on Police attacks against journalists across the U.S. since May 28
Freedom of the press is certainly important, and if anything changes because of all this, people hearing about it will be instrumental, but it's not a replacement for proper systems of accountability. If the bar for getting away with murder is "don't make national headlines," something is deeply wrong.

Up until now the bar has been far lower than that.

zenhack··on ECMAScript 4: The Missing Version
This needn't be the case; it depends on the details and what the particular format is designed for.

Wasm is a good example of a bytecode format designed for small code size. Though I expect wasm may often still be larger than equivalent js just because it's so much lower level. But there's no reason you couldn't design a compact bytecode format with high level semantics, and I would expect it to beat any human readable format.

zenhack··on Frameworkless Movement
Back when I was doing a lot of Python work I was a big fan of Flask. The reason is that it really just provided an integration layer for existing stand alone libraries; it didn't feel like I was buying in to some massive framework, just leaning on Flask to get rid of some of the boilerplate glue code that is otherwise need to write to e.g. find a jinja2 template, render data with it and then turn that into an http response. Just `return render_template(...)`. But if there wiring became inappropriate it's ultimately not doing that much, and it's easy enough to take that template and use it in a different context.
zenhack··on ECMAScript 4: The Missing Version
Ultimately though this end probably would have been better served by bytecode.
zenhack··on ECMAScript 4: The Missing Version
On this bit:

> Perhaps if ES4 landed, fewer people would need complex build tools like Babel, Webpack and Typescript.

I'd pose it the other way: if stuff like Babel existed at the time, folks might have actually written es4 because they could do so without breaking backwards compatibility. And most of the value in a static type system is the ability to flag errors before running the program, so I don't think there's anything you can add to the browser that would have obviated an offline tool for that.

Frankly, I think we'd be better off if we started getting a lot more selective about what gets added to browsers. Adding more and more features to browser's js implementations is silly when most folks are using ahead of time build steps to get access to those features without the browser's help. And continuing to add things is a great way to ensure that they'll keep right on using those tools, so they don't have to worry (as much) about who supports what. And it just makes the barrier of entry for building browsers higher and higher.

There's more utility when native browser support can do something a compiler can't. Things like reducing code size for really widely used functionality, enabling technologies that can't be bootsraped through developer tools (e.g. WebRTC). I'd like to see additional growth of the web platform be focused on areas that can't adequately be addressed by separate tools.

zenhack··on Two years in, GDPR defined by mixed signals, unbalanced enforcement
Relevant: https://idlewords.com/talks/haunted_by_data.htm

(Maybe you were familiar). The closing is particularly worth taking in:

> Finally, don't be surprised. The current model of total surveillance and permanent storage is not tenable.

> If we keep it up, we'll have our own version of Three Mile Island, some widely-publicized failure that galvanizes popular opinion against the technology.

> At that point people who are angry, mistrustful, and may not understand a thing about computers will regulate your industry into the ground. You'll be left like those poor saps who work in the nuclear plants, who have to fill out a form in triplicate anytime they want to sharpen a pencil.

> You don't want that. Even I don't want that.

> We can have that radiant future but it will require self-control, circumspection, and much more concern for safety that we've been willing to show.

> It's time for us all to take a deep breath and pull off those radium underpants.

I'm not sure it came in the form of a single event (though I can think of some candidates -- the cambridge analytica scandal made a big impression for one), but it's clear to me at this point that the warning was ignored, and our industry has missed the window for self-regulation.

zenhack··on SHA-1 collisions now cost $45k [pdf]
"for a while" suggests that this was ever a recommended choice, which is not the case. As others have pointed out, for password hashing you want a specialized algorithm, not a general purpose cryptographic hash function. This is true regardless of whether the hash function is "compromised;" it just wasn't designed for that application in the first place.

Algorithms designed for password hashing are intentionally both compute and memory intensive, to make guessing slower, whereas general cryptographic hash functions are by contrast intended to be fast, as most applications will want that. The idea is that password hashing algorithms should be fast enough to keep up with a human and no faster; if you already know he password the performance is not a hindrance but if you have to guess it makes doing so impractical.

zenhack··on Ask HN: What collaborative whiteboard are you using?
> What platform are you on?

Firefox on Linux.

← PreviousPage 2 of 8Next →