angelmz
I’m still fairly new to the language. I wanted to know more about the “Elixir” way of doing things so I wrote a tiny program 3 ways, but I’m not sure which is the “right way”. I know you’d normally want only one module per page, this is just for demonstration purposes.
This one has the most isoloation of responsibilities:
defmodule Shapes do
defmodule Rectangle do
defstruct [:width, :height]
def perimeter(%Rectangle{width: width, height: height}) do
2 * (width + height)
end
def area(%Rectangle{width: width, height: height}) do
width * height
end
end
defmodule Circle do
defstruct [:radius]
def area(%Circle{radius: radius}) do
radius * radius * :math.pi()
end
end
end
This one leverages pattern matching a little more.
defmodule Shape do
defmodule Rectangle do
defstruct [:width, :height]
end
defmodule Circle do
defstruct [:radius]
end
def perimeter(%Rectangle{width: width, height: height}) do
2 * (width + height)
end
def area(%Rectangle{width: width, height: height}) do
width * height
end
def area(%Circle{radius: radius}) do
radius * radius * :math.pi()
end
end
This is my attempt at implementing it as a protocol. I’m a little unsure
because to my understanding protocols are for taking in different types.
defprotocol Shape do
def area(data)
def perimeter(data)
end
defmodule Rectangle do
defstruct [:width, :height]
defimpl Shape, for: Rectangle do
def area(%Rectangle{width: width, height: height}) do
width * height
end
def perimeter(%Rectangle{width: width, height: height}) do
2 * (width + height)
end
end
end
defmodule Circle do
defstruct [:radius]
defimpl Shape, for: Circle do
def area(%Circle{radius: radius}) do
:math.pi() * radius * radius
end
end
end
Thank you for any help ![]()
Trending in Questions
Hello!
Suppose you are building workflow (order / task / payment) processing system with the following requirements:
Each workflow con...
New
I’m in search of an Elixir library that offers PDF generation capabilities similar to Ruby’s Prawn. While there have been discussions abo...
New
I’m looking to build a personal workflow to quickly deploy web applications written in elixir/phoenix, for local consumption (ie not on t...
New
Before I dive in myself, did anyone successfully sprinkle Hologram into their existing LiveView app?
Looking for hints regarding:
Addi...
New
Kia ora,
We have been using elixir-google-api to connect to Google Drive. However, with the updates to Tesla due to CVEs this is now bro...
New
Hi all, I wanted to ask how the community is dealing with post-release steps.
Today we have Ecto migrations, which make sure that the db...
New
Hello,
I have an Elixir backend that implements a custom protocol over TCP. I want to load test the backend and assess the performance o...
New
Other Trending Topics
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
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
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
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
Emily is an Elixir library that runs Nx computations on Apple’s MLX. Install it as the default Nx backend and Nx, defn, Axon, Nx.Serving,...
New
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #blog-post
- #phoenix_html
- #iex
- #graphql
- #ai
- #genstage
- #elixirconf-us
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #security
- #hex










Showing Posts 1 to 6- Show Best Posts
- Show All Posts (oldest first)
- Show All Posts (newest first)
ityonemo
You don’t need the for: when the defimpl is nested in the module it’s implementing for.
If this were actually intended to be reused I would also maybe make your modules be Shape.Rectangle and Shape.Circle to avoid module name piracy (keep as many top level namespaces open, we have aliases to help readability)
gregvaughn
This sample project is almost a textbook example of polymorphism. Protocols are Elixir’s core way of supporting polymorphism. That being said, your second approach is not bad when you have limited expectations of the datatypes to support.
The main thing a protocol offers over the second approach is that you could publish the Protocol in one package. Then some other library author could choose to make their new data structure (which was unknown to you when you wrote the Protocol) fit into it.
adamu
I think your protocols version is great, but you should implement all the functions:
It seems that even structs that don’t implement all the functions in a protocol have dummy placeholders. Here’s an example from the core library for
Function, which doesn’t implement all the functions ofEnumerable:https://github.com/elixir-lang/elixir/blob/6730d669fb319411f8e411d4126f1f4067ef9231/lib/elixir/lib/enum.ex#L4778-L4780
LostKobrakai
This is special though. All the “optional” callbacks of
Enumerablecan be implemented using the non optionalreduce/3. The optional ones are only useful when the underlying datastructures allow for more efficient ways for those operations than usingreduce/3. So you can still useEnum.counton anyEnumerable, even if the implementation returns{:error, __MODULE__}.That’s different to not implementing part of a protocol.
Also I think
@optional_callbacksis the more appropriate way to mark optional callbacks, butEnumerablelikely can’t do so for historical reasons.adamu
Thanks for pointing that out - I didn’t check the implementation of
Enumerableproperly when I wrote that. I was looking for an example of a protocol that defines multiple functions, and an implementation that doesn’t implement them all. All the other protocols I can think of only define one functionityonemo
Protocols can’t have missing functions.
Behaviours can and usually the way to check is using function_exported?/3