Skip to content

Instantly share code, notes, and snippets.

@esehara
Forked from udzura/LICENSE
Last active October 16, 2017 04:18
Show Gist options
  • Save esehara/7587746 to your computer and use it in GitHub Desktop.
Save esehara/7587746 to your computer and use it in GitHub Desktop.
やわらかClojure -- Porting やわらかRuby to Clojure

Clojure をインストールする

演習

  • lein replで対話型コンソールが立ち上がることを確認しよう

(他未定)

Clojureを遊び尽くす弾丸ツアー

整数、文字列、配列、ハッシュ

  • 頻出表現
(Integer/parseInt "1")
(odd? 3)
#=> true
(even? 2)
#=> true

(count "clojure")
#=> 7

(count (filter #(= \c %) "clojure is very cool."))
#=> 2

(clojure.string/join (reverse "clojure"))
#=> "erujolc"

(sort [1 3 2])
#=> (1 2 3)

演習

  • 次の関数は存在する?存在しない?存在しないとしたら何処にある?

  • shuffle # ランダムに並び替える

  • hexadecimal # 16進数として解釈する

  • hours # 時間だとして何秒か表示する

ビックリとハテナ

  • ハテナで終わるメソッドはtrueまたはfalseを返す。?で終わることが出来るので、わざわざ is_~ を付けない。
  • ビックリで終わるメソッドは、元のオブジェクトに操作を加える(破壊的メソッド)
    • ただし、破壊的でないメソッドとかならず対になって存在する(Array#concatなどはビックリじゃないけど破壊的)
(clojureでの該当を探す)

未完


演習(1)

  • 以下のstr1とstr2の違いは何?
str1 = str2 = "paperboy"
str1 += "&co." 
str2 << "&co."
# ヒント
str1 == str2 #=> ?
str1.object_id == str2.object_id #=> ?

演習(2)

  • こうするとstr1は変更されるが、
str1 = "paperboy"
str1.tr! "p", "q"
  • こうするとstr2は変更されない。String#dupは何をしている?
str2 = "paperboy"
str2.dup.tr! "p", "q"

演習(3)

  • 整数のクラス(Integer)に「!」で終わるメソッドはあるか?それはなぜか?

ブロック

  • 3回繰り返す
3.times do
  puts "Hello, world!"
end
  • 配列に対して繰り返す
["dog", "cat", "chicken"].each do |name|
  puts sprintf("%s is an animal", name)
end
  • Fileを読み込んで必ず閉じる
File.open("/etc/hosts") do |f|
  puts f.read
end

演習

p = Proc.new do |obj|
  p obj
end
  • p はどんなオブジェクト?irbで調べてみよう
  • また、以下を実行するとどう表示される?
["dog", "cat", "chicken"].each &p
["dog", "cat", "chicken"].each p

p.call "dog"

クラスとモジュール

class Animal
  def warm_body?
    false
  end
end

class Fish < Animal
end

class Mammal < Animal
  def warm_body?
    true
  end
end

Fish.new.warm_body?
Mammal.new.warm_body?
  • モジュールと三角継承
class Animal
end
class Mammal < Animal
  def swimmable?
    false
  end
end
module Swimmable
  def swimmable?
    true
  end
end

class Fish < Animal
  include Swimmable
end

class Dolphin < Mammal
  include Swimmable
end

Fish.new.swimmable?
Mammal.new.swimmable?
Dolphin.new.swimmable?
  • モジュールとは何だろう?

    • クラスのメソッド定義の一部を切り出したもの
    • 便利メソッドを束ねたもの
    • 名前空間
  • インスタンス変数

class Dog
  def initialize(name)
    @name = name
  end

  def info
    "This dog's name is #{@name}"
  end
end

dog = Dog.new("Akubi")
puts dog.info

# こうでもいいかも
class Dog
  attr_accessor :name

  def initialize(name)
    self.name = name
  end

  def info
    "This dog's name is #{name}"
  end
end
  • クラスメソッドの定義
class Dog
  class << self
    def print_info(name)
      dog = new(name)
      puts dog.info
    end
  end
end

演習(1)

  • 以下のメソッドの結果はどういう意味か?
Dolphin.ancestors

演習(2)

  • Rubyの組み込みクラスの継承関係のドキュメントを探して、確認してみよう
  • また、Enumerable Comperable を継承しているクラスは何か確認してみよう

オープンクラス

def fizzbuzz(n)
  (1..n).each do |i|
    out = ""
    if (i % 3).zero?
      out = "Fizz"
    end
    if (i % 5).zero?
      out += "Buzz"
    end
    out = i.to_s if out.empty?
    puts out
  end
end
  • 100.to_fizzbuzz って呼び出したくない?
class Integer
  def to_fizzbuzz
    (1..self).each do |i|
      out = ""
     if (i % 3).zero?
        out = "Fizz"
      end
      if (i % 5).zero?
        out += "Buzz"
      end
      out = i.to_s if out.empty?
      puts out
    end
  end
end

200.to_fizzbuzz

演習(1)

  • Integer#hours を自作しよう

演習(2)

  • エスケープシーケンスについて調べて、 String#to_red を追加しよう

ほんのちょっとだけメタプログラミング

bloc = proc do
  puts reverse
  puts size
  puts chars.shuffle.join
end

bloc.call
#=> NoMethodError!

str = "paperboy"
str.instance_eval &bloc
#=> !!!

演習(1)

  • どういうことか考えるだけ考えてみよう

演習(2)

  • 以下と比較しよう
methods = "chars.shuffle.join"
str = "paperboy"
eval "puts str.#{methods}"

ちょっとだけ実用Ruby

RubyGems

  • Rubyのパッケージマネージャー
  • Rubyの便利プログラムのひとまとまり=gem
$ gem list -rd hashie

*** REMOTE GEMS ***

hashie (2.0.5)
    Authors: Michael Bleigh, Jerry Cheung
    Homepage: https://github.com/intridea/hashie

    Your friendly neighborhood hash toolkit.
  • インストール
$ gem install hahsie
  • 使うには
require "hashie"
options = Hashie::Mash.new(name: "Akubi")
options.name
  • gem以外にも、「標準添付ライブラリ」というものもあるよ
require "uri"
URI.parse "https://lolipop.jp"
  • gemの正体
    • 実は、特定の構成のファイル群をgzipで固めただけのもの
    • 一部はビルドスクリプトも付いている
    • インストール時に展開して特定のディレクトリに配置する

演習(1)

  • インストールしたgemについて、以下の表示を確認しよう
$ gem list -d hashie

演習(2)

RubyGems.org で適当なgemをダウンロードして、展開して中身を見てみよう

Bundler

  • 「プロジェクトでどんなgemを使うか」を管理するためのライブラリ
  • もともとRailsのgem管理システムが進化したもの
source "https://rubygems.org"

gem "hashie"
gem "coderay"
gem "redcarpet"
## brew install libxml2 libxslt
$ cat Gemfile
$ bundle install
require "bundler/setup"
Bundler.require
# sample use coderay
puts CodeRay.scan(<<EOC, :ruby).terminal
def add(some)
  1 + 2 + some
end
EOC
$ bundle exec ruby sample.rb

演習(1)

Gemfile.lock の中身を見てみよう

演習(2)

  • Gemfileのgem "redcarpet" をコメントアウトしたりしなかったりした状態で、以下のスクリプトの実行結果を見てみよう
require "bundler/setup"
require "redcarpet"
p defined?(Redcarpet)

Sinatra で遊んでみよう

$ gem install sinatra
$ ruby -rsinatra -e "get('/') { 'Fastest web development' }"
  • 少しアプリらしくする
Gemfile
app.rb
source "https://rubygems.org"
gem "sinatra"
require "sinatra"

get "/" do
  'Fastest web development'
end
$ bundle exec ruby app.rb

DSLと言う考え方

  • get ~ do でルーティングと処理を表現する
  • get はRubyのメソッドではなく、Sinatraがウェブのルーティングを表現するために追加した専用の言語
  • use, set なども追加される

演習(1)

  • じゃんけんをするウェブアプリケーションを作ってみよう
require "sinatra"

get "/" do
  erb [(1)???]
end

[(2)???] "/result" do
  @choice = [(3)???]
  @op_choice = %w(goo choki paa).sample
  win_to_lose = {
    "goo" => "choki",
    "choki" => "paa",
    "paa" => "goo",
  }
  @result = if win_to_lose[@choice] == @op_choice
    "Won!"
  elsif @choice == @op_choice
    "Draw"
  else
    "Lost..."
  end
  erb :result
end

__END__
@ index
<html>
<h1>じゃんけん?</h1>
<form action='/result' method='post'>
  <select name='choice'>
    <option value='goo'>グー</option>
    <option value='choki'>チョキ</option>
    <option value='paa'>パー</option>
  </select>
<input type='submit' />
</form>
</html>

@ result
<html>
<h1>結果:</h1>
<p><%= [(4)???] %></p>
<p>自分:<%= [(5)???] %> 相手:<%= [(6)???] %></p>
</html>

演習(2)

  • さっきのアプリケーションに、RubyのみでBasic認証の機能を追加するにはどうする?
    • ヒント: Rack Middleware

Ruby情報(日本語)

るりま

るびま

ドットインストール

Ruby Toolbox

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment