HN user

deredede

507 karma
Posts0
Comments212
View on HN
No posts found.
Leaving Mozilla 1 month ago

I don't have that reading at all. The phrasing even seems (carefully?) chosen to avoid this interpretation: it's "Examples are many of the administrators [...]", not "Examples are the administrators [...]".

We mourn our craft 6 months ago

I know how to review code without looking at the corresponding assembly and have high confidence in the behavior of the final binary. I can't quite say the same for a prompt without looking at the generated code, even with temperature 0. The difference is explainability, not determinism.

I also do this.

Random flags added to core tools are done with aliases, which do not affect the launched processes, not by shadowing them in ~/bin. Shadowing in ~/bin are for cases where a newer (compared to the system-wide version) or custom version of a tool is needed.

I like it. IIFEs always make me nervous because they look like they beg to be removed if you don't know why they are used. Using an explicit function such as `run` looks much more intentional, and provide a single intuitive place (the documentation of the `run` function) to explain the pattern.

Not GP but bump allocation (OCaml's GC uses a bump allocator into the young heap) mitigates this somewhat, list nodes tend to be allocated near each other. It is worse than the guaranteed contiguous access patterns of a vector, but it's not completely scattered either.

I can think of plenty situations where you really want to use the dependency's types though. For instance the dependency provides some sort of data structure and you have one library that produces said data structure and a separate library that consumes it.

What you're describing with SML functors is essentially dependency injection I think; it's a good thing to have in the toolbox but not a universal solution either. (I do like functors for dependency injection, much more than the inscrutable goo it tends to be in OOP languages anyways)

Alternative answer: both versions will be picked up.

It's not always the correct solution, but sometimes it is. If I have a dependency that uses libUtil 2.0 and another that uses libUtil 3.0 but neither exposes types from libUtil externally, or I don't use functions that expose libUtil types, I shouldn't have to care about the conflict.

It's not "all the transitive dependencies". It's only the transitive dependencies you need to explicitly specify a version for because the one that was specified by your direct dependency is not appropriate for X reason.

What if libinsecure 0.2.1 is the version that introduces the vulnerability, do you still want your application to pick up the update?

I think the better model is that your package manager let you do exactly what you want -- override libuseful's dependency on libinsecure when building your app.

The article starts with this description of 2FA:

an electronic authentication method in which a user is granted access to a website or application only after successfully presenting two or more distinct types of evidence (or factors) to an authentication mechanism.

and concludes with (emphasis mine):

For the average user, the smartphone has become a single point of failure, where the theft of one device and one piece of knowledge (the passcode) can lead to total financial compromise.

Looks like 2FA to me, not 1FA.

If people need "`expect` scripting and a few open source packages [to] automate it to be 1 factor", it is effectively 2 factor for 99.9% of the population.

Also, if someone uses a password manager to store both the password and the OTP credential, that is still an improvement to security. Intercepting (e.g. shoulder surfing) or guessing the password is no longer enough, an attacker needs to get into the password manager's vault.

It's not actually how code reviews are done by the people who wrote it.

What do you mean by that? Even if you do review by emailing patchsets those are still managed locally using branches, to my knowledge.

This is excruciating in git if you ever need to make a fix to an earlier PR because you have to manually rebase every subsequent change.

Spreading the word about `git rebase --update-refs` that will automatically update any branches that point to commits along the path (very useful with stacked branches). It is less convenient than what jujutsu offers (you need to know the branches to update, where jujutsu automatically updates any dependency), but still a very useful if you don't want to or can't switch to another tool.

"Parse, don't validate" is a catchy way of saying "Instead of mixing data validation and data processing, ensure clean separation by first parsing 'input data' into 'valid data', and then only process 'valid data'".

It doesn't mean you should completely eliminate `if` statements and error checking.

You need an email_or_error and a name_or_error, etc.

You don't need that. A practical solution is a generic `error` type that you return (with a special value for "no error") and `name` or `email` output arguments that only get set if there's no error.

E.g., requiring that a file have the correct MIME type, not be too large, and contain no EXIF metadata.

"Parse, don't validate" doesn't mean that you must encode everything in the type system -- in fact I'd argue you should usually only create new types for data (or pieces of data) that make sense for your business logic.

Here the type your business logic cares about is maybe "file valid for upload", and it is perfectly fine to have a function that takes a file, perform a bunch of checks on it, and returns a "file valid for upload" new type if it passes the checks.

The problem with convention is that no ten people do it the same way

"Stuff that starts with one underscore is an internal implementation detail, use at your own risk" in Python is as close to a universal convention as you can get.

At least TypeOK can be much more expressive than any type system.

Can you clarify what you mean by that? Dependent types or more practically refinement types (à la F*) can embed arbitrary predicates.

"Moving preconditions up" means moving the code that checks the precondition up. The precondition still needs to be documented (in the type system is ideal, with an assertion otherwise, in a comment if necessary) close to where it's assumed.

that is not used anywhere in daily life

Does it matter? MM-DD-YYYY is used in America and makes DD-MM-YYYY ambiguous, but as far as I know nobody uses YYYY-DD-MM, so ISO8601 should be perfectly fine, especially if users are trained. Besides, if you're not used to it, starting with the year forces you to think, which is desirable if you want to avoid human error.

Modular implicits have been shelved indefinitely from what I understand, if that's what you're referring to.

They have not — people are still working on it. There's been a paper at the OCaml Workshop at ICFP this year, and a PR on the OCaml repo. The student who worked on this is now starting a PhD on modular implicits in the lab that created OCaml.