Skip to content

Instantly share code, notes, and snippets.

@martinos
Last active January 4, 2022 19:44
Show Gist options
  • Save martinos/1076522bb326cc19b68978ac6227d4c3 to your computer and use it in GitHub Desktop.
Save martinos/1076522bb326cc19b68978ac6227d4c3 to your computer and use it in GitHub Desktop.
# https://gist.github.com/martinos/1076522bb326cc19b68978ac6227d4c3
require "fn_reader"
class Object
def _(fn)
fn.(self)
end
end
module HashFn
fn_reader :map_val
@@map_val = ->fn, a {
a.reduce({}) do |memo, (k, v)|
memo[k] ||= fn.(v)
memo
end
}.curry
end
module ObjectFn
fn_reader :attr, :attrs, :attrs_of, :same
@@attr = ->method, a {
a.send(method)
}.curry
@@attrs_of = ->defn, a {
defn.inject({}) do |memo, (method, fn)|
memo[method] ||= fn.(attr.(method).(a))
memo
end
}.curry
@@attrs = ->attribs, o { attribs.map { |a| [a, o.send(a)] }.to_h }.curry
@@same = ->a { a }
end
module EnumFn
fn_reader :count_by, :count, :sum, :at, :index_by, :group_by
class DoubleEntries < StandardError; end
@@at = ->key, a {
a.fetch(key)
}.curry
@@count_by = ->fn, a {
a.reduce({}) do |memo, a|
key = fn.(a)
memo[key] ||= 0
memo[key] += 1
memo
end
}.curry
@@count = ->a { a.count }
@@sum = ->fn, enum { enum.sum(&fn) }.curry
@@index_by = ->fn, a {
a.reduce({}) do |memo, a|
res = fn.(a)
if memo[res]
raise DoubleEntries
else
memo[res] = a
end
memo
end
}.curry
@@group_by = ->fn, a { a.group_by(&fn) }.curry
end
include EnumFn
include ObjectFn
include HashFn
__END__
require "minitest/autorun"
require "minitest/spec"
E = EnumFn
O = ObjectFn
H = HashFn
describe EnumFn do
describe "at" do
it "returns the element at pos" do
_(E.at.(:name).({ name: "Martin" })).must_equal("Martin")
end
end # =>
describe "sum" do
it "sums according to a givent algorithm" do
res = E.sum.(E.at.(:friends)).([{ friends: 2 }, { friends: 3 }])
_(res).must_equal(5)
end
end
describe "count_by" do
it "count_by an algorithm" do
res = E.count_by.(E.at.(:name)).([{ name: "Martin" }, { name: "Martin" }, { name: "Joe" }])
_(res).must_equal({ "Martin" => 2, "Joe" => 1 })
end
end
describe "index_by" do
it "indexes by a given algorithm" do
res = E.index_by.(E.at.(:name)).([{ name: "Martin" }, { name: "Joe" }])
_(res).must_equal({ "Martin" => { name: "Martin" }, "Joe" => { name: "Joe" } })
end
end
describe "count" do
it "counts element of a enum" do
_(count.([1, 2, 3])).must_equal(3)
end
end
describe "group_by" do
it "groups by an algorithm" do
_(group_by.(at.(:name)).([{ name: "Martin", age: 23 },
{ name: "Martin", age: 44 },
{ name: "Joe", age: 34 }])).
must_equal({ "Martin" => [{ name: "Martin", age: 23 },
{ name: "Martin", age: 44 }],
"Joe" => [{ name: "Joe", age: 34 }] })
end
end
end
require "ostruct"
describe ObjectFn do
describe "attr" do
it "returns the value of an object attribute" do
user = OpenStruct.new
user.age = 12
_(O.attr.(:age).(user)).must_equal 12
end
end
describe "attrs_of" do
it "extracts a map with attr accessor fields and apply an algorithm" do
user = OpenStruct.new
user.age = "12"
res = O.attrs_of.({ age: ->a { Integer(a) } }).(user)
_(res).must_equal({ age: 12 })
end
end
describe "attrs" do
it "extracts a map with" do
user = OpenStruct.new
user.first_name = "Joe"
user.last_name = "Bloe"
user.age = 13
res = O.attrs.([:first_name, :last_name]).(user)
_(res).must_equal({ first_name: "Joe", last_name: "Bloe" })
end
end
end
describe HashFn do
describe "map_val" do
it "maps values" do
res = H.map_val.(->a { a + 1 }).({ "joe" => 11, "john" => 22 })
_(res).must_equal({ "joe" => 12, "john" => 23 })
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment