Last active
April 28, 2018 02:48
-
-
Save mauricioszabo/a8f21571b341a0d8659491e0daceb2e6 to your computer and use it in GitHub Desktop.
Anima's Examples
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "hamster" | |
require "benchmark" | |
require "set" | |
TIMES = 2_000_000 | |
Benchmark.bmbm do |r| | |
x = arr = nil | |
r.report("Mutable array - push") do | |
x = [] | |
TIMES.times do |i| | |
x << i | |
x << rand | |
end | |
arr = x.dup | |
end | |
r.report("Mutable array - pop") do | |
(TIMES * 2).times do |i| | |
x.pop() | |
end | |
end | |
r.report("Mutable array - unshift") do | |
x = [] | |
TIMES.times do |i| | |
x.unshift i | |
x.unshift rand | |
end | |
end | |
r.report("Mutable array - get random element") do | |
TIMES.times do | |
x[rand(TIMES)] | |
end | |
end | |
r.report("Mutable array - shift") do | |
(TIMES * 2).times do |i| | |
x.shift() | |
end | |
end | |
r.report("Immutable list - prepend") do | |
x = Hamster::List[] | |
TIMES.times do |i| | |
x = x.add(i).add(rand) | |
end | |
end | |
r.report("Immutable list - shift") do | |
(TIMES * 2).times do |i| | |
x = x.tail | |
end | |
end | |
r.report("Immutable deque - append at last") do | |
x = Hamster::Deque[] | |
TIMES.times do |i| | |
x = x.push(i) | |
x = x.push(rand) | |
end | |
end | |
r.report("Immutable deque - pop") do | |
(TIMES * 2).times do |i| | |
x = x.pop() | |
end | |
end | |
r.report("Immutable deque - append at first") do | |
x = Hamster::Deque[] | |
TIMES.times do |i| | |
x = x.unshift(i) | |
x = x.unshift(rand) | |
end | |
end | |
r.report("Immutable deque - shift") do | |
(TIMES * 2).times do |i| | |
x = x.shift() | |
end | |
end | |
r.report("Immutable vector") do | |
x = Hamster::Vector[] | |
TIMES.times do |i| | |
x = x << i | |
x = x << rand | |
end | |
end | |
r.report("Mutable vector - get random element") do | |
TIMES.times do | |
x[rand(TIMES)] | |
end | |
end | |
r.report("Mutable vector - pop") do | |
y = x | |
(TIMES * 2).times do | |
x.pop | |
end | |
end | |
r.report("Mutable SET") do | |
x = Set[] | |
TIMES.times do |i| | |
x << i | |
x << rand | |
end | |
end | |
r.report("Mutable SET - check element") do | |
TIMES.times do |i| | |
x.include?(i + 2) | |
end | |
end | |
r.report("Immutable SET") do | |
x = Hamster::Set[] | |
TIMES.times do |i| | |
x = x.add?(i) | |
x = x.add?(rand) | |
end | |
end | |
r.report("Immutable SET - check element") do | |
TIMES.times do |i| | |
x.include?(i + 2) | |
end | |
end | |
r.report("Immutable list - from mutable") do | |
Hamster::List[*arr] | |
end | |
r.report("Immutable Deque - from mutable") do | |
Hamster::Deque[*arr] | |
end | |
r.report("Immutable Vector - from mutable") do | |
Hamster::Vector[*arr] | |
end | |
r.report("Immutable Set - from mutable") do | |
Hamster::Set[*arr] | |
end | |
end;nil |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'sequel' | |
require "sqlite3" | |
require "json" | |
require "anima" | |
require "hamster" | |
require "dry-validation" | |
DB = Sequel.connect('sqlite:/') | |
Sequel.extension :migration | |
Sequel::Model.plugin :timestamps | |
class CreateAll < Sequel::Migration | |
def up | |
create_table(:users) do | |
primary_key :id | |
String :name, null: false | |
String :email, null: true | |
end | |
create_table(:tasks) do | |
primary_key :id | |
foreign_key :user_id, :users | |
column :title, String, null: false | |
end | |
end | |
end | |
CreateAll.apply(DB, :up) | |
DB[:users].insert(name: "Foo Bar") | |
NameValidation = Dry::Validation.Schema do | |
required(:name).filled | |
end | |
# This is NOT a good implementation of `Either` monad: | |
# ideally, it would need to check if return code is an | |
# Either class, then "flatten" the structure | |
# the same as JS Promise do | |
class Either | |
def self.left(val) | |
new(val, nil, false) | |
end | |
def self.right(val) | |
new(nil, val, true) | |
end | |
def initialize(left, right, is_right) | |
@left, @right = left, right | |
@is_right = is_right | |
end | |
private :initialize | |
def get! | |
raise ArgumentError.new("Left value") unless @is_right | |
@right | |
end | |
def error | |
@left | |
end | |
def then | |
if @is_right | |
Either.right(yield @right) | |
else | |
self | |
end | |
end | |
def or_else | |
if @is_right | |
self | |
else | |
Either.left(yield @left) | |
end | |
end | |
end | |
class User | |
extend Sequel::Model::ClassMethods | |
include Anima.new(:id, :name, :email) | |
self.dataset = DB[:users] | |
def self.call(param) | |
new(param) | |
end | |
def update!(params) | |
validate(params).then do |new_obj| | |
pk = self.class.primary_key | |
pk_value = send(pk) | |
self.class.dataset.where(pk => pk_value).update(new_obj.to_h) | |
new_obj | |
end | |
end | |
private :with | |
private def validate(params) | |
new_obj = with(params) | |
errors = NameValidation.call(new_obj.to_h).errors | |
if(errors.empty?) | |
Either.right(new_obj) | |
else | |
Either.left(errors) | |
end | |
end | |
end | |
u = User.first | |
u2 = u.update!(name: "") | |
u2 = u.update!(email: "[email protected]") | |
u2 = u.update!(name: "Szabo") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "anima" | |
require "hamster" | |
module UpInAnima | |
def update_in(arg, *rest, &b) | |
value = self.send(arg) | |
if(rest.size == 0) | |
with(arg => b.call(value)) | |
else | |
with(arg => value.update_in(*rest, &b)) | |
end | |
end | |
end | |
class User | |
include Anima.new(:name, :children) | |
include UpInAnima | |
NULL = new(name: "", children: Hamster::Vector[]) | |
end | |
class Children | |
include Anima.new(:name, :age) | |
include UpInAnima | |
NULL = new(name: "", age: 0) | |
end | |
user = User::NULL.with( | |
name: "Ariovaldo", | |
children: Hamster::Vector[ | |
Children::NULL.with(name: "Emily", age: 9) | |
] | |
) | |
# Emily's birthday! | |
user.update_in(:children, 0, :age) { |x| x + 1 } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "sinatra" | |
require_relative "database_access" | |
class User | |
def self.call(param) | |
User::Valid.new(param) | |
end | |
private def validate(params) | |
new_obj = with(params) | |
obj_hash = new_obj.to_h | |
errors = NameValidation.call(obj_hash).errors | |
if(errors.empty?) | |
Either.right(new_obj) | |
else | |
Either.left(User::Invalid.new(obj_hash, errors)) | |
end | |
end | |
end | |
class User::Valid < User | |
end | |
class User::Invalid < User | |
attr_reader :errors | |
def initialize(params, errors) | |
super(params) | |
@errors = errors.freeze | |
end | |
end | |
get "/" do | |
@users = User.all | |
erb :index | |
end | |
get "/:id/edit" do |id| | |
@user = User[id] | |
erb :edit | |
end | |
post "/:id" do |id| | |
@user = User[id] | |
user_params = params[:user].map { |k, v| [k.to_sym, v] }.to_h | |
@user.update!(user_params).then { |new_user| | |
return redirect "/#{new_user.id}/edit" | |
}.or_else { |user| | |
@user = user | |
return erb :edit | |
} | |
end | |
__END__ | |
@@ index | |
<h1>Users</h1> | |
<ul> | |
<% @users.each do |user| %> | |
<li> | |
<%= user.name %> -> <%= user.email || "no e-mail configured" %> | |
<a href="/<%= user.id %>/edit">Edit</a> | |
</li> | |
<% end %> | |
</ul> | |
@@ edit | |
<h1>Editing <%= @user.name %></h1> | |
<% if @user.is_a?(User::Invalid) %> | |
<h2>Errors validating...</h2> | |
<ul> | |
<% @user.errors.each do |field, values| %> | |
<li><%= field %>: <%= values.join(", ") %></li> | |
<% end %> | |
</ul> | |
<% end %> | |
<form action="/<%= @user.id %>" method="POST"> | |
<p>Name: <input type="text" value="<%= @user.name %>" name="user[name]"></p> | |
<p>E-Mail: <input type="text" value="<%= @user.email %>" name="user[email]"></p> | |
<p><input type="submit" value="Save"></p> | |
</form> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment