Giter Site home page Giter Site logo

ex-r_enum's Introduction

hex.pm version CI GitHub code size in bytes

REnum

REnum is Enum extended with convenient functions inspired by Ruby and Rails ActiveSupport. It also provides full support for native functions through metaprogramming. In addition to REnum, modules such as RList, RMap, RRange can also be used.

Installation

def deps do
  [
    {:r_enum, "~> 0.6"}
  ]
end

For the full list of available functions, see API Reference.

About REnum

All the functions are available defined in

compact/1

Returns an list of all non-nil elements.

iex> REnum.compact([1, nil, 2, 3])
[1, 2, 3]
# See also REnum.ActiveSupport.compact_blank

each_slice/2

Returns Stream given enumerable sliced by each amount.

iex> ["a", "b", "c", "d", "e"]
iex> |> REnum.each_slice(2)
iex> |> Enum.to_list()
[["a", "b"], ["c", "d"], ["e"]]

grep/2

Returns elements selected by a given pattern or function.

iex> ["foo", "bar", "car", "moo"]
iex> |> REnum.grep(~r/ar/)
["bar", "car"]

iex> 1..10
iex> |> REnum.grep(3..8)
[3, 4, 5, 6, 7, 8]

reverse_each/2

Calls the function with each element, but in reverse order; returns given enumerable.

iex> REnum.reverse_each([1, 2, 3], &IO.inspect(&1))
# 3
# 2
# 1
[1, 2, 3]

pluck/2

Extract the given key from each element in the enumerable.

iex> payments = [
...>   %Payment{dollars: 5, cents: 99},
...>   %Payment{dollars: 10, cents: 0},
...>   %Payment{dollars: 0, cents: 5}
...> ]
iex> REnum.pluck(payments, [:dollars, :cents])
[[5, 99], [10, 0], [0, 5]]
iex> REnum.pluck(payments, :dollars)
[5, 10, 0]
iex> REnum.pluck([], :dollars)
[]

exclude?/2

The negative of the Enum.member?.Returns true+if the collection does not include the object.

iex> REnum.exclude?([2], 1)
true

iex> REnum.exclude?([2], 2)
false
# See also REnum.ActiveSupport.include?

without/2

Returns enumerable excluded the specified elements.

iex> REnum.without(1..5, [1, 5])
[2, 3, 4]

iex> REnum.without(%{foo: 1, bar: 2, baz: 3}, [:bar])
%{foo: 1, baz: 3}
# See also REnum.ActiveSupport.including

many?/2

Returns true if the enumerable has more than 1 element.

iex>  REnum.many?([])
false

iex> REnum.many?([1])
false

iex> REnum.many?([1, 2])
true

iex> REnum.many?(%{})
false

iex> REnum.many?(%{a: 1})
false

iex> REnum.many?(%{a: 1, b: 2})
true

list_and_not_keyword?/1

Returns true if argument is list and not keyword list.

iex> REnum.list_and_not_keyword?([1, 2, 3])
true

iex> REnum.list_and_not_keyword?([a: 1, b: 2])
false

map_and_not_range?/1

Returns true if argument is map and not range.

iex> REnum.map_and_not_range?(%{})
true

iex> REnum.map_and_not_range?(1..3)
false

About RList

RList is List extended with convenient functions inspired by Ruby and Rails ActiveSupport. All the functions are available defined in

push/2

Appends trailing elements.

iex> [:foo, 'bar', 2]
iex> |> RList.push([:baz, :bat])
[:foo, 'bar', 2, :baz, :bat]

iex> [:foo, 'bar', 2]
iex> |> RList.push(:baz)
[:foo, 'bar', 2, :baz]
# See also REnum.Ruby.shift, REnum.Ruby.pop, REnum.Ruby.unshift

combination/2

Returns Stream that is each repeated combinations of elements of given list. The order of combinations is indeterminate.

iex> RList.combination([1, 2, 3, 4], 1)
iex> |> Enum.to_list()
[[1],[2],[3],[4]]

iex> RList.combination([1, 2, 3, 4], 3)
iex> |> Enum.to_list()
[[1,2,3],[1,2,4],[1,3,4],[2,3,4]]

iex> RList.combination([1, 2, 3, 4], 0)
iex> |> Enum.to_list()
[[]]

iex> RList.combination([1, 2, 3, 4], 5)
iex> |> Enum.to_list()
[]
# See also RList.Ruby.repeated_combination, RList.Ruby.permutation, RList.Ruby.repeated_permutation

fill/3

Fills the list with the provided value. The filler can be either a function or a fixed value.

iex> RList.fill(~w[a b c d], "x")
["x", "x", "x", "x"]

iex> RList.fill(~w[a b c d], "x", 0..1)
["x", "x", "c", "d"]

iex> RList.fill(~w[a b c d], fn _, i -> i * i end)
[0, 1, 4, 9]

iex> RList.fill(~w[a b c d], fn _, i -> i * 2 end, 0..1)
[0, 2, "c", "d"]

dig/3

Finds and returns the element in nested elements that is specified by index and identifiers.

iex> [:foo, [:bar, :baz, [:bat, :bam]]]
iex> |> RList.dig(1)
[:bar, :baz, [:bat, :bam]]

iex> [:foo, [:bar, :baz, [:bat, :bam]]]
iex> |> RList.dig(1, [2])
[:bat, :bam]

iex> [:foo, [:bar, :baz, [:bat, :bam]]]
iex> |> RList.dig(1, [2, 0])
:bat

iex> [:foo, [:bar, :baz, [:bat, :bam]]]
iex> |> RList.dig(1, [2, 3])
nil

intersection/2

Returns a new list containing each element found both in list1 and in all of the given list2; duplicates are omitted.

iex> [1, 2, 3]
iex> |> RList.intersection([3, 4, 5])
[3]

iex> [1, 2, 3]
iex> |> RList.intersection([5, 6, 7])
[]

iex> [1, 2, 3]
iex> |> RList.intersection([1, 2, 3])
[1, 2, 3]
"""

sample/2

Returns one or more random elements.

values_at/1

Returns a list containing the elements in list corresponding to the given selector(s).The selectors may be either integer indices or ranges.

iex> RList.values_at(~w[a b c d e f], [1, 3, 5])
["b", "d", "f"]

iex> RList.values_at(~w[a b c d e f], [1, 3, 5, 7])
["b", "d", "f", nil]

iex> RList.values_at(~w[a b c d e f], [-1, -2, -2, -7])
["f", "e", "e", nil]

iex> RList.values_at(~w[a b c d e f], [4..6, 3..5])
["e", "f", nil, "d", "e", "f"]

iex> RList.values_at(~w[a b c d e f], 4..6)
["e", "f", nil]

second/1

Equal to Enum.at(list, 1).

iex> ~w[a b c d]
iex> |> RList.second()
"b"
# See also RList.ActiveSupport.third, RList.ActiveSupport.fourth, RList.ActiveSupport.fifth and RList.ActiveSupport.forty_two

from/2

Returns the tail of the list from position.

iex> ~w[a b c d]
iex> |> RList.from(0)
["a", "b", "c", "d"]

iex> ~w[a b c d]
iex> |> RList.from(2)
["c", "d"]

iex> ~w[a b c d]
iex> |> RList.from(10)
[]

iex> ~w[]
iex> |> RList.from(0)
[]

iex> ~w[a b c d]
iex> |> RList.from(-2)
["c", "d"]

iex> ~w[a b c d]
iex> |> RList.from(-10)
[]
# See also RList.ActiveSupport.to

to_sentence/2

Converts the list to a comma-separated sentence where the last element is joined by the connector word.

You can pass the following options to change the default behavior. If you pass an option key that doesn't exist in the list below, it will raise an

Options

  • :words_connector - The sign or word used to join all but the last element in lists with three or more elements (default: ", ").
  • :last_word_connector - The sign or word used to join the last element in lists with three or more elements (default: ", and ").
  • :two_words_connector - The sign or word used to join the elements in lists with two elements (default: " and ").
iex> ["one", "two"]
iex> |> RList.to_sentence()
"one and two"

iex> ["one", "two", "three"]
iex> |> RList.to_sentence()
"one, two, and three"

iex> ["one", "two"]
iex> |> RList.to_sentence(two_words_connector: "-")
"one-two"

iex> ["one", "two", "three"]
iex> |> RList.to_sentence(words_connector: " or ", last_word_connector: " or at least ")
"one or two or at least three"

iex> ["one", "two", "three"]
iex> |> RList.to_sentence()
"one, two, and three"

new/2

Make a list of size amount.

iex> 1
iex> |> RList.new(3)
[1, 1, 1]

About RMap

RMap is Map extended with convenient functions inspired by Ruby and Rails ActiveSupport. All the functions are available defined in

dig/2

Returns the object in nested map that is specified by a given key and additional arguments.

iex> RMap.dig(%{a: %{b: %{c: 1}}}, [:a, :b, :c])
1

iex> RMap.dig(%{a: %{b: %{c: 1}}}, [:a, :c, :b])
nil

each_key/2

Calls the function with each key; returns :ok.

iex> RMap.each_key(%{a: 1, b: 2, c: 3}, &IO.inspect(&1))
# :a
# :b
# :c
:ok
# See also RMap.Ruby.each_value, RMap.Ruby.each_pair

except/2

Returns a map excluding entries for the given keys.

iex> RMap.except(%{a: 1, b: 2, c: 3}, [:a, :b])
%{c: 3}

invert/1

Returns a map object with the each key-value pair inverted.

iex> RMap.invert(%{"a" => 0, "b" => 100, "c" => 200, "d" => 300, "e" => 300})
%{0 => "a", 100 => "b", 200 => "c", 300 => "e"}

iex> RMap.invert(%{a: 1, b: 1, c: %{d: 2}})
%{1 => :b, %{d: 2} => :c}

values_at/2

Returns a list containing values for the given keys.

iex> RMap.values_at(%{a: 1, b: 2, c: 3}, [:a, :b, :d])
[1, 2, nil]

deep_atomize_keys/1

Returns a list with all keys converted to atom. This includes the keys from the root map and from all nested maps and arrays.

iex> RMap.deep_atomize_keys(%{"name" => "Rob", "years" => "28", "nested" => %{ "a" => 1 }})
%{name: "Rob", nested: %{a: 1}, years: "28"}

iex> RMap.deep_atomize_keys(%{"a" => %{"b" => %{"c" => 1}, "d" => [%{"a" => 1, "b" => %{"c" => 2}}]}})
%{a: %{b: %{c: 1}, d: [%{a: 1, b: %{c: 2}}]}}
# See also RList.ActiveSupport.deep_symbolize_keys, RList.ActiveSupport.symbolize_keys, RList.ActiveSupport.deep_stringify_keys, RList.ActiveSupport.stringify_keys,

deep_transform_keys/2

Returns a list with all keys converted to atom. This includes the keys from the root map and from all nested maps and arrays.

iex> RMap.deep_transform_keys(%{a: %{b: %{c: 1}}}, &to_string(&1))
%{"a" => %{"b" => %{"c" => 1}}}

iex> RMap.deep_transform_keys(%{a: %{b: %{c: 1}, d: [%{a: 1, b: %{c: 2}}]}}, &inspect(&1))
%{":a" => %{":b" => %{":c" => 1}, ":d" => [%{":a" => 1, ":b" => %{":c" => 2}}]}}
# See also RList.ActiveSupport.deep_transform_values

About RRange

All the functions are available defined in

begin/1

Returns the first element of range.

iex> RList.begin(1..3)
1
# See also RRange.Ruby.end

step/2

Returns Stream that from given range split into by given step.

iex> RList.step(1..10, 2)
iex> |> Enum.to_list()
[1, 3, 5, 7, 9]
"""

overlaps?/2

Compare two ranges and see if they overlap each other.

iex> RList.overlaps?(1..5, 4..6)
true

iex> RList.overlaps?(1..5, 7..9)
false

About RUtils

Some useful functions.

blank?/1

Return true if object is blank, false, empty, or a whitespace string. For example, +nil+, '', ' ', [], {}, and +false+ are all blank.

iex>  RUtils.blank?(%{})
true

iex> RUtils.blank?([1])
false

iex> RUtils.blank?("  ")
true

present?/1

Returns true if not RUtils.blank?

iex> RUtils.present?(%{})
false

iex> RUtils.present?([1])
true

iex> RUtils.present?("  ")
false

define_all_functions!/2

Defines in the module that called all the functions of the argument module.

iex> defmodule A do
...>   defmacro __using__(_opts) do
...>     RUtils.define_all_functions!(__MODULE__)
...>   end
...>
...>   def test do
...>     :test
...>   end
...> end
iex> defmodule B do
...>   use A
...> end
iex> B.test
:test

Progress

REnum Elixir Module Ruby Class Elixir Ruby ActiveSupport
REnum Enum Enumerable
RList List Array
RMap Map Hash
RRange Range Range
RStream Stream Enumerator::Lazy TODO TODO

ex-r_enum's People

Contributors

koga1020 avatar mnishiguchi avatar sinack avatar tashirosota avatar torifukukaiou avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

ex-r_enum's Issues

Maybe hide some implementation details?

It is a matter of design decision. So it is just an idea.

Currently the library exposes all the implementation details. I have a feeling that what users want is the top-level module and its functions. If we hide all the potentially-private modules, the documentation could be simpler. Then we can explain about each of the top-level functions in their @doc.

In other words, do the users need to know about REnum.Native, REnum.Ruby, etc?

Maybe skip implementing Ruby `Array#zip`?

Implementing List zip is a bit tricky!
Maybe we could skip it unless we really want what Ruby exactly does 🤔

Notes

  • Elixir has very flexible and powerful functions for zipping lists; all named zip or zip_*
  • Ruby zip behaves slightly different; when list lengths are not the same, nil is padded for shorter lists
  • Ruby's zip accept variable arguments; it accepts any argument length

Some related docs

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.