Hacker News new | ask | show | jobs
by rwl 1852 days ago
This is a good point, but notice that what makes the segregation easy in your example is that the query and the command have a shared way to refer to what the command will operate on: the filename.

Consider a conceptually very similar case: instead of finding and deleting files in a filesystem, think about finding and deleting lines matching a pattern within a file. Then the query is something like grep...but what do you put for the command on the other side of the pipe?

Of course, you can tell grep to output line numbers and use a command that operates on line numbers, or similar. The point is, in order to achieve this kind of segregation, you need some common way of naming operands on both sides of the divide. And naming things is hard, so segregating things this way is hard, and thus there's a lot of tools with mixed query/command responsibilities.

2 comments

PowerShell solved this problem by outputting easy to map objects instead of just plain text. Unfortunately they made it a bit more verbose than it could've been, and the industry didn’t recognize the potential, so it remained a niche product.

I still love PowerShell.

I love PowerShell too, but I think the real barrier to adoption is that it's just too slow.
The concept of object output isn't slow. PS is mostly slow because it's based on .NET and they didn't bother optimizing it.
Finding is a query. Deleting is destructive. Make sure that you are not nesting your destructions within a query.

You would first build a pure function that read the files and returned matching lines. You could then display the count of the matched lines, and if the user wants they can see those lines and what line number it is. This looks a lot like a dry-run.

You can then pass these results into an executor. You then build a system that combines all deletes of a file and passes that to your DeleteLinesInFile fuction that does so in a single transaction. Cycle through each file and voila.

My point is not that this is impossible; it's that separating the tasks of building a list of query results and then executing an operation on those results requires some kind of convention about how to refer to those results across the two phases. Developing such a convention is a harder problem than it looks like.

The example I was responding to was from the (Unix) shell, which as far as I am aware does not offer any such convention other than filenames. Real programming languages of course offer more options, but even there the problem is not solved: as you say, you must then build the system which understands how to take the results of the query and execute something on them. That means designing such a convention inside your program. The article is about using a type system to help you do that cleanly.