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

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
Hey everyone! :waving_hand: I’ve published Part 7 of the Building Distributed Systems in Elixir series, where we build core distributed ...
New
mudasobwa
So, instead of wasting my afternoon arguing with anonymous handles on X, I turned to my trusty, soulless assistant and said: “Listen, ple...
New
zorn
An educational side project in Elixir, Phoenix, and Tauri. I share what I learned while wiring Automerge into the BEAM, including how I s...
New
abreujp
New article: Elixir Project Structure — From mix new to a Growing Codebase I’ve published a new article in my Elixir learning series on d...
New
nathanl
Process labels are useful for visualization and debugging. Here’s why you should use them.
New
zorn
:pencil: Phoenix’s built-in LiveView test helpers require you to hand-build the form payload and start a fresh pipe after every click. Wo...
New

Other Trending Topics Top

JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews