runexec
Proof-of-concept Elixir Contracts
I was toying around to see if I could possibly get something similar to Clojure-style pre/post enforcement. This is what I came up with and would like your input. Thanks.
Example Usage
defmodule Example do
require Contract
def reverse_abc(x) do
# Contract pre processing
pre_must_be_abc = fn -> x == "abc" end
pre = [
pre_must_be_abc,
]
# Contract post processing
post_must_be_cba = fn x -> x == "cba" end
post_must_be_string = fn x -> is_binary x end
post = [
post_must_be_cba,
post_must_be_string,
]
# Contract
# The arguments here are `[x]` and do not represent the current value of `x`
reverse_abc_contract = Contract.new([x], [pre: pre, post: post], String.reverse(x))
# Encorce Contract
reverse_abc_contract.(x)
end
end
Basic Implementation
defmodule Contract do
defmodule EnforcePreError do
defexception message: "Argument(s) Failed Pre Processing Requrements."
end
defmacro enforce(:pre, list, expr) do
quote do
valid? =
Enum.map(unquote(list), fn f -> f.() end)
|> Enum.all?(&(&1 == true))
case valid? do
true -> unquote(expr)
_ -> raise EnforcePreError
end
end
end
defmodule EnforcePostError do
defexception message: "Return value Failed Post Processing Requrements."
end
defmacro enforce(:post, list, value) do
quote do
valid? =
Enum.map(unquote(list), fn f -> f.(unquote(value)) end)
|> Enum.all?(&(&1 == true))
case valid? do
true -> unquote(value)
_ -> raise EnforcePostError
end
end
end
defmodule EnforceNothingError do
defexception message: "No enforcements are defined."
end
defmacro enforce(:prepost, pre, post, expr) do
quote do
pre = unquote(pre) || []
post = unquote(post) || []
no_enforcements? = (pre == [] && post == [])
get_value = fn ->
unquote(__MODULE__).enforce(:pre, unquote(pre), unquote(expr))
end
cond do
no_enforcements? -> raise EnforceNothingError
pre && post -> unquote(__MODULE__).enforce(:post, unquote(post), get_value.())
(pre == []) && post -> unquote(__MODULE__).enforce(:post, unquote(post), unquote(expr))
(post == []) && pre -> get_value.()
end
end
end
defmacro new(args, opts, expr) do
quote do
fn (unquote_splicing(args)) ->
unquote(__MODULE__).enforce(
:prepost, unquote(opts[:pre]), unquote(opts[:post]), unquote(expr)
)
end
end
end
end
Popular in Discussions
In django there is a cache framework backed by memcached. Rails also puts a lot of emphasis on caching, and even the idea of russian-doll...
New
After doing a port from a c++ library to my project in phoenix I’ve seen that I need a faster way to run this algorithm and I found this ...
New
Hi there Elixir friends :vulcan_salute:
In a recent task I was on, I needed to check in two dates which of them is the maximum and which...
New
The reason that Rails is as popular as it is is because it’s very easy for relatively inexperienced developers to get a lot of work done....
New
I have discovered Nix last month and I am currently on my way to migrating to it—both on macOS at home and the full NixOS distrubution at...
New
I suppose this question is effectively hackney vs. ibrowse but we are at a point in our project where we have to make a choice between th...
New
Hello,
Please pardon me for any faux paux. I am 46 and this is my first time on a forum of any kind. I wanted to to get answers from tho...
New
What configs will make sense to put to runtime.exs?
–
A bit of how I configure apps:
I have generic configs in config/config.exs,
dev...
New
I’m playing with Elixir - It’s fun. I think @rvirding does give Elixir courses these days.
Re: files and database - when I given Erlang ...
New
Seen any cool LiveView demos, sample apps or examples? Please post them here! :003:
New
Other popular topics
This post is an instruction guide to help you setup your Neovim for Elixir development from scratch. It includes general information on h...
New
Hi,
I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? Ecto.Repo — Ecto v3.14.0 has exampl...
New
What learn first? Rust or Elixir
Hi Elixir community!
I’m here because i want learn a new language. I’m a junior developer and mainly i ...
New
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors:
[WARN] - (starship::utils): Executing command ...
New
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
I’ve got an issue with an app and I’ve no idea of how to troubleshoot it. I’m hoping someone here might have seen something similar.
I p...
New
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
Seen any cool LiveView demos, sample apps or examples? Please post them here! :003:
New
Kind of like when jquery came out, it was super necessary. Existing drag and drop libraries have a bunch of baggage to support old browse...
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
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance








