JKWA

JKWA

Author of Advanced Functional Programming with Elixir

More optics in Funx: when you need multiple foci, use a traversal.

Includes a Livebook

livebook funx

Showing Posts 1 to 10

tfwright

tfwright

I’ve never been super clear on the concept of functional programming and this is the first time I’ve heard it linked with “declarative” code, which is also something I’m frankly not super sold on as a useful category. But in the interest of hopefully gaining some clarity on both, my question is why you frequently seem to target pattern matching as the main “alternative” to these more functional tools? My understanding is that pattern matching itself is touted as a fundamental part of the Elixir’s functional tool kit? Again, not claiming any firm grasp of any of these categories so maybe I’m reading too much into that example.

But pattern matching is not the tool I would reach for if I wanted to solve the problem in your hypothetical:

Our domain requires that a transaction’s item price match its payment amount. We don’t need a single focus: we need both the item and the payment.

This is a boundary problem: we want to prevent an invalid transaction from being processed.

Wouldn’t we optimally want to prevent such a transaction from existing? Pattern matching works great as a tool for controlling execution, but I don’t think of it being a good candidate for validation for this reason. As in your example, it might be that no function head would match the invalid case, but not due to any intent to validate the data being passed, but because Elixir’s unique architecture enables us to forego explicit handling for the majority of error cases (“let it crash“). If anything it seems like your approach is more about defensiveness (which might be justified in the domain) than anything else. Wouldn’t the proper comparison be using a tool like Ecto to handle validating the data inputs (which would be modeled/tested etc)? What is not “declarative” or “functional” about that approach (which is a standard pattern)?

garrison

garrison

The term “declarative” is just very overloaded and has several popular meanings which are only vaguely related. One of those meanings is that of “referential transparency”, essentially pure functions, which of course has a lot to do with functional programming.

My own preferred meaning (and we have discussed this before) is that of code which rebuilds itself from scratch on each invocation rather than attempting to “patch” itself with small state changes. This is actually a programming technique more than anything which is why I often write “declarative style”. This technique is helpful for preventing bugs and tools that enable it (like React) are very powerful as long as you know that’s what they’re for. Unfortunately many do not.

The technique is strangely hard to put into words, but it has a great “know it when you see it” quality, so here are some articles with didactic examples that I found helpful.

All three of these are about frontend, but the technique is very broadly useful. Actually it was the description in section 6.3 of the FoundationDB paper that finally made it click for me. A distributed OLTP database is about as far from frontend as you can get and yet they present a real-world case of the exact same technique preventing bugs!

tfwright

tfwright

Appreciate your being game about repeating the discussion but I think the reason it hasn’t clicked for me is because I think about these things in terms of the backend where I’m not sure what to make of this idea:

So my question here remains the same, what are the advantages to the kind of tools being promoted in OP, vs just having a function that encapsulates the validation logic (so it can be reused, tested etc)?

garrison

garrison

The version of declarative in the OP is one which I would describe as “factoring out functions plus a fancy DSL”. There are times where you want a fancy DSL, usually for aesthetic reasons. Like, it’s kinda nice that Ecto queries look like SQL so they’re recognizable. And as for factoring, we all know how to do that.

As far as I can tell we have entire frameworks built around that declarative (e.g. Ash) and TBH I don’t really get it either, but hopefully someone else can provide the defense you’re looking for.

However, I think you understand “my” declarative more than you realize:

What is letting it crash but rebuilding the program from scratch? :slight_smile:

This is actually exactly the same concept. OTP supervision and React components take the same fundamental idea of “turn it off and on again”. The only real difference is that the latter are more sophisticated, but in fairness React is also decades newer. If you try to reason through “how do I build OTP supervisors but with dozens of processes in unique roles that can retain their complex state” you will eventually reinvent React from first principles.

JKWA

JKWA OP

Author of Advanced Functional Programming with Elixir

I’m using “declarative” in contrast to imperative or procedural control flow, not as a synonym for “pure FP.” What I mean is that declarative code describes intent, while procedural code proscribes execution.

tfwright

tfwright

OK, that’s the definition I’m familiar with (and so still not sold on). How does using a “Traversal” pattern describe intent better than a plain old validate function?

JKWA

JKWA OP

Author of Advanced Functional Programming with Elixir

Yes, agreed. Funx implements the underlying patterns. The DSLs are there to improve the syntax and readability, but behind the scenes they just compile down to Funx constructs.

JKWA

JKWA OP

Author of Advanced Functional Programming with Elixir

I tend to talk about “let it crash” more specifically, starting from invariants. You don’t try to fix or defend against broken invariants. If “a transaction must always have an :item” is an invariant, then a missing :item is a crash, not something to recover from.

garrison

garrison

It’s confusing because the definitions are all related, but as I said, vaguely.

The reason writing code that “defines intent” is useful is that you get to avoid manually defining the codepaths for complex state transitions. Instead you rebuild the state from scratch. This is good because keeping disparate pieces of state in sync by hand is bug-prone and laborious.

The OP is not a good pedagogical example of this because the code in question isn’t really stateful at all.

tfwright

tfwright

Your definition is interesting but strikes me as fairly esoteric, both in terms of use and remote from connotations of “declarative.” I think I have a vague sense of the connection you’re getting at, but I’ve also heard “self-healing” and “recoverable” as descriptions of that kind of design either of which seem like a much better term?

Where Next? Top

Trending in Blog Posts Top

mudasobwa
I am seeing a lot of aplications of Argumentum ad Vericundiam in software discussions. They do link some piece of writing and point us to...
New
bartblast
Hey folks, I just published a post about Hologram’s funding and where the project goes next - the short version: Curiosum as Main Spons...
New
pckrishnadas88
A while back, I had to process millions of database updates in a legacy system that was already hitting its 64 GB RAM limit, so scaling t...
New
rhcarvalho
At the heart of every Phoenix application is the often “invisible” HTTP server layer. For over a decade Cowboy has served the community ...
New
smaller_infinity
I recently figured out how to the the Rust hotpath profiling crate running in an elixir benchmark script (for profiling NIFs). I had some...
New
rhcarvalho
The Phoenix framework is notorious for its long term stability and dependability. Unlike most comparable projects, the Phoenix team activ...
New
pckrishnadas88
I’ve published Part 3 of my Elixir distributed systems learning series. This part explores process monitoring using the low-level primit...
New

Other Trending Topics Top

garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
mcass19
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve. They are GUI (Emerge) and State management (S...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
wintermeyer
There are three potential reasons for members of this forum to have a look at https://vutuv.de You are tired or annoyed of LinkedIn. Yo...
New
webofbits
Aludel - LLM Evaluation Workbench Aludel is an embeddable Phoenix LiveView dashboard for evaluating and comparing LLM prompts across mult...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews