Live data from Hacker News

Generalizing 'jq' and Traversal Systems using optics and standard monads

chrispenner.ca

21–30 of 102 posts

Re: Generalizing 'jq' and Traversal Systems using optics and standard monads

#21
post #13

Earlier quoted context omitted.

That's more difficult to type than something like `.company.staff | .pets | flatten | filter .type == "cat" | log(...)`

Maybe so, but much easier to read . Code is read 10x more often than written, especially in teams, so it makes sense to optimize for legibility rather than elegance in some "higher" mindset, or less keys pressed (because most of the time will be spent staring at the line you wrote than actually typing if you write a functional line like that.)

Perhaps its easier for you to read. It takes me 2-3 longer to read the loops since each loop is unique and I have to parse the semantics/context, whereas its quick for me to parse the behavior from the named functional operators even at a glance. Conversely I find writing the functional version a bit trickier for complex reduce operations.

Re: Generalizing 'jq' and Traversal Systems using optics and standard monads

#22
post #15
post #11

Earlier quoted context omitted.

Functions are composable. Your statement is not. If I would ask you to create a snippet that searches for cats, another one that searches for dogs and a third one that searches for staff that owns both a cat and a dog you will either duplicate a lot of code or end up with functions. Now if you restrict yourself to not introduce any side effects, the interpreter can be proven correct, the execution can be analysed muc…

What's wrong with functions? A function `printCatsBelongingToStaff()` is much easier to read than a line of functional code. I don't understand what you mean by "analyzed much better" and "neat safety guarantees". Is my code hard to analyze or unsafe?

Your code is impossible to analyze. Console.log is a side effect.

For loops can be easily mapped into functional constructs, but not your snipped does not compute anything. It's not a function.

Re: Generalizing 'jq' and Traversal Systems using optics and standard monads

#23
post #9

Why do you need all this theory when you can use simple imperative languages? for staff in company.staff: for pet in staff.pets: if pet.type == 'cat': print(pet.name + " belongs to " + staff.name) I don't understand why functional languages are used at all.

Because it is easier to reason about data transformations. Here when I see loops and conditionals it is confusing because anything could be happening. company.staff.filter(notCats).forEach(printMessage) has more information of what is going on for example imho. But there is a lot more to it.

Re: Generalizing 'jq' and Traversal Systems using optics and standard monads

#25
post #23
post #9

Why do you need all this theory when you can use simple imperative languages? for staff in company.staff: for pet in staff.pets: if pet.type == 'cat': print(pet.name + " belongs to " + staff.name) I don't understand why functional languages are used at all.

Because it is easier to reason about data transformations. Here when I see loops and conditionals it is confusing because anything could be happening. company.staff.filter(notCats).forEach(printMessage) has more information of what is going on for example imho. But there is a lot more to it.

How would you define the `printMessage` function? The `pet` object doesn't have context about `staff`, and the `filter` function is filtering staff, not pets. It could return staff that have both cats and dogs, so it would incorrectly print dogs.

Re: Generalizing 'jq' and Traversal Systems using optics and standard monads

#26
post #22
post #15

Earlier quoted context omitted.

What's wrong with functions? A function `printCatsBelongingToStaff()` is much easier to read than a line of functional code. I don't understand what you mean by "analyzed much better" and "neat safety guarantees". Is my code hard to analyze or unsafe?

Your code is impossible to analyze. Console.log is a side effect. For loops can be easily mapped into functional constructs, but not your snipped does not compute anything. It's not a function.

Oh, you mean using analyzing software. Yeah, I've never had a use for that. On the other hand, you could make my function append to a string and then return the string. Then it wouldn't have side effects so it would be analyzable.

Re: Generalizing 'jq' and Traversal Systems using optics and standard monads

#27
post #9

Why do you need all this theory when you can use simple imperative languages? for staff in company.staff: for pet in staff.pets: if pet.type == 'cat': print(pet.name + " belongs to " + staff.name) I don't understand why functional languages are used at all.

Because I can abstract over whether it's staff.pets or staff.children etc. etc.

It's all right. In the sense of using a tool when you find yourself constrained perhaps it's worth waiting till you find a problem where you feel "there's got to be a better way".

It's happened to me when I was writing generators/shrinkers for generative tests that operate over any Thrift or Protobuf type.

Re: Generalizing 'jq' and Traversal Systems using optics and standard monads

#28
post #9

Why do you need all this theory when you can use simple imperative languages? for staff in company.staff: for pet in staff.pets: if pet.type == 'cat': print(pet.name + " belongs to " + staff.name) I don't understand why functional languages are used at all.

The syntax you just typed is an example of the theory in practice. Syntax != semantics.

Re: Generalizing 'jq' and Traversal Systems using optics and standard monads

#29
post #9

Why do you need all this theory when you can use simple imperative languages? for staff in company.staff: for pet in staff.pets: if pet.type == 'cat': print(pet.name + " belongs to " + staff.name) I don't understand why functional languages are used at all.

Functional idioms are often more expressive when you want to do something with a result other than an immediate side effect like printing. Sure, you can use imperative loops to build up a data structure to work with, but functional idioms (or comprehensions, which are generally an imperative-looking wrapper over functional idioms) can be quite concise and expressive for that purpose.

  for (owner 
builds a datastructure with the same information yours prints, with no extra boilerplate around building the datastructure.

Re: Generalizing 'jq' and Traversal Systems using optics and standard monads

#30
post #26
post #22

Earlier quoted context omitted.

Your code is impossible to analyze. Console.log is a side effect. For loops can be easily mapped into functional constructs, but not your snipped does not compute anything. It's not a function.

Oh, you mean using analyzing software. Yeah, I've never had a use for that. On the other hand, you could make my function append to a string and then return the string. Then it wouldn't have side effects so it would be analyzable.

> On the other hand, you could make my function append to a string and then return the string. Then it wouldn't have side effects

State mutation is a side effect. If you mean it builds it up locally, it would then not have nonlocal side effects (e.g., it would have a pure functional interface even though it has an imperative implementation). But to do that, you'd have construction and mutation overhead in the code, whereas with functional idioms / comprehensions, you would not.

This is especially the case when (as is often the case in practice) you are taking collection datastructures and producing collection structures to work with.

Post reply on HN