I miss the ternary operator - does anyone have a macro that allows a ternary operator in Elixir code?

sometimes i wish elixir had ternary operator :frowning:

Does anyone have a macro that allows ternary operator like in their elixir code?

Mostly need it when using conditional rendering of tailwind classes on a html element inside LiveView

I’m the person who usually rejects PRs if they contain a single if clause. In a language like Elixir, using conditional operators is a clear sign of a wrong-written non-idiomatic code. Ternary would have been rejected and ruled out by credo custom checks even if it existed. [End of the uninvited cry of the soul.]

Back to the ability of implementing it, no, that’s not possible in a nutshell, this syntax won’t pass the parser/lexer. OTOH, nothing (short of common sense) prevents one from implementing a macro with one of the allowed but not used by core pipe-operators.

foo = bar <|> :baz <~> :baw would be 10 LoCs.

There is a “ternary operator” in elixir, it’s the if macro itself:

if true, do: "True!", else: "False!"

In heex, you can do any of these

<div class={["btn", @active && "btn-active", @disabled && "btn-disabled"]}>

<div class={["btn", if(@active, do: "btn-active", else: "btn-inactive")]}>

<div class={["btn", {"btn-active", @active}, {"btn-disabled", @disabled}]}>

The two available options are usually the ones @fceruti already mentioned… Either inlining if or doing something like (a && b) || c for short. But I have to admit I’m also on @mudasobwa’s camp - I’d just avoid using conditionals as well and instead focus on the data-flow :sweat_smile:

TIL the {class, conditional} form exists. Will use that more in future.

Yeah, other than if your first option is falsey, the x = cond && opt1 || opt2 is a pretty good analogue, and it feels appropriately hacky, like you’re writing sh.

x = cond && opt1 || opt2

good enough, welcome back ternary operator :rofl: :rofl: :rofl: :rofl:

i knew i asked a dumb question but seeing the replies, im so glad i asked.

<div class={["btn", {"btn-active", @active}, {"btn-disabled", @disabled}]}> this is so good

You still gotta be careful here and should likely prefer to write it as @thiagomajesk suggested: (a && b) || c otherwise you don’t get the ternary behaviour if b is falsey:

iex> true && false || "oops"
"oops"

EDIT: Wait, what am I saying? The parens don’t solve that at all, lol. So ya, be careful of that.

Yeah, like I said “other than if your first option is falsey”, just that in practice that’s usually not the case.

supplemental_mod = if core_only?, do: nil, else Supplemental

Although there is a bullet-proof version

condition && (opt1 || true) || opt2

(please don’t use it at home or school.)

Bulletproof you say :thinking:

iex (19) { opt1, opt2 } = { nil, "opt2" }
{nil, "opt2"}
iex (20) if true, do: opt1, else: opt2
nil
iex (21) true && ( opt1 || true ) || opt2
true

:person_facepalming:

Indeed.

sigh, ya sorry, my comment was a train-wreck through-and-through :person_facepalming: :skull:

:rofl:

It’s the weekend, expectations were very low, but you exceeded them anyway :wink:

You were just excited to see me :slight_smile:

I think this is good evidence to support your argument that ternaries should be avoided. It’s deceptively complex to make bulletproof. :slight_smile:

I work in JS for my dayjob, and ternaries are everywhere cause everything can be null or undefined at any point in the program even if we try to be thorough with parsing and validation. Some library will return Optional<T> at some point and we’re back to explicitly checking null on every line unless we wrap every dependency (which is generally good practice in imperative code but also has a cost).

I find that ternaries tend to appear more frequently when the code doesn’t have well-defined data structures to pass between abstraction boundaries.

Since Elixir is strongly typed, we can avoid all this pain by focusing on data flow and pattern matching like @thiagomajesk mentioned. It feels like a huge weight has been lifted from my shoulders when I open up an Elixir project after working in JS all week. lol

I’ve also almost never needed a ternary in Python code since Python is strongly typed and has good support for working with well-defined custom data structures as well. :slight_smile:

Not tooootally wrong :stuck_out_tongue: I certainly thought to myself “Hey, @smathy’s back!” but I haven’t posted here in several weeks at this point, so wasn’t sure how long it’s been.

Also, I’m just going to tell people I’m battling AI slop with human slop :upside_down_face:

Happy to be back. OMG Phoenix 1.8 is amazeballs. Good to see your little pug face again :slight_smile:

I wish human slop was up to the challenge, but AI slop is the dominant force in that battle.

This is a ludicrous position. Any use of if or cond is non-idiomatic? By that measure, every prominent package in the ecosystem and elixir itself aren’t idiomatic.

I personally strive for fewer branches, flat control flows, and avoid nested conditionals. There is still logical branching involved. Pushing all logic branches into functions, or pattern matches, doesn’t necessarily make your code clearer.

I could not agree more. Although I never proposed that. What I meant, is logical branching is (usually, not always, and I stated this clearly in the quote you cited) a result of a bad design.

I love how Joe Armstrong reasoned about Erlang was just modelling the real world around us, and I strive to keep aligned with this approach. Ask yourself how often you take a decision in a form of a strict conditional operator?

Offtopic: I just recalled the oldie but goldie. A wife asks a developer to go to groshery and says, “Take a milk and if there are eggs, take a dozen.” In an hour the developer comes back with a dozen of milk cartons.

So yeah, we rarely do something like “if there is a summer, I go swimming, otherwise I go skying.” Just think about that.