5
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

7つの言語 7つの世界 を読む 1

Last updated at Posted at 2014-10-28

あせらず、ちょっとずつ読んでいくつもり。
ケーススタディとかは、答え合わせをさぼったり、がんばりを後回しに保留したりとかする感じで。

Ruby

象徴的。

彼が関心があるのは、プログラマの生産効率の最適化に関心である。

読み進めつつメモ 1日目

・ブロックの概念が設計者のお気に入り
・スレッドを廃止してアクターやその他の高度な並列機能を追加したいとのこと

・まず対話コンソールをつかうといい
・バイトコードにコンパイルする仮想マシンの開発もある
・実行にはかならず値が返ってくる
・文字列リテラルの変数は置換で埋め込まれる

・うわ、Rubyでは数値もオブジェクト
・条件文は行末に書く修飾子もあるのね、処理を書いてから分岐を考える場合には便利なのか
・unlessの方が可読性が良いらしい
・数値の0はtrue評価
・論理演算子は左から評価
・&または|で式全体を実行して比較

・強く型付けされたように振る舞うが、型安全性を破壊することも可能
・動的型付け(関数実行時に型チェックを実行)となっている
・to_iメソッドの例のように、quackメソッドによって、ダックタイピングができる

irb楽しい
実践は省略、乳母とはぎこちなく会話できる感じ
もっとこの時点でいろいろ試してみるべきなのかも知れないがサボって次へ進もうっと
あと、序盤の文章の分からない単語も調べずに進んでいるので後々調べた方が良いかもっと

読み進めつつメモ 2日目

コレクション・シンボル・シンタックス

・順序付きコレクション(配列・ハッシュを含む)は有用な機能

・animals[-2]のような記述はシンタックスシュガーによるもの
・animals[0..2]のような記述はシンタックスシュガーによるものではなく、0..2はRange
つまり、コアシンタックスということなのかな。範囲演算子というらしい。
・[]はArrayクラスのメソッド
・[]と[]=は配列にアクセスするためのシンタックスシュガー

・シンボルは:symbolのようにコロンの識別子をつける
・シンボルは同じ名前の記述であれば一意で物理的に同じオブジェクトを表す
・文字列リテラルはそれが示す文字列が同じでも別オブジェクトであり得る
・関数の引数のブレース()は省略可能
・何でも配列、ハッシュキー、ハッシュ値に保持できるので高度なデータ構造体を作れる

・配列には多くのAPIが用意されている(配列オブジェクトのメソッドのこと?)

コードブロック・yield・クラス・オブジェクト

・コードブロックはRubyの本当の力を発揮させる
・コードブロックは無名関数で、関数やメソッドの引数としても渡せる
・1行のコードブロックはブレースで、複数ならdo/endで囲むのが慣習
・コードブロックの威力の片鱗は下記コードに現れる

test.rb
 animals.each {|a| puts a}

・ん??え??既存のクラスにメソッドを追加できる

test.rb
class Fixnum
  def my_times
    i=self
    while i>0
      i=i-1
      yield
    end
  end
end

・上記、yieldキーワードのタイミングで無名関数が実行されているが、
 関数に引数をとることが明記されていないけどどのタイミングで実行するんだ??

yieldの言語処理系での違いについてググった。
なるほど。

rubyの場合は、C#とPythonと違い、渡されたブロックに値を送り込むというものです。
主従が異なるので、rubyは"逆"と覚えてください。

これは、

block.call

で置き換え可能ってこと??

・メソッドでブロックを引数にとるには&をつける

PHPだと参照の意味だけどRubyのこれは違うのかな。
ちなみに試しに先頭に&をつけないで関数の引数としてブロックを渡したらエラーになった。

test.rb
class Fixnum
    def my_times5 block
        i=self
        while i>0
                i=i-1
                block.call i
        end
    end
end
3.my_times5 {|n|puts "mangy moose #{n}"}
# test.rb:30:in `my_times5': wrong number of arguments (0 for 1) (ArgumentError)

・コードブロックには多くの用途がある

ファイルの各行を処理する、HTTP トランザクション内で処理を実行する、コレクションに対して複雑な演算を実行する

・クラスは全てObjectクラスから派生する
・オブジェクトはクラスから導出される
・クラスのインスタンスはオブジェクトのテンプレートとなる
・クラスのインスタンスはオブジェクトでもある

つまり、 クラス>インスタンス(クラスでありオブジェクト)>オブジェクト ってことかな。
クラスとオブジェクトの線引きはどうなってるんだ。jsのprototype的な何かあるのかな。

・Ruby1.9以降ではObjectのスーパークラスとしてBaseObjectがある

・クラスの初期化ではinitializeが呼ばれる
・インスタンス変数には@をつける
・クラス変数には@@をつける
・インスタンス変数の定義には attr と attr_accessor gaaru

あれ、クラス内メソッドをクラス内から呼び出すときにはthisとかselfとかいう指定の記述はなくていいのか。
スコープの外の関数とどう区別するのかな。優先順位は?スコープの指定も出来る?

モジュール・Mixin

PHPのtraitもそうだけど、モジュールの混ぜ込みの内部処理はどういう処理なのだろう。
そもそもクラスとかってどう処理されるのか。

・モジュールの概念があり、関数と定数の阿智真理で、クラスの一部として混ぜ込むことが出来る

挙動としてはPHPでいうtraitみたいなものかな。
違うかな、違うとするとどう違うのだろう。

モジュール内でもthisとかselfとかの指定の記述はないな。

・混ぜ込むことをMixinとよぶ

このプログラミングスタイルはmixinと呼ばれ、Flavorsで初めて導入され、SmalltalkやPythonなど多くの言語で使われている。

・Mixinしたクラスを継承したサブクラスもスーパークラスのMixinした実装を使うことが出来る
・Rubyで最も重要なmixinとして、EnumerableとComparableがある
・Enumerableをmixinする場合、eachを実装する必要がある
・Comparableをmixinする場合、宇宙船演算子<=>を実装する必要がある

Fixnumの宇宙船演算子の実装はどうなってるのか。

シンボルはなんかいいな。便利そう。
う、いろいろ保留しても二日目が長くて終わらない。。

二日目まとめ

このレベルの抽象化でも少しは優れたプログラミング言語になるが、Rubyの真の秘術が登場するのはまだまだこれからだ。

セルフスタディ

むむ、ちょっと分析的な思考が必要になるとのこと。

探してみよう

  • コードブロックの利点(ファイルアクセス)

    • 概要の振り返り
      • 関数の引数を用意しなくても呼び出せるyieldで(コードブロック以外に無名関数がある?)
      • yieldでの処理受け渡し
    • 可読性の向上
      • ファイルオープンのストリームなど再利用をあまりしない場合には記述箇所が明確化(無名関数の利点)
    • 記述性の向上
      • ブレースで囲むだけでいい
      • ストリームの変換処理などの限定した処理の受け渡しが可能(無名関数の受け渡しの利点)
      • 処理をコードブロック側にゆだねてしまうことで柔軟に記述できる
    • ブロックを使わない場合について
      • 関数を定義したり、その名前空間に気を遣ったりすることがあるかもしれない
      • 関数をトレースすればSDKなどで記述元を追える
      • お約束的・慣習的な共通処理が再利用できる
      • 指定や定義により手続が増えがちになるかも
  • ハッシュと配列の相互変換

    • キャストをつかう
      • 多分ある

        test.rb
         irb(main):147:0> [['3','5']].to_h
         => {"3"=>"5"}
         irb(main):150:0> {3=>"hoge",8=>'b'}.to_a
         => [[3, "hoge"], [8, "b"]]
        
      • キャストの内部処理はどうしてるのか

    • ループを回してクローンする
      • each {}
  • ハッシュの各要素のループ

    • 例にあったTreeクラスの様にコードブロックを使う(再帰ループ)
    • 例にあったEnumerableやComparableをMixinしてallメソッドを活用する
  • 配列で可能なデータ構造体

    • スタック
    • シーケンス

試してみよう

問いの意図するところがいまいちわかってないかも。

  • eachだけを使って出力
test.rb
# ひとまず破壊的です
arr16 = [1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6]
arr4 = [1,2,3,4]

if arr4.length > arr16.length
	arr4.each {|j|i=arr16.shift;puts "#{i} #{j}";}
else
	arr16.each {|j|i=arr4.shift;puts "#{i} #{j}";}
end
  • Enumerableを使って出力

わからんので調べたけど。。多分問題の意味するところを勘違いしてる。

test.rb
(1..8).each_slice(3) {|arr| print "(" + arr.join(",") + ") " }

・Treeクラスを改善する

どうせなので継承についてはさくっとしらべた。
http://www.ruby.or.jp/ja/tech/development/ruby/tutorial/090_class_extension.html

test.rb
class Tree
    attr_accessor :children, :node_name

    def initialize(name, children=[])
        @children = children
        @node_name = name
    end

    def visit_all(&block)
        visit &block
        children.each {|c| c.visit_all &block}
    end

    def visit(&block)
        block.call self
    end
end

ruby_tree = Tree.new("Ruby",[Tree.new("reia"),Tree.new("MacRuby")])
ruby_tree.visit {|node| puts node.node_name}
ruby_tree.visit_all {|node| puts node.node_name}

#  できるだけ既存の構造を残す形にしてみる。できねー。ちゃんといろいろ調べないと無理だな。
#  日が変わってからやりなおしたらできた

quest = {
    'grandpa' => {
        'dad' => {
            'child 1' => [] , 'child 2' => ["3","4"]
        }, 'uncle' => {
            'child 3' => [], 'child 4' => [] 
        }
    }
}

class TreeCustom < Tree

    def visit_all(&block)
        visit &block
		if children.kind_of?(Array)
	        children.each {|value|
	            TreeCustom.new(value).visit_all &block
	        }
        elsif children.kind_of?(Hash)
	        children.each {|key,value|
	            TreeCustom.new(key, value).visit_all &block
	        }
        else
			TreeCustom.new(value).visit &block
        end
    end

    def visit(&block)
        block.call self if self.node_name
    end
end

ruby_tree2 = TreeCustom.new(false, quest.clone)
ruby_tree2.visit {|node| puts node.node_name}
ruby_tree2.visit_all {|node| puts node.node_name}


・grepを実装

grep.rb
if ARGV.length != 2
        puts "wrong number of arguments #{ARGV}"
        exit
end

word = ARGV[0]
filename = ARGV[1]

f = open(filename)
f.each_with_index {|line, key|print (key +1).to_s + ')' + line if line.index(word) != nil}
f.close

以下ブラウザ検索のメモ

irbでも補完

require "irb/completion" 

組み込みコマンドのshell-modeを使うと、プロンプトにカレントディレクトリが表示され、tabキーでディレクトリ名を補完できるようになり、よりファイル操作が簡単になります。

Ruby には Perl に由来する while 修飾子と until 修飾子もあります。 修飾する式が begin…end か否かで 動作が異なるという非常にまぎらわしい意味を持ちます。 過去の遺産を引き継ぐとき以外,使わないのが無難です。 伝統的には C++/Java の do S while (E ); を模倣するために begin…end の特別ルール付きで使われることがありますが (そして,この模倣こそが特別ルールが導入された理由ですが), 前述のとおり loop イテレータと break で十分表現できます。

null/nil の扱いをオブジェクト指向的に考え直す

シンタックスとは

コンピュータ言語における構文規則。プログラミング言語、構文解析など参照。

範囲オブジェクトのクラス。範囲オブジェクトは範囲演算子 .. または ... によって生成されます。.. 演算子によって生成された範囲 オブジェクトは終端を含み、... 演算子によって生成された範囲オブジェ クトは終端を含みません。

5
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?