case_class 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +5 -0
- data/.gitignore +21 -0
- data/README +28 -0
- data/Rakefile +52 -0
- data/VERSION +1 -0
- data/examples/example.rb +13 -0
- data/examples/expr.rb +19 -0
- data/examples/rbtree.rb +85 -0
- data/lib/case_class.rb +47 -0
- data/test/helper.rb +9 -0
- data/test/test_case_class.rb +22 -0
- metadata +78 -0
data/.document
ADDED
data/.gitignore
ADDED
data/README
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
= case_class
|
2
|
+
|
3
|
+
Scala-like case classes for Ruby
|
4
|
+
|
5
|
+
== SYNOPSIS:
|
6
|
+
|
7
|
+
require "case_class"
|
8
|
+
include CaseClass
|
9
|
+
|
10
|
+
Number = Case[:n]
|
11
|
+
Sum = Case[:e1, :e2]
|
12
|
+
|
13
|
+
# evaluation with pattern matching
|
14
|
+
def eval(n)
|
15
|
+
case n
|
16
|
+
when Sum[e1 = _, e2 = _] then eval(e1) + eval(e2)
|
17
|
+
when Number[n = _] then n
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# (1 + 2) + (3 + 4) => 10
|
22
|
+
expr = Sum[Sum[Number[1], Number[2]], Sum[Number[3], Number[4]]]
|
23
|
+
p eval(expr) #=> 10
|
24
|
+
|
25
|
+
== LICENSE:
|
26
|
+
|
27
|
+
Copyright:: Yusuke Endoh <mame@tsg.ne.jp>
|
28
|
+
License:: Ruby's
|
data/Rakefile
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "case_class"
|
8
|
+
gem.summary = %Q{Scala-like case classes for Ruby}
|
9
|
+
gem.description = %Q{This provides Scala-like case classes for Ruby. You can enjoy pattern matching with place holders.}
|
10
|
+
gem.email = "mame@tsg.ne.jp"
|
11
|
+
gem.homepage = "http://github.com/mame/case_class"
|
12
|
+
gem.authors = ["Yusuke Endoh"]
|
13
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
14
|
+
end
|
15
|
+
Jeweler::GemcutterTasks.new
|
16
|
+
rescue LoadError
|
17
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
18
|
+
end
|
19
|
+
|
20
|
+
require 'rake/testtask'
|
21
|
+
Rake::TestTask.new(:test) do |test|
|
22
|
+
test.libs << 'lib' << 'test'
|
23
|
+
test.pattern = 'test/**/test_*.rb'
|
24
|
+
test.verbose = true
|
25
|
+
end
|
26
|
+
|
27
|
+
begin
|
28
|
+
require 'rcov/rcovtask'
|
29
|
+
Rcov::RcovTask.new do |test|
|
30
|
+
test.libs << 'test'
|
31
|
+
test.pattern = 'test/**/test_*.rb'
|
32
|
+
test.verbose = true
|
33
|
+
end
|
34
|
+
rescue LoadError
|
35
|
+
task :rcov do
|
36
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
task :test => :check_dependencies
|
41
|
+
|
42
|
+
task :default => :test
|
43
|
+
|
44
|
+
require 'rake/rdoctask'
|
45
|
+
Rake::RDocTask.new do |rdoc|
|
46
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
47
|
+
|
48
|
+
rdoc.rdoc_dir = 'rdoc'
|
49
|
+
rdoc.title = "case_class #{version}"
|
50
|
+
rdoc.rdoc_files.include('README*')
|
51
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
52
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.0.0
|
data/examples/example.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require "case_class"
|
2
|
+
include CaseClass
|
3
|
+
|
4
|
+
# create placeholder (a.k.a. promise or future)
|
5
|
+
x = _
|
6
|
+
a = [1, x, 2, x, 3, x]
|
7
|
+
|
8
|
+
p a #=> [1, _promise_, 2, _promise_, 3, _promise_]
|
9
|
+
|
10
|
+
# fulfill promise by 42 (not assign)
|
11
|
+
x === 42
|
12
|
+
|
13
|
+
p a #=> [1, 42, 2, 42, 3, 42]
|
data/examples/expr.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require "case_class"
|
2
|
+
include CaseClass
|
3
|
+
|
4
|
+
# data Expr = Number Int | Sum Expr Expr
|
5
|
+
|
6
|
+
Number = Case[:n]
|
7
|
+
Sum = Case[:e1, :e2]
|
8
|
+
|
9
|
+
# evaluation with pattern matching
|
10
|
+
def eval(n)
|
11
|
+
case n
|
12
|
+
when Sum[e1 = _, e2 = _] then eval(e1) + eval(e2)
|
13
|
+
when Number[n = _] then n
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# (1 + 2) + (3 + 4)
|
18
|
+
expr = Sum[Sum[Number[1], Number[2]], Sum[Number[3], Number[4]]]
|
19
|
+
p eval(expr) #=> 10
|
data/examples/rbtree.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
require "case_class"
|
2
|
+
include CaseClass
|
3
|
+
|
4
|
+
# translated from http://www.cs.kent.ac.uk/people/staff/smk/redblack/
|
5
|
+
module RedBlackTree
|
6
|
+
# data RB a = E | T Color (RB a) a (RB a)
|
7
|
+
E = Case[]
|
8
|
+
T = Case[:c, :l, :v, :r]
|
9
|
+
|
10
|
+
def insert(x, t)
|
11
|
+
T[_,a=_,z=_,b=_] === insert0(x, t)
|
12
|
+
T[:B,a,z,b]
|
13
|
+
end
|
14
|
+
|
15
|
+
def insert0(x, t)
|
16
|
+
case t
|
17
|
+
when E; T[:R,E,x,E]
|
18
|
+
when T[:B,a=_,y=_,b=_]
|
19
|
+
case
|
20
|
+
when x<y; balance(insert0(x, a), y, b)
|
21
|
+
when x>y; balance(a, y, insert0(x, b))
|
22
|
+
else t
|
23
|
+
end
|
24
|
+
when T[:R,a=_,y=_,b=_]
|
25
|
+
case
|
26
|
+
when x<y; T[:R, insert0(x, a), y, b]
|
27
|
+
when x>y; T[:R, a, y, insert0(x, b)]
|
28
|
+
else t
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def member(x, t)
|
34
|
+
case t
|
35
|
+
when T[_, a=_, y=_, b=_]
|
36
|
+
case
|
37
|
+
when x<y; member(x, a)
|
38
|
+
when x>y; member(x, b)
|
39
|
+
else true
|
40
|
+
end
|
41
|
+
else
|
42
|
+
false
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def balance(l, v, r)
|
47
|
+
case [l, v, r]
|
48
|
+
when [T[:R,T[:R,a=_,x=_,b=_],y=_,c=_],z=_,d=_]; T[:R,T[:B,a,x,b],y,T[:B,c,z,d]]
|
49
|
+
when [T[:R,a=_,x=_,T[:R,b=_,y=_,c=_]],z=_,d=_]; T[:R,T[:B,a,x,b],y,T[:B,c,z,d]]
|
50
|
+
when [T[:R,a=_,x=_,b=_],y=_,T[:R,c=_,z=_,d=_]]; T[:R,T[:B,a,x,b],y,T[:B,c,z,d]]
|
51
|
+
when [a=_,x=_,T[:R,T[:R,b=_,y=_,c=_],z=_,d=_]]; T[:R,T[:B,a,x,b],y,T[:B,c,z,d]]
|
52
|
+
when [a=_,x=_,T[:R,b=_,y=_,T[:R,c=_,z=_,d=_]]]; T[:R,T[:B,a,x,b],y,T[:B,c,z,d]]
|
53
|
+
when [a=_,x=_,b=_]; T[:B,a,x,b]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# # balance with no pattern matching
|
58
|
+
# def balance(l, v, r)
|
59
|
+
# case
|
60
|
+
# when T===l && l.c===:R && T===l.l && l.l.c===:R
|
61
|
+
# T[:R,T[:B,l.l.l,l.l.v,l.l.r],l.v,T[:B,l.r,v,r]]
|
62
|
+
# when T===l && l.c===:R && T===l.r && l.r.c===:R
|
63
|
+
# T[:R,T[:B,l.l,l.v,l.r.l],l.r.v,T[:B,l.r.r,v,r]]
|
64
|
+
# when T===l && l.c===:R && T===r && r .c===:R
|
65
|
+
# T[:R,T[:B,l.l,l.v,l.r],v,T[:B,r.l,r.v,r.r]]
|
66
|
+
# when T===r && r.c===:R && T===r.l && r.l.c===:R
|
67
|
+
# T[:R,T[:B,l,v,r.l.l],r.l.v,T[:B,r.l.r,r.v,r.r]]
|
68
|
+
# when T===r && r.c===:R && T===r.r && r.r.c===:R
|
69
|
+
# T[:R,T[:B,l,v,r.l],r.v,T[:B,r.r.l,r.r.v,r.r.r]]
|
70
|
+
# else T[:B,l,v,r]
|
71
|
+
# end
|
72
|
+
# end
|
73
|
+
end
|
74
|
+
|
75
|
+
include RedBlackTree
|
76
|
+
|
77
|
+
tree = E
|
78
|
+
(1..10).to_a.shuffle.each do |x|
|
79
|
+
tree = insert(x, tree)
|
80
|
+
end
|
81
|
+
|
82
|
+
p member( 5, tree) #=> true
|
83
|
+
p member(11, tree) #=> false
|
84
|
+
p member( 0, tree) #=> false
|
85
|
+
p tree
|
data/lib/case_class.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
require "delegate"
|
2
|
+
|
3
|
+
module CaseClass
|
4
|
+
class PlaceHolder < SimpleDelegator
|
5
|
+
def initialize
|
6
|
+
class << self
|
7
|
+
def ==(obj)
|
8
|
+
obj = obj.__getobj__ while PlaceHolder === obj
|
9
|
+
class << self
|
10
|
+
remove_method(:==)
|
11
|
+
remove_method(:===)
|
12
|
+
remove_method(:inspect)
|
13
|
+
end
|
14
|
+
__setobj__(obj)
|
15
|
+
true
|
16
|
+
end
|
17
|
+
|
18
|
+
alias === ==
|
19
|
+
|
20
|
+
def inspect
|
21
|
+
"_promise_"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
super(nil)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class Case < Struct
|
30
|
+
def ===(obj)
|
31
|
+
obj = obj.__getobj__ while PlaceHolder === obj
|
32
|
+
super
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.[](*ary)
|
36
|
+
if ary.size >= 1
|
37
|
+
new(*ary)
|
38
|
+
else
|
39
|
+
new(:dummy)[nil]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def _
|
45
|
+
PlaceHolder.new
|
46
|
+
end
|
47
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
class TestCaseClass < Test::Unit::TestCase
|
4
|
+
def test_placeholder
|
5
|
+
x = CaseClass::PlaceHolder.new
|
6
|
+
assert_equal("_promise_", x.inspect)
|
7
|
+
assert_equal(true, x === 42)
|
8
|
+
assert_equal("42", x.inspect)
|
9
|
+
end
|
10
|
+
|
11
|
+
Foo = CaseClass::Case[:x, :y, :z]
|
12
|
+
def test_case
|
13
|
+
foo = Foo[1, 2, 3]
|
14
|
+
x = CaseClass::PlaceHolder.new
|
15
|
+
y = CaseClass::PlaceHolder.new
|
16
|
+
z = CaseClass::PlaceHolder.new
|
17
|
+
Foo[x, y, z] === Foo[1, 2, 3]
|
18
|
+
assert_equal(1, x)
|
19
|
+
assert_equal(2, y)
|
20
|
+
assert_equal(3, z)
|
21
|
+
end
|
22
|
+
end
|
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: case_class
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 1
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
version: 1.0.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Yusuke Endoh
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-05-22 00:00:00 +09:00
|
18
|
+
default_executable:
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description: This provides Scala-like case classes for Ruby. You can enjoy pattern matching with place holders.
|
22
|
+
email: mame@tsg.ne.jp
|
23
|
+
executables: []
|
24
|
+
|
25
|
+
extensions: []
|
26
|
+
|
27
|
+
extra_rdoc_files:
|
28
|
+
- README
|
29
|
+
files:
|
30
|
+
- .document
|
31
|
+
- .gitignore
|
32
|
+
- README
|
33
|
+
- Rakefile
|
34
|
+
- VERSION
|
35
|
+
- examples/example.rb
|
36
|
+
- examples/expr.rb
|
37
|
+
- examples/rbtree.rb
|
38
|
+
- lib/case_class.rb
|
39
|
+
- test/helper.rb
|
40
|
+
- test/test_case_class.rb
|
41
|
+
has_rdoc: true
|
42
|
+
homepage: http://github.com/mame/case_class
|
43
|
+
licenses: []
|
44
|
+
|
45
|
+
post_install_message:
|
46
|
+
rdoc_options:
|
47
|
+
- --charset=UTF-8
|
48
|
+
require_paths:
|
49
|
+
- lib
|
50
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
segments:
|
56
|
+
- 0
|
57
|
+
version: "0"
|
58
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
59
|
+
none: false
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
segments:
|
64
|
+
- 0
|
65
|
+
version: "0"
|
66
|
+
requirements: []
|
67
|
+
|
68
|
+
rubyforge_project:
|
69
|
+
rubygems_version: 1.3.7
|
70
|
+
signing_key:
|
71
|
+
specification_version: 3
|
72
|
+
summary: Scala-like case classes for Ruby
|
73
|
+
test_files:
|
74
|
+
- test/helper.rb
|
75
|
+
- test/test_case_class.rb
|
76
|
+
- examples/rbtree.rb
|
77
|
+
- examples/expr.rb
|
78
|
+
- examples/example.rb
|