All Projects → fewlinesco → Kaur

fewlinesco / Kaur

Licence: mit
A bunch of helper functions to ease the development of your applications.

Programming Languages

elixir
2628 projects

Projects that are alternatives of or similar to Kaur

Aioreactive
Async/await reactive tools for Python 3.9+
Stars: ✭ 215 (+1164.71%)
Mutual labels:  functional-programming, functional
Kotlin Result
A multiplatform Result monad for modelling success or failure operations.
Stars: ✭ 369 (+2070.59%)
Mutual labels:  functional-programming, functional
Phunctional
⚡️ λ PHP functional library focused on simplicity and performance
Stars: ✭ 243 (+1329.41%)
Mutual labels:  functional-programming, functional
Rangeless
c++ LINQ -like library of higher-order functions for data manipulation
Stars: ✭ 148 (+770.59%)
Mutual labels:  functional-programming, functional
Moses
Utility library for functional programming in Lua
Stars: ✭ 541 (+3082.35%)
Mutual labels:  functional-programming, functional
Helios
A purely functional JSON library for Kotlin built on Λrrow
Stars: ✭ 157 (+823.53%)
Mutual labels:  functional-programming, functional
Coconut
Simple, elegant, Pythonic functional programming.
Stars: ✭ 3,422 (+20029.41%)
Mutual labels:  functional-programming, functional
Forge
Functional style JSON parsing in Kotlin
Stars: ✭ 106 (+523.53%)
Mutual labels:  functional-programming, functional
Hof
Higher-order functions for c++
Stars: ✭ 467 (+2647.06%)
Mutual labels:  functional-programming, functional
Yalinqo
Yet Another LINQ to Objects for PHP [Simplified BSD]
Stars: ✭ 400 (+2252.94%)
Mutual labels:  functional-programming, functional
Sup
Composable, purely functional healthchecks in Scala.
Stars: ✭ 138 (+711.76%)
Mutual labels:  functional-programming, functional
Functional Programming Learning Path
A Learning Path for Functional Programming
Stars: ✭ 582 (+3323.53%)
Mutual labels:  functional-programming, functional
Redux Most
Most.js based middleware for Redux. Handle async actions with monadic streams & reactive programming.
Stars: ✭ 137 (+705.88%)
Mutual labels:  functional-programming, functional
Deep Waters
🔥Deep Waters is an easy-to-compose functional validation system for javascript developers 🔥
Stars: ✭ 188 (+1005.88%)
Mutual labels:  functional-programming, functional
Lambda Lantern
🧙 ‎‎ A 3D game about functional programming patterns. Uses PureScript Native, C++, and Panda3D.
Stars: ✭ 122 (+617.65%)
Mutual labels:  functional-programming, functional
Eslint Plugin Functional
ESLint rules to disable mutation and promote fp in JavaScript and TypeScript.
Stars: ✭ 282 (+1558.82%)
Mutual labels:  functional-programming, functional
Bulb
A reactive programming library for JavaScript.
Stars: ✭ 84 (+394.12%)
Mutual labels:  functional-programming, functional
Fuego
Functional Experiment in Golang
Stars: ✭ 87 (+411.76%)
Mutual labels:  functional-programming, functional
Carp
Carp is a programming language designed to work well for interactive and performance sensitive use cases like games, sound synthesis and visualizations.
Stars: ✭ 4,389 (+25717.65%)
Mutual labels:  functional-programming, functional
Pampy.js
Pampy.js: Pattern Matching for JavaScript
Stars: ✭ 544 (+3100%)
Mutual labels:  functional-programming, functional

Hex pm Build Status Inline docs

Kaur

Pronounced |kɔː|

A bunch of helper functions to ease the development of your applications.

Installation

def deps do
  [{:kaur, "~> 1.1.0"}]
end

Usage

:ok, :error tuples A.K.A Result tuples

{:ok, value} and {:error, reason} is a common pattern in Erlang and Elixir. The Kaur.Result module adds functions to help deal with these values without getting out of your pipeline.

You can have a look at the documentation to know what's available or you can take a look at how we use it in Kaur itself.

Just below you will find a small example of how your code could look like using Kaur.Result. In this example we try to determine if a person can rent a car. People can rent a car if they are between 21 and 99 year old and have a bonus greater than 0.8.

Example without Kaur

defmodule Person do
  defstruct [:name, :age, :bonus]
end

defmodule MyModule do
  def rent_a_car(person = %Person{}) do
    with {:ok, person1} <- validate_age(person),
         {:ok, person2} <- validate_bonus(person1)
    do
      {:ok, display_driving_message(person2)}
    else
      {:error, reason} ->
        {:error, handle_error(person, reason)}
    end
  end

  defp display_driving_message(person) do
    "Welcome #{person.name}, you can rent a car"
  end

  defp handle_error(person, {:bonus, expected_bonus}) do
    "Sorry #{person.name}, but you need a bonus of #{expected_bonus} but have only #{person.bonus}."
  end
  defp handle_error(person, {:license_type, expected_license}) do
    "Sorry #{person.name}, but you need a #{expected_license} license but have a #{person.license_type} license."
  end
  defp handle_error(person, {:too_old, maximum_age}) do
    "Sorry #{person.name}, but you need to be younger than #{maximum_age}"
  end
  defp handle_error(person, {:too_young, minimum_age}) do
    "Sorry #{person.name}, but you need to be older than #{minimum_age}"
  end

  defp validate_age(%{age: age}) when age > 99, do: {:error, {:too_old, 99}}
  defp validate_age(%{age: age}) when age < 21, do: {:error, {:too_young, 21}}
  defp validate_age(person), do: {:ok, person}

  defp validate_bonus(person = %{bonus: bonus}) when bonus > 0.8, do: {:ok, person}
  defp validate_bonus(_person), do: {:error, {:bonus, 0.8}}
end

Example using Kaur

defmodule MyModule do
  alias Kaur.Result

  def rent_a_car(person = %Person{}) do
    person
    |> validate_age()
    |> Result.and_then(&validate_bonus/1)
    |> Result.map(&display_driving_message/1)
    |> Result.map_error(&handle_error(person, &1))
  end

  # ... Same business logic as before
end

Execution

iex> MyModule.rent_a_car %Person{name: "Jane", age: 42, bonus: 0.9}
{:ok, "Welcome Jane, you can rent a car"}

iex> MyModule.rent_a_car %Person{name: "John", age: 42, bonus: 0.5}
{:error, Sorry John, but you need a bonus of 0.8 but have only 0.5."}

iex> MyModule.rent_a_car %Person{name: "Robert", age: 11, bonus: 0.9}
{:error, "Sorry Robert, but you need to be older than 21"}

iex> MyModule.rent_a_car %Person{name: "Mary", age: 122, bonus: 0.8}
{:error, "Sorry Mary, but you need to be younger than 99"}

Security

A small module which can generate API keys:

iex>  Kaur.Secure.generate_api_key
"UtiE9qs-7FbJs8OIt5nCiw=="

iex> Kaur.Secure.generate_api_key
"BTxaJNrA_QsAhWSLKOMj8A==

Environment Variables

We love environment variables but, unfortunately, Elixir configuration doesn't play well with them. If we use System.get_env in config/*.exs files, they will be evaluated at compile time.

We would really want to have our configuration based on environment variables. A common pattern is to use {:system, "ENVIRONMENT_VARIABLE"} wherever we need a value to be fetched at runtime. That's common but, unfortunately, that's not built-in so we have to handle this behaviour ourselves.

Kaur.Environment abstracts how we read application configuration so it can automatically handle the loading of environment variables when it's needed.

# config/config.exs
config :my_app, :my_key, {:system, "MY_KEY"}
config :my_app, :my_key2, "MY STATIC VALUE"

iex> Kaur.Environment.read(:my_app, :my_key)
{:ok, "VALUE DYNAMICALLY LOADED"}

iex> Kaur.Environment.read(:my_app, :my_key2)
{:ok, "MY STATIC VALUE"}

iex> Kaur.Environment.read(:my_app, :something_else)
{:error, :no_value}

Code of Conduct

By participating in this project, you agree to abide by its CODE OF CONDUCT.

Contributing

You can see the specific CONTRIBUTING guide.

License

Kaur is released under The MIT License (MIT).

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].