HN user

Dan42

148 karma
Posts3
Comments42
View on HN

Yeah, it doesn't work with keyword arguments. In the playground I tried a simple keyword with default value, and it converted to the wrong thing, as if "someone" was a valid type.

    def greet(name: "someone"): String
      "Hello, #{name}!"
    end
Ruby Blocks 9 months ago

This is really cute and heartwarming.

Back in the day, a lot of people including me reported feeling more comfortable in Ruby after one week than all their other languages with years of experience, as if Ruby just fits your mind like a glove naturally.

I'm glad new people are still having that "Ruby moment"

I see posts like this one pop up from time to time. I love it. Based on my 30y of exp that's also the workflow I converged on. It seems to me like every experienced and skilled developer is converging on this. jujutsu is entirely built to accommodate this workflow.

There are no silver bullets or magical solutions, but this is as close to one as I've ever seen. A true "best practice" distilled from the accumulated experience of our field, not from someone with something to sell.

Actually you're right, it is an implementation detail. The original isn’t mistaken, it’s just showing the lo-to-hi partitioning pass rather than the from-both-ends version I had in mind when I implemented quicksort before.

shame, shame, I should have double-checked before posting.

I'm pretty sure the swapping is a fundamental part of the quicksort algorithm, not a mere implementation detail. That's the reason quicksort is an in-place algorithm.

This is cool, but missing a LOT of details between steps 4 and 5, which is the meat of the quicksort. Actually, the first and last elements of step 4 would be swapped, which means the order depicted in step 5 is incorrect.

Look Out for Bugs 11 months ago

This article really resonated with me. I've been trying to teach this way of thinking to juniors, but with mixed results. They tend to just whack at their code until it stops crashing, while I can often spot logic errors in a minute of reading. I don't think it's that hard, just a different mindset.

There's a well-known quote: "Make the program so simple, there are obviously no errors. Or make it so complicated, there are no obvious errors." A large application may not be considered "simple" but we can minimize errors by making it a sequence of small bug-free commits, each one so simple that there are obviously no errors. I first learned this as "micro-commits", but others call it "stacked diffs" or similar.

I think that's a really crucial part of this "read the code carefully" idea: it works best if the code is made readable first. Small readable diffs. Small self-contained subsystems. Because obviously a million-line pile of spaghetti does not lend itself to "read carefully".

Type systems certainly help, but there is no silver bullet. In this context, I think of type systems a bit like AI: they can improve productivity, but they should not be used as a crutch to avoid reading, reasoning, and building a mental model of the code.

Don't we have decades of research about the improvements in productivity and correctness brought by static type checking?

Yes, we have decades of such research, and the aggregate result of all those studies is that no productivity gain can be significantly demonstrated for static over dynamic, and vice-versa.

Triptych Proposals 2 years ago

This is incorrect, according to this comment from the Firefox implementer who delayed the feature. He intended the roll back to be temporary. [0]

I see no such thing in the link you have there. #ref-6 starts with:

[6] On 01/12/2011, at 9:57 PM, Julian Reschke wrote: "One thing I forgot earlier, and which was the reason

But the link you have there [1] does not contain any such comment. Wrong link?

[1] https://lists.w3.org/Archives/Public/public-html-comments/20...

(will reply to other points as time allows, but I wanted to point out this first)

Triptych Proposals 2 years ago

No, please, just no.

The idea of using PUT, DELETE, or PATCH here is entirely misguided. Maybe it was a good idea, but history has gone in a different direction so now it's irrelevant. About 20 years ago, Firefox attempted to add PUT and DELETE support to the <form> element, only to roll it back. Why? Because the semantics of PUT and DELETE are not consistently implemented across all layers of the HTTP infrastructure—proxies, caches, and intermediary systems. This inconsistency led to unpredictable failures, varying by website, network, and the specific proxy or caching software in use.

The reality we live in, shaped by decades of organic evolution, is that only GET and POST are universally supported across all layers of internet infrastructure.

Take a cue from the WHATWG HTML5 approach: create your RFC based on what is already the de facto standard: GET is for reading, and POST is for writing. The entire internet infrastructure operates on these semantics, with little to no consideration for other HTTP verbs. Trying to push a theoretically "correct" standard ignores this reality and, as people jump into the hype train, will consume significant time and resources across the industry without delivering proportional value. It's going to be XHTML all over again, it's going to be IPv6 all over again.

Please let's just use what already works. GET for reading, POST for writing. That’s all we need to define transport behavior. Any further differentiation—like what kind of read or write—is application-specific and should be decided by the endpoints themselves.

Even the <form> element’s "action" attribute is built for this simplicity. For example, if your resource is /tea/genmaicha/, you could use <form method="post" action="brew">. Voilà, relative URLs in action! This approach is powerful, practical, and aligned with the infrastructure we already rely on.

Let’s not overcomplicate things for the sake of theoretical perfection. KISS.

grep has a --line-buffered option that does the job fine in most cases. Just set in your aliases grep='grep --line-buffered', that way you get the correct behavior when you tail logs piped to a sequence of greps, and you avoid the performance penalty in scripts.

It's the first time I hear "Mikado" but it's pretty much the commit policy I established for work, and we call it micro-commits.

http://lucasr.org/2011/01/29/micro-commits/

https://mrcote.info/blog/2017/12/04/more-lessons-from-mozrev...

https://dev.to/rpalo/plan-your-commits

The article focuses on refactoring and migrations, but it works also for regular development. One rule of thumb is: write a one-line commit message, and then write the code described by the commit, and just that. Another rule of thumb is that refactors should go into their own commit. So while you are coding according to your one-line commit message, if there are small refactors needed along the way, commit them separately. Fix whitespace? One commit. Extract a method so you can re-use it? One commit to extract, then use the extracted method in your next commit.

Having small atomic commits makes code that is much easier to review, and much easier to test. I think it's similar to unit testing: we change how we write code in order to make it unit-testable. This is for code review: we write code with micro-commits in order to make it code-reviewable.

This method is pretty much incompatible with squash-and-rebase. Squashing throws away all the useful information of micro-commits. Instead, just merge, and the merge commit itself is equivalent to the squashed-rebased version.

Obviously, the Mikado Method cannot work if you don’t have a good and highly reliable automated test suite.

I disagree. Of course it's always better to have an automated test suite. But in the absence of one, the only thing you can rely on is thorough code review. And with micro-commits you have a much better chance of spotting problems if the code-diff you review contains only a small self-contained atomic change. Code-reviewing a large squashed commit is all but impossible.

Yep, this is pretty much what I've settled on myself.

GET for read, POST for write. And a url made of a slash-terminated "resource" followed by an "action" verb. user 123 + edit = "/user/123/edit" ; user 123 + default(show) = "/user/123/" ; list of users = "/user/list" ; etc.

When applied to web pages, it means you can have <form action="edit"> and the "action" attribute of the form directly matches the "action" of the backend/router/API. I like that, it makes me feel warm and fuzzy. :-)

Thank you for saying that, it save me the trouble of writing it.

This apples-to-oranges comparison (strawman? motivated reasoning?) unfortunately makes me mistrust this entire article.

Fully agree. When the user selects a file via the file selection dialog, that automatically implies s/he has given permission to read that file. So the Flatpak libportal approach has really good UX. Having a second popup to grant access to the file would be horrible UX. Which is why apps ask for coarse-grained permissions like "access to all files" in order to bother the user as little as possible with multiple permission dialogs. Which then kinda defeats the point of sandboxing. I'm reminded of how Android apps need to know your "location" in order to scan for wifi networks.

In general I think all permission dialogs should be reframed as selection or confirmation dialogs.

• Open file dialog -> grants permission to read that file.

• Open file for edit dialog -> grants permission to read/write that file.

• Save as -> grants permission to read/write that file.

• Select which wifi network to connect to -> grants permission to use internet

• Do you want to display events in your neighborhood? -> grants permission to location data

• Select which camera & mic to use for this call -> grants permission to record video & audio

--

I have to say though, apart from that permissions thing, the author makes a lot of good points I hadn't realized before.

I wonder what would be the performance characteristics of using the top 2 bits to mark 63-bit integers. So 00xxx are positive integers and 11xxx are negative integers. That way all integer operations stay simple and you just need to check that the result is in the correct range.

No.

Web 1.0 was one-to-many publishing, the direct translation to the web of existing pre-web business models. Thus "1.0", the first iteration based on known/previous models.

Web 2.0 was many-to-many publishing, user-generated-content, stuff that wasn't possible or even conceivable prior to the web. Thus "2.0", the second iteration based on characteristics unique/native to the web.

Honestly, people need to stop redefining those terms.

It's an interesting hypothesis.

Unfortunately I see a bunch of people kneejerk to say "adblocking is good" or "ads are bad" when that's not really relevant to the question.

But I don't think it's adblockers that caused the ruin the of the ad-based free content model, rather they are the symptom. I believe the cause is Google capturing an ever-higher share of the ad revenue. Let's say in the old days 80% of the ad revenue went to the publisher (and 20% to the ad ecosystem), and that was enough to keep the lights on. Ad revenue dried up, but it's because the share that goes to the publisher is now 20% while the "ecosystem" (mostly Google now) captures 80%. This happened gradually like a frog boiling in water, and as ads generated less revenue per unit, publishers were forced to add more ads per page to compensate. Just one more ad. And one more. And 15 years later there's more ads than content. In response, users started using adblockers more and more, which led to decreasing revenue, which led to more ads per page. A vicious cycle.

Nowadays there's so little revenue to made made from ads (since most is captured by Google) that only content with the smallest production cost can make it. Genuine content is not economical, and the only content that can survive on those razor-thin margins is automatically-generated SEO spam.

The "chocolate covered bananas and European currency systems problem" is certainly more accurate, but in terms of naming things, it's automatically disqualified because it's way too long to be usable in any context. So the "XY problem" wins by default. Maybe if you had titled it the "CCB-ECS problem" it would have caught on. Or something less abstract and chocolatey. Naming things sure is hard.