HN user

samdk

2,399 karma

very outdated website: http://samdk.com

email name: sam, domain: defabbiakane.com

Posts19
Comments369
View on HN

Most of that stuff isn't necessary just to replace Plex, the OP's saying them Jellyfin started them on a journey they're presumably enjoying, not that they needed everything there to replace it.

I think you're right the bar is still too high for most folks, although I will note that I think it's dramatically lower than it used to be. A lot of the tools are all-around way easier to deal with, tailscale makes a lot of "personal cloud" use-cases much more feasible, and then coding agents (I'm using claude code) dramatically reduce the labor costs of getting this stuff all working and fixing it when something goes wrong.

It's not that postgres can't handle large tables, it's more that many of the ways it uses system tables aren't particularly optimized for them being large, so you're operating outside the territory the table/query design was probably built for.

Like most things postgres it'll probably still work better than it has any right to for a while, but it'd be extremely unsurprising if it caused you unexpected problems at some point. (And if it does, they'll likely excitingly novel and you'll probably have to dig pretty deep to understand what's going on.)

The Little Schemer was what finally got me to internalize how to solve problems recursively. I'd taken a couple of college classes and could do it some already, but it took a lot more thought than solving those same problems in other ways.

About a third of the way through The Little Schemer, things just clicked, and what had been hard became pretty instantly easy.

Some of that was it building on existing knowledge, but I found the structure very helpful. The narrative is really just the glue around a well-designed series of incremental problems.

Postgres doesn't natively support multi-master. (Although there are a variety of open source/proprietary offerings that add support for it to various degrees.)

I think it's unfortunate the first/often only exposure people get to FP is a build-up-from-the-foundations approach that emphasizes recursion so much, I think it leaves most students with a poor understanding of why functional paradigms and practices are practical and useful.

I've written primarily in a functional language (OCaml) for a long time now, and it's very rare I write a recursive function. Definitely less than once a month.

In most domains, almost every high-level programming task involves operating on a collection. In the same way that you generally don't do that with a while loop in an imperative language, you generally don't do it with recursion in a functional one, because it's an overly-powerful and overly-clunky tool for the problem.

For me the real key to starting to be comfortable and productive working in a functional language was realizing that they do actually all have for-each loops all over the place: the "fold" function.

(Although actually it turns out you don't end up writing "fold"s all that often either, because most functional languages have lots of helper functions for common cases--map, filter, partition, etc. If you're solving a simpler problem, the simpler tool is more concise and easier to think about.)

This is not the same thing, but you might be interested in taking a look at the excellent online Terra Mystica implementation (https://terra.snellman.net/) if you haven't seen it already.

It's a web interface, but the underlying representation is text-based, and you can type in the commands directly if you want. This leads to some nice features--for example, you can plan your moves several steps ahead of time, and you get a game log for free.

There creator wrote a blog post about that particular design decision: https://www.snellman.net/blog/archive/2014-12-08-command-lan...

Thanks for writing this!

One nitpick: the guide says "If you're curious why it's important to not have a phone number on your account, see the security key FAQ", but the linked security FAQ doesn't actually appear to say why it's important.

I use it on my laptop and am generally very happy with it, although I don't do all that much technical work there and certainly wouldn't want it to replace my primary workstation. (I'd be dearly sad if I had to give up xmonad.)

But it's made my laptop a far more pleasant place to get work done if I need to do so, and generally works far better than I was expecting it would. I no longer feel compelled to run a VM on my laptop to get real work done.

You can have Goodreads do something like this, in the newsletters and other mail section you can check the 'send me the monthly new releases email', 'only send this to me if it includes an author I've read', and click the customize button and deselect all of the genres.

And then you end up with an email which has new releases by authors you've read before.

I generally have no use for most of what Goodreads does, but this combined with the ability to pull my Kindle purchases in automatically is pretty useful.

"Back-end web understanding" seems oddly specific compared to everything else on that list.

Why that and not something more general which might encompass other kinds of domain-specific knowledge? There are a lot of companies on your list which seem like they might care more about other skills that don't really fit anywhere else. (Experience working with databases for example, for one of the 7 or so database companies.)

Finding out you spend all day in meetings still tells you something, especially with a few follow-up questions. Who do you spend your time meeting with? What about? How many people are typically involved? How long do meetings last?

(That said, most of the people I've been interviewed by were devs, so this was not really ever an issue.)

    Note: after 25 minutes answering questions for a job you really
    want it’s kinda hard to shift to a question-asking mode.
When I was looking for a job I found that it helped enormously to write down a set of questions ahead of time.

Some I liked:

What does a typical day look like for you?

What projects do you work on?

How long have you been at $company? How has your role changed since then?

If I were hired for this role, what would my first day/week/month look like?

Is there anything about $company that some people really like, but others might dislike? (For example, having an open-plan office.)

What tools do you use on a regular basis?

I think you may be under-weighting the value of Python being a great exploratory tool a bit.

For the (relatively small) amount of research I've done, the bulk of the time spent working with code was spent exploring large-ish sets of data to see what results came up. Python is a very nice language for doing this, and also has a great ecosystem of tools and libraries for doing it.

I think it's also true that the benefits of FP and static typing are most pronounced on large codebases. If you're writing small specific bits of code you can mostly hold in your head all at once you don't gain nearly as much from a language like Haskell.

Which is not to say I wouldn't like to see more people using languages like Haskell (my primary programming language is OCaml now), but I think the bad habits people in scientific fields have around programming are a lot more of a detriment than the specific language they're using.

Negative comments 12 years ago

My initial reaction to this post was similar to many of the other commenters here. There's a real danger in making "negative" comments taboo.

But I don't think Nick's saying "don't make critical comments" here. This sentence encapsulates the idea quite well:

    But I fear emphasis has shifted from critically
    reflecting on and examining our own beliefs to simply 
    criticizing and pointing out errors in other people’s work.
If someone proposes an idea and you think it's terrible, it's worth taking a few minutes to think about whether you're wrong or misunderstanding or missing some part of the bigger picture. It's not about accepting ideas un-critically, but instead about examining your own ideas and beliefs just as critically as you're examining others.

I suspect it's just always been the case that many people are bad at this. It's just that the internet has democratized and scaled up the process of getting poorly thought out negative opinions about your work.

You're missing some big ones, I think. In the last few years protest movements have effected regime changes in Tunisia, Egypt, and Ukraine. Those transitions have been at all smooth, but it's hard to claim the protests in each of those cases weren't hugely influential.

The protests in Ferguson, MO are still playing out so it's hard to say what exactly the effects will be, but I suspect not nothing.

In Hong Kong protests in 2003 helped stop the passage of a security law restricting activity that the mainland Chinese government doesn't like (http://en.wikipedia.org/wiki/Hong_Kong_1_July_marches). More recently protests helped prevent a "moral education" bill from being passed here also.

In general I think it's a bit shortsighted to look at protest movements and think they're ineffective because many of them do not produce change. Protests are (generally) a way for people without a lot of political power to have their voices heard. They're going to fail a lot of the time, because protest movements start when people don't have other kinds of leverage or power.

Also, I think it's important to remember that at least part of the goal of a protest movement is getting attention. The Occupy Wall Street protests didn't directly change much, but they did create a national (and international) conversation about equality that didn't really exist before. It's a lot harder to evaluate that kind of indirect result, but I think it would be a mistake to discount it. (The OWS protests also spurred the creation of Occupy Central, one of the organizations that's leading these protests in Hong Kong.)

Board game designers will very often give permission for things like this so long as there's not an official money-generating version in existence, or at least ignore their existence.

I think the most visible case of this happening is the deck-building game Dominion, where the policy was that it was fine to have free versions so long as they didn't use the artwork and so long as they're taken down when there's an official app. (Which has now happened on some platforms and I think is expected to happen on others soon.)

I also suspect that Vassal is so niche that most designers/publishers don't really see it as taking away very much from paid apps, even if those do exist. The people playing on Vassal are generally the kind of people who buy a lot of board games.

Did you read the article? The entire thing is about a school that for years did things like have teachers change test answers after the fact in order to increase their overall test scores. That's what I mean by gaming statistics.

edit: clearly I should have chosen a different word. I think you're all focusing on one specific word I used, and not on the actual argument I'm making, which is that if your model of assessment depends on a single Big Important Number, people will find ways to make that number what they need it to be.

NCLB tried to fix those "ineffectual, corrupt money pits" by giving enormous, overriding importance to a small set of easily gamed statistics.

Creating a single performance metric that people Must Meet Or Else is an exceedingly naive approach to performance problems. It creates perverse incentives that reward cheating and short-term hacks over sustainable long-term solutions, and it doesn't actually do anything to help solve the problem at all.

I'm not, to be clear, saying that trying to use statistics as a tool to solve problems in education is a bad idea, but laws like NCLB are comparable to non-technical managers trying to measure software dev performance with metrics like "lines of code produced" or "number of bug tickets closed". (And I don't think I have to explain to anyone here why that's a bad idea.)

Moving a file (within the same file system) is an atomic operation on most file systems, but writing data is not.

If you don't do this and you're overwriting a file directly and the write fails for some reason, the data from the old file will be gone and you'll only have a partially-written new file in its place.

This also helps with systems that continuously poll files and watch for changes. If you have, say, a compiler watching your file, you don't want it to start compiling a partially-written version of your file and give you some strange error just because it happened to poll before the write finished.

If your app gets a nontrivial number of visitors this is probably way easier than trying to pull a specific user's request out of logs.

And once you reach a certain size the person doing user-level support very likely doesn't have access to server logs.

There's also this: http://www.podval.org/~sds/ocaml-sucks.html

I also mostly agree with it for base OCaml (and I write OCaml every day), but it's worth noting a lot of the complaints--even the ones outside of the 'standard library' section--can be fixed by using a better standard library. (Like Jane Street's Core/Async, which is what I'm most familiar with.)

I do disagree with several of those complaints though (not auto-converting between numeric types is a feature, not a bug!), and several of them are the kind of things that seemed like a big deal when I first started using OCaml and now no longer do. (Like the record field names issue...if you're writing well-organized code each type almost always has its own module anyway, so this doesn't matter much.)

If you combine many lines of code into one, you lose readability in any language ;).

Probably you would actually format this as follows:

    let menu = GMenu.menu () in
    let explain = GMenu.menu_item ~packing:menu#add ~label:"Explain this decision" () in
    explain#connect#activate ~callback:(fun () -> show_explanation impl) 
    |> ignore;
    menu#popup ~button:(B.button bev) ~time:(B.time bev);
Which is rather nicer.

If you haven't, also check out Jane Street's Core/Async, which is an almost-complete replacement (and extension) of the standard library. (Info here: http://janestreet.github.io/.) I work for JS so I'm biased, but I think it's quite a nice set of libraries. Because it's been developed mostly internally, we've had a lot of freedom to fix bad decisions, so it hasn't built up as much cruft as might be expected. (Although it is still obviously far from perfect.)

Yep, this is a hard problem. I wasn't super enthusiastic about the verbosity of option types when I first started programming OCaml, but almost two years later I'm quite convinced that they're the right way to do things. I really don't think there's a whole lot of downside, and being able to basically just not think about a large and hard-to-identify class of bugs is incredibly freeing.

This may not cover your use cases, but for cascading errors you can often write code something like the following:

     match
       foo_err ()
       >>=? bar_err
       >>=? baz_err
       [... etc ...]
     with
     | Error e -> Log.error e
     | Ok result ->
       [...]
This ends up working pretty well when you're working with pure functions because there's not anything to unwind, but you're right that it doesn't solve all problems.

If you're interested in talking to more people about this kind of thing, the Core mailing list might be a good place to try: https://groups.google.com/forum/?fromgroups#!forum/ocaml-cor...

    Even the best functional programmers I've seen fall
    back to some kind of exit-or-exception semantic in
    the None case.
I offer two responses to this. I'm going to use Jane Street's alternative Core standard library for OCaml (http://janestreet.github.io/) in my examples, because that's what I'm most familiar with.

First, consciously raising an exception is far, far better than having an exception raised without you being aware of it. I can search OCaml code for all of the instances of raise, failwith, and _exn, and end up with a reasonable understanding of when my code might conceivably fail. I can't do the same thing in Java, because many of the functions I'm calling might return null.

And it's really not that hard to deal with optional values when you have them. Sure, it's slightly more verbose than not having to deal with null, but in practice you have to write a bunch of if statements checking if things are null everywhere anyway.

Also, most languages don't have good abstractions for dealing with nulls despite them being everywhere, so they're always painful. Languages like OCaml and Haskell do have good abstractions, so you can often avoid a lot of the verbosity: if you have an optional value and really do want to raise an exception (usually only in scripts/smaller programs), wrap your value in Option.value_exn. If you have a reasonable default value, call Option.value ~default:(...). If you have a bunch of optional values together, you can sequence them together with Option.(>>=), because Option is a monad.

Second, there are alternatives to raising exceptions in the middle of big programs. Consider the Or_error library (see https://github.com/janestreet/core/blob/master/lib/or_error....), which is a part of Core. Rather than having a type like Option everywhere:

    type 'a option = Some 'a | None
It also has types like Or_error (defined approximately like this):
    type 'a or_error = Ok 'a | Error Error.t
Error.t is a very useful type that lets you lazily construct error messages from values, so that you don't pay the (often high) cost of serializing things into a human-readable form until you actually decide you need the error message.

What this lets you do is write your code inside the Or_error monad. Because it's a monad, it's very easy to sequence error-generating operations together, and you don't have to check for errors unless you explicitly decide you want to.

Often, you can do something useful like log the error to a log file or display an alert, rather than killing off the entire program. Sometimes, of course, an error is bad enough that it should cause the program to die, and then you can make it terminate with Or_error.ok_exn. But that's relatively rare. If you're trying to write robust systems, many errors are things you can deal with intelligently, and having those errors encoded in the type system ensures you don't forget to do it.

I basically agree with the final conclusion, but I don't think the example given--deleting five lines of text--actually supports it at all. The author is claiming that vim's way of doing it is cryptic (normal 5dd), and then says this about emacs' way:

    Define a function for a ‘universal’ n-many operator
    ( Control-U ), pass that an iteration count integer,
    have that perform the pre-defined global
    kill-line-of-text operation ( Control-K ).
Vim's solution is conceptually the same: you're in normal mode because that's where you do text manipulation, prefixing commands with numbers is the standard way of repeating an action a fixed number of times, and dd is the pre-defined global delete-line-into-a-buffer operation.

They're both cryptic until you understand what's happening--the only real difference is that vim is less explicit, because this kind of action is exactly what vim is best at.

I suspect that there's a better example for demonstrating emacs' power, but I don't know emacs well enough to provide it. Vim is probably my favorite piece of software, but there are certainly things emacs does better.

The Chadwick Chair 13 years ago

I don't know that this does, but the Aeron comes in three different sizes. You can adjust the tension of the fabric base (that's the twisty knob on the right-hand side), also.