Created
October 13, 2014 11:06
-
-
Save assembler/6ebafc69d1b92148381a to your computer and use it in GitHub Desktop.
Revisions
-
assembler created this gist
Oct 13, 2014 .There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,283 @@ # https://www.youtube.com/watch?v=uTR__8RvgvM # ---------------------------------------------------------------------------- # Project = Struct.new(:creator) Person = Struct.new(:address) Address = Struct.new(:country) Country = Struct.new(:capital) City = Struct.new(:weather) class Optional attr_accessor :value def initialize(value) @value = value end def self.from_value(value) new(value) end def and_then(&block) if value.nil? Optional.new(nil) else block.call(value) end end def method_missing(*args, &block) and_then do |value| Optional.new(value.public_send(*args, &block)) end end end def get_project_weather(project) # Optional.new(project) # .and_then { |project| Optional.new(project.creator) } # .and_then { |creator| Optional.new(creator.address) } # .and_then { |address| Optional.new(address.country) } # .and_then { |country| Optional.new(country.capital) } # .and_then { |capital| Optional.new(capital.weather) } # .value Optional.new(project).creator.address.country.capital.weather.value end project = Project.new(Person.new(Address.new(Country.new(City.new("sunny"))))) p get_project_weather(project) project = Project.new(Person.new) p get_project_weather(project) # ---------------------------------------------------------------------------- # Blog = Struct.new(:categories) Category = Struct.new(:posts) Post = Struct.new(:comments) class Many attr_accessor :values def initialize(values) @values = values end def self.from_value(value) new([value]) end def and_then(&block) Many.new(values.map(&block).flat_map(&:values)) end def method_missing(*args, &block) and_then do |value| Many.new(value.public_send(*args, &block)) end end end def words_in(blogs) # Many.new(blogs) # .and_then { |blog| Many.new(blog.categories) } # .and_then { |category| Many.new(category.posts) } # .and_then { |post| Many.new(post.comments) } # .and_then { |comment| Many.new(comment.split(/\s+/)) } # .values Many.new(blogs).categories.posts.comments.split(/\s+/).values end blogs = [ Blog.new([ Category.new([ Post.new(['I love cats', 'I love dogs']), Post.new(['I love mice', 'I love pigs']), ]), Category.new([ Post.new(['I hate cats', 'I hate dogs']), Post.new(['I hate mice', 'I hate pigs']), ]), ]), Blog.new([ Category.new([ Post.new(['Red is better than blue']), ]), Category.new([ Post.new(['Blue is better than red']), ]), ]), ] p words_in(blogs) # ---------------------------------------------------------------------------- # Thread.abort_on_exception = true require "rubygems" gem "uri_template" require "uri" require "net/http" require "json" require "uri_template" def get_json(url, &success) Thread.new do puts "[GET] #{url}..." uri = URI.parse(url) json = Net::HTTP.get(uri) value = JSON.parse(json) success.call(value) end end # get_json("https://api.github.com") do |urls| # org_url_template = URITemplate.new(urls["organization_url"]) # org_url = org_url_template.expand(org: "ruby") # get_json(org_url) do |org| # repos_url = org["repos_url"] # get_json(repos_url) do |repos| # most_popular_repo = repos.max_by { |repo| repo["watchers_count"] } # repo_url = most_popular_repo["url"] # get_json(repo_url) do |repo| # contributors_url = repo["contributors_url"] # get_json(contributors_url) do |users| # most_profilic_user = users.max_by { |user| user["contributions"] } # user_url = most_profilic_user["url"] # get_json(user_url) do |user| # puts "The most influential Rubyist is #{user["name"]} (#{user["login"]})" # end # end # end # end # end # end class Eventually attr_accessor :block def initialize(&block) @block = block end def self.from_value(value) new { |s| s.call(value) } end def and_then(&block) Eventually.new do |success| run do |value| block.call(value).run(&success) end end end def run(&success) block.call(success) end end def get_github_api_urls github_root_url = "https://api.github.com" Eventually.new{ |success| get_json(github_root_url, &success) } end def get_org(urls, name) org_url_template = URITemplate.new(urls["organization_url"]) org_url = org_url_template.expand(org: name) Eventually.new{ |success| get_json(org_url, &success) } end def get_repos(org) repos_url = org["repos_url"] Eventually.new { |success| get_json(repos_url, &success) } end def get_most_popular_repo(repos) most_popular_repo = repos.max_by { |repo| repo["watchers_count"] } repo_url = most_popular_repo["url"] Eventually.new { |success| get_json(repo_url, &success) } end def get_contributors(repo) contributors_url = repo["contributors_url"] Eventually.new { |success| get_json(contributors_url, &success) } end def get_most_profilic_user(users) most_profilic_user = users.max_by { |user| user["contributions"] } user_url = most_profilic_user["url"] Eventually.new { |success| get_json(user_url, &success) } end get_github_api_urls .and_then { |urls | get_org(urls, 'ruby') } .and_then { |org | get_repos(org) } .and_then { |repos| get_most_popular_repo(repos) } .and_then { |repo | get_contributors(repo) } .and_then { |users| get_most_profilic_user(users) } .run do |user| puts "The most influential Rubyist is #{user["name"]} (#{user["login"]})" end # ---------------------------------------------------------------------------- # module Monad def within(&block) and_then do |value| self.class.from_value(block.call(value)) end end end Optional.include Monad Many.include Monad Eventually.include Monad def description_from(containing_json) containing_json.within do |json| JSON.parse(json) end.within do |hash| "%s (%s)" % hash.values_at("name", "login") end end optional_nil = Optional.new(nil) p description_from(optional_nil) optional_json = Optional.new(%|{ "login": "nobu", "name": "Nobuyoshi Nakada" }|) p description_from(optional_json) many_jsons = Many.new([ %|{ "login": "nobu", "name": "Nobuyoshi Nakada" }|, %|{ "login": "matz", "name": "Yukihiro Matsumoto" }|, ]) p description_from(many_jsons) eventually_json = Eventually.new do |success| Thread.new do uri = URI.parse("https://api.github.com/users/nobu") json = Net::HTTP.get(uri) success.call(json) end end description_from(eventually_json).run { |description| p(description) } puts "\n press any key to exit \n" gets