Scala で素数のリスト

Scalaでエラトステネスの篩を参考に Scala 2.10 向けにアレンジして書いてみた。しかし効率は良くないようで、10000 個くらいの素数を取得しようとするとあっという間に OutOfMemory になる。

object Prime {
  def primes: Stream[Int] = {
    def sieve(xs: Stream[Int]): Stream[Int] =
      xs.head #:: sieve(xs.tail.filter(_ % xs.head != 0))
    sieve(Stream.from(2))
  }

  def main(args: Array[String]): Unit = {
    primes.take(20).foreach { println }
  }
}

的外れなコメント達に突っ込んでみる

今すぐ辞めて欲しい、「Ruby on Rails勉強してます」「CakePHP勉強してます」 – sumyapp

Railsネガキャンですか、と思って読んでみたがとんでもない、ちゃんとした記事で好感が持てた。しかしコメントがあまりに的外れちゃんなのでかいつまんでツッコミを入れようと思う。

結論が勉強してからRailsを使うべきだってことは、今すぐ辞めて欲しいっていうのは釣りってことでいいんですよね?

釣りの意図は私は感じなかった。Rails はとにかく世話焼きが好き過ぎて、初心者でもコマンド一つでデータベースの作成からテーブルの作成、初期データの投入までさくっとできてしまうのであるが、それが危険*1であるということを指摘しているだけである。

そらあんた。高級言語全般そうでんがな。
そういい始めるなら、全部アセンブラで書いてつかあさい。

本人も言っているとおり、言語そのものには一切言及していない。あくまでも framework への言及である。「仕組みを理解せずに使うのは危険だから」と言っていちいちアセンブラから始めてたらかえって学習困難でしょうに。それにこの人は別に Rails を dis ってる訳でもないし「使うな」と言っているわけでもない*2

タクシーの運転手が自動車をつくるのに必要な機械工学や高等数学を
勉強する必要があるかというとそんなことはないですし。

理解が浅いと使ってはいけないってことですか?
テレビの仕組みを知らなければ見てはいけないと思いますか?
DRAMの記憶の仕組みを知らないとPCを使ってはいけないと思いますか?
どうもいまいち何がダメで何がよいのか整理できていないのではないでしょうか。

いずれも比較する対象が間違ってる。ここでいう自動車なりテレビなり DRAM なりはどちらかと言えば「プログラミング言語」に相当する。どの言語を使う人でも、それがどう機械語に変換されるかの仕組みを逐一理解して使ってる人はいないし、そうしなくても使えるように高級言語は発展を遂げてきた。対して framework は、タクシーで言えば車の運転方法みたいなもので、運転の仕方*3がよくわかってないのにタクシーの運転手にはなれないだろう。

ツッコミどころはこんなもんかな。でも私としては Ruby on Rails はやっていて楽しいし、Ruby を積極的に覚えたい人には一つの framework として Ruby on Rails はやはり知っていてもらいたいと思うので、これからも Ruby on Rails 関連の記事は書き続けます。

*1:仕組みを理解できないままええわええわでやっていると結局は身に付かないと言う意味で。

*2:正確には、初心者に対しては「安易に使うな」とは言っているが、そうでない人にまで「使うな」とは言ってない。

*3:何故ハンドルを回すと車は曲がるのか、何故ブレーキを踏んだら車は減速→停止するのか、etc...

中間テーブルを用いた多対多の関係(その 5)

前回からの続きです。モデル同士のアソシエーションを定義します。

class Customer < ActiveRecord::Base
  has_many :sales
  has_many :products, :through => :sales
end
class Product < ActiveRecord::Base
  has_many :sales
end
class Employee < ActiveRecord::Base
  has_and_belongs_to_many :branches
  belongs_to :manager, :class_name => 'Employee', :foreign_key => 'mgr_id'
  has_many :assistants, :class_name => 'Employee', :foreign_key => 'mgr_id'
  has_many :sales
  scope :belongs, lambda { |b| joins(:branches).where(:branches => { :name => b }) }
end
class Branch < ActiveRecord::Base
  has_and_belongs_to_many :employees
end
class Sale < ActiveRecord::Base
  belongs_to :product
  belongs_to :employee
  belongs_to :customer
end

中間テーブルの話からは逸れますが、Employee クラスを見ていただいてわかるとおり、アソシエーションはテーブル名と一致しないものも作れます。その場合は対応するモデルと結合に利用する外部キーを指定する必要があります。

EmployeeBranch の関係は以前にやったのと同じ、外部キーしか持たない中間テーブルを利用した多対多の関係です。

注目すべきは CustomerProduct の関係です。CustomerSale は一対多の関係にありますが、ProductSale が一対多の関係にあることを利用して CustomerProduct の多対多の関係を持たせています。その場合は has_many を使いますが

has_many :products, :through => :sales

のように経由する中間テーブルを指定する必要があります。また、中間テーブルのデータとなるモデルに対するアソシエーションも併せて定義しておく必要があります。

続きを読む

中間テーブルを用いた多対多の関係(その 4)

次に、中間テーブルが外部キー以外のデータを持つ場合について考えます。使用するアプリは

  • 顧客(customer)
  • 商品(product)
  • 従業員(employee)
  • 支店(branch)
  • 売上(sale)

のデータを持っているとします。

モデルの作成から始めましょう。

rails g model customer name:string phone:string --timestamps=false
rails g model product name:string group_name:string purchase_price:integer wholesale_price:integer --timestamps=false
rails g model employee name:string phonetic:string mgr_id:integer birthday:date sex:integer --timestamps=false
rails g model sale slip_no:integer line_no:integer processing_date:date product_id:integer employee_id:integer customer_id:integer quantity:integer --timestamps=false
rails g model branch name:string --timestamps=false
rails g migration CreateBranchesEmployees employee_id:integer branch_id:integer

最後は従業員(employee)と支店(branch)を関連付ける中間テーブルの作成のためのマイグレーションファイルを作成しています。主キーが作成されないように編集をしておきましょう。

class CreateBranchesEmployees < ActiveRecord::Migration
  def change
    create_table :branches_employees, :id => false do |t|
      t.integer :employee_id, :null => false
      t.integer :branch_id, :null => false
    end
  end
end
続きを読む