necromancy 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rst +8 -8
- data/VERSION +1 -1
- data/examples/fizzbuzz.rb +1 -1
- data/lib/necromancy/control/alternative.rb +28 -2
- data/lib/necromancy/control/applicative.rb +35 -0
- data/lib/necromancy/control/arrow.rb +16 -0
- data/lib/necromancy/control/category.rb +18 -0
- data/lib/necromancy/control.rb +34 -9
- data/lib/necromancy/version.rb +1 -1
- data/lib/necromancy.rb +7 -0
- data/spec/examples/category_spec.rb +10 -0
- metadata +1 -1
data/README.rst
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
Necromancy
|
1
|
+
屍術/Necromancy
|
2
2
|
================================================================================
|
3
3
|
|
4
|
-
Necromancy conjures up the functional code.
|
4
|
+
*屍術/Necromancy* conjures up the functional code.
|
5
5
|
|
6
6
|
.. code:: ruby
|
7
7
|
|
@@ -20,7 +20,7 @@ Features
|
|
20
20
|
Function composition
|
21
21
|
________________________________________________________________________________
|
22
22
|
|
23
|
-
Every messages to instance of
|
23
|
+
Every messages to instance of ``Necromancy`` are function composition
|
24
24
|
by default. that is left-to-right composition.
|
25
25
|
|
26
26
|
.. code:: ruby
|
@@ -53,16 +53,16 @@ No core extensions.
|
|
53
53
|
________________________________________________________________________________
|
54
54
|
|
55
55
|
Open classes is evil unless that is need really!
|
56
|
-
Necromancy isn't. All methods are defining at local modules,
|
57
|
-
and you can call their methods by sending some messages to a Necromancy object.
|
56
|
+
*屍術/Necromancy* isn't. All methods are defining at local modules,
|
57
|
+
and you can call their methods by sending some messages to a ``Necromancy`` object.
|
58
58
|
|
59
59
|
Examples
|
60
60
|
--------------------------------------------------------------------------------
|
61
61
|
|
62
|
-
Simple
|
62
|
+
Simple function composition
|
63
63
|
________________________________________________________________________________
|
64
64
|
|
65
|
-
First, you create a
|
65
|
+
First, you create a ``Necromancy`` object.
|
66
66
|
it is immutable, you can save it to any variable you like.
|
67
67
|
for example, that is constant, global varibale, instance variable, class variable, local variable, etc.
|
68
68
|
|
@@ -76,7 +76,7 @@ After, you send some message to N when you need to write a simple block.
|
|
76
76
|
|
77
77
|
(1..5).map &N ** 2 # => [1, 4, 9, 16, 25]
|
78
78
|
|
79
|
-
Function
|
79
|
+
Function composition
|
80
80
|
________________________________________________________________________________
|
81
81
|
|
82
82
|
.. code:: ruby
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.2
|
data/examples/fizzbuzz.rb
CHANGED
@@ -8,18 +8,44 @@ module Necromancy
|
|
8
8
|
|
9
9
|
include Control::Applicative
|
10
10
|
|
11
|
+
# Tests whether the result is empty or not.
|
12
|
+
# If it is empty, {#empty?} returns the true, otherwise that returns the false.
|
13
|
+
# By default, {#empty?} returns the true, if it is nil or false.
|
11
14
|
def empty?(x, *xs)
|
12
15
|
not x
|
13
16
|
end
|
14
17
|
|
15
|
-
|
18
|
+
:empty?.tap(&method(:protected))
|
19
|
+
# protected :empty?
|
16
20
|
|
17
|
-
|
21
|
+
# Applies the result of the callable into self unless that result is empty.
|
22
|
+
# @see #empty?
|
23
|
+
# @note self :: a -> b -> c
|
24
|
+
# @param [Object] callable a -> b
|
25
|
+
# @return [Necromancy] a -> c
|
26
|
+
# @example
|
27
|
+
# require 'necromancy'
|
28
|
+
# N = Necromancy.Alternative.new
|
29
|
+
# f = lambda(&N.+ * N) # == ->(o) { :+.to_proc.(o,o) if o }
|
30
|
+
# f.(nil) # => nil
|
31
|
+
# f.("foo") # => "foofoo"
|
32
|
+
def *(callable)
|
18
33
|
str = make_evaluable_string(callable)
|
19
34
|
necromancy = "self.empty?(*(xs = (#{str}))) ? xs : (args.concat(xs); #{@necromancy})"
|
20
35
|
self.class.new(necromancy, @references.dup)
|
21
36
|
end
|
22
37
|
|
38
|
+
# Evaluates the callable, unless result of self is empty. otherwise that returns result of self.
|
39
|
+
# @see #empty?
|
40
|
+
# @note self :: a -> b
|
41
|
+
# @param [Object] callable a -> b
|
42
|
+
# @return [Necromancy] a -> b
|
43
|
+
# @example
|
44
|
+
# require 'necromancy'
|
45
|
+
# N = Necromancy.Alternative.new
|
46
|
+
# f = lambda(&N | ->(o){"foo"}) # == ->(o){ o ? o : "foo" }
|
47
|
+
# f.(nil) # => "foo"
|
48
|
+
# f.("bar") # => "var"
|
23
49
|
def |(callable)
|
24
50
|
str = make_evaluable_string(callable)
|
25
51
|
|
@@ -5,20 +5,55 @@ module Necromancy
|
|
5
5
|
|
6
6
|
module Control::Applicative; extend Control
|
7
7
|
|
8
|
+
# @note self :: a -> b -> c
|
9
|
+
# @param [Object] callable a -> b
|
10
|
+
# @return [Necromancy] a -> c
|
11
|
+
# @example
|
12
|
+
# require 'necromancy'
|
13
|
+
# N = Necromancy.Applicative.new
|
14
|
+
# f = lambda(&N.+ * N) # == ->(o) {o + o}
|
15
|
+
# f.(42) # => 84
|
8
16
|
def *(callable)
|
9
17
|
str = make_evaluable_string(callable)
|
10
18
|
self.class.new("args.concat((#{str})); #{@necromancy}", @references.dup)
|
11
19
|
end
|
12
20
|
|
21
|
+
# A variant of {#*} with the arguments reversed.
|
22
|
+
# @note self :: a -> b
|
23
|
+
# @param [Object] callable a -> b -> c
|
24
|
+
# @return [Necromancy] a -> c
|
25
|
+
# @example
|
26
|
+
# require 'necromancy'
|
27
|
+
# N = Necromancy.Applicative.new
|
28
|
+
# f = lambda(&N ** :+) # == ->(o) {o + o}
|
29
|
+
# f.(42) # => 84
|
13
30
|
def **(callable)
|
14
31
|
str = make_evaluable_string(callable)
|
15
32
|
self.class.new(str, @references.dup).__Applicative_Astarisk(self)
|
16
33
|
end
|
17
34
|
|
35
|
+
# Sequence actions, discarding the value of the callable.
|
36
|
+
# @note self :: a -> b
|
37
|
+
# @param [Object] callable a -> _
|
38
|
+
# @return [Necromancy] a -> b
|
39
|
+
# @example
|
40
|
+
# require 'necromancy'
|
41
|
+
# N = Necromancy.Applicative.new
|
42
|
+
# f = lambda(&N.succ << N.pred) # == ->(o) {o.pred; o.succ}
|
43
|
+
# f.(42) # => 43
|
18
44
|
def <<(callable)
|
19
45
|
self.class.new("args.pop; #{@necromancy}", @references.dup).__Applicative_Astarisk(callable)
|
20
46
|
end
|
21
47
|
|
48
|
+
# Sequence actions, discarding the value of self.
|
49
|
+
# @note self :: a -> _
|
50
|
+
# @param [Object] callable a -> b
|
51
|
+
# @return [Necromancy] a -> b
|
52
|
+
# @example
|
53
|
+
# require 'necromancy'
|
54
|
+
# N = Necromancy.Applicative.new
|
55
|
+
# f = lambda(&N.succ >> N.pred) # == ->(o) {o.succ; o.pred}
|
56
|
+
# f.(42) # => 41
|
22
57
|
def >>(callable)
|
23
58
|
str = make_evaluable_string(callable)
|
24
59
|
self.class.new("args.pop; #{str}", @references.dup).__Applicative_Astarisk(self)
|
@@ -8,12 +8,28 @@ module Necromancy
|
|
8
8
|
|
9
9
|
include Control::Category
|
10
10
|
|
11
|
+
# @note self :: a -> b
|
12
|
+
# @param [Object] callable a -> b'
|
13
|
+
# @return [Necromancy] a -> (b, b')
|
14
|
+
# @example
|
15
|
+
# require 'necromancy'
|
16
|
+
# N = Necromancy.Arrow.new
|
17
|
+
# f = lambda(&N.upcase & :capitalize & :reverse) # == ->(o) { [o.upcase, o.capitalize, o.reverse] }
|
18
|
+
# f.("foo") # => ["FOO", "Foo", "oof"]
|
11
19
|
def &(callable)
|
12
20
|
str = make_evaluable_string(callable)
|
13
21
|
necromancy = "(#{@necromancy}) + (#{str})"
|
14
22
|
self.class.new(necromancy, @references.dup)
|
15
23
|
end
|
16
24
|
|
25
|
+
# @note self :: a -> b
|
26
|
+
# @param [Object] callable a' -> b'
|
27
|
+
# @return [Necromancy] (a, a') -> (b, b')
|
28
|
+
# @example
|
29
|
+
# require 'necromancy'
|
30
|
+
# N = Necromancy.Arrow.new
|
31
|
+
# f = lambda(&N.to_sym * N.to_f) # == ->(a, b) { [a.to_sym, b.to_f] }
|
32
|
+
# f.("x", 42) # => [:x, 42.0]
|
17
33
|
def *(callable)
|
18
34
|
str = make_evaluable_string(callable)
|
19
35
|
necromancy = "stack << [] << args; args = stack[-1][0..-2]; stack[-2].concat((#{@necromancy})); args = [stack[-1][-1]]; stack[-2].concat((#{str})); args = stack.pop; stack.pop"
|
@@ -5,12 +5,30 @@ module Necromancy
|
|
5
5
|
|
6
6
|
module Control::Category; extend Control
|
7
7
|
|
8
|
+
# Left-to-right composition.
|
9
|
+
# @note self :: a -> b
|
10
|
+
# @param [Object] callable b -> c
|
11
|
+
# @return [Necromancy] a -> c
|
12
|
+
# @example
|
13
|
+
# require 'necromancy'
|
14
|
+
# N = Necromancy.Category.new
|
15
|
+
# f = lambda(&N.to_i > N * 2) # == ->(o) { o.to_i * 2 }
|
16
|
+
# f.('42') # => 84
|
8
17
|
def >(callable)
|
9
18
|
str = make_evaluable_string(callable)
|
10
19
|
necromancy = "args = (#{@necromancy}); #{str}"
|
11
20
|
self.class.new(necromancy, @references.dup)
|
12
21
|
end
|
13
22
|
|
23
|
+
# Right-to-left composition
|
24
|
+
# @note self :: b -> c
|
25
|
+
# @param [Object] callable a -> b
|
26
|
+
# @return [Necromancy] a -> c
|
27
|
+
# @example
|
28
|
+
# require 'necromancy'
|
29
|
+
# N = Necromancy.Category.new
|
30
|
+
# f = lambda(&N.to_i < N * 2) # == ->(o) { (o * 2).to_i }
|
31
|
+
# f.('42') # => 4242
|
14
32
|
def <(callable)
|
15
33
|
str = make_evaluable_string(callable)
|
16
34
|
necromancy = "args = (#{str}); #{@necromancy}"
|
data/lib/necromancy/control.rb
CHANGED
@@ -2,6 +2,8 @@ module Necromancy
|
|
2
2
|
|
3
3
|
module Control
|
4
4
|
|
5
|
+
# Creates a {Necromancy::Necromancy} object including the {Necromancy::Control}.
|
6
|
+
# @return [Necromancy]
|
5
7
|
def new
|
6
8
|
mod = self
|
7
9
|
Class.new(::Necromancy::Necromancy) { include mod }.new
|
@@ -14,6 +16,7 @@ module Necromancy
|
|
14
16
|
|
15
17
|
private :branch
|
16
18
|
|
19
|
+
# @deprecated
|
17
20
|
def call(*targets)
|
18
21
|
warn <<EOF
|
19
22
|
Necromancy.Hoge.() deprecated.
|
@@ -22,6 +25,7 @@ EOF
|
|
22
25
|
branch { protected *instance_methods }[*targets]
|
23
26
|
end
|
24
27
|
|
28
|
+
# @deprecated
|
25
29
|
def using(*targets)
|
26
30
|
warn <<EOF
|
27
31
|
Necromancy.Hoge.using() deprecated.
|
@@ -30,7 +34,21 @@ EOF
|
|
30
34
|
self[*targets]
|
31
35
|
end
|
32
36
|
|
33
|
-
|
37
|
+
# Reveals some methods and Creates some aliases.
|
38
|
+
# @param [Symbol] target Reveals a method of the symbol.
|
39
|
+
# @param [Hash] target Hides all methods of each key and creates aliases from each value to each key.
|
40
|
+
# @param [Array] targets A list of Symbol or Hash that will be processing as target.
|
41
|
+
# @return [Control] Processed new {Necromancy::Control} object.
|
42
|
+
# @example
|
43
|
+
# require 'necromancy'
|
44
|
+
# N = Necromancy.Alternative[:<< => :if,
|
45
|
+
# :>> => :then,
|
46
|
+
# :| => :else].new
|
47
|
+
# puts (1..100).map &( (N%15).zero? .then(proc{"FizzBuzz"}) .else \
|
48
|
+
# (N%3).zero? .then(proc{"Fizz"}) .else \
|
49
|
+
# (N%5).zero? .then(proc{"Buzz"}) .else N )
|
50
|
+
def [](target, *targets)
|
51
|
+
targets.unshift(target)
|
34
52
|
names = targets.select { |t| t.is_a? Symbol }
|
35
53
|
aliases = targets.select { |t| t.is_a? Hash }.inject(:merge) || {}
|
36
54
|
branch do
|
@@ -43,22 +61,29 @@ EOF
|
|
43
61
|
end
|
44
62
|
end
|
45
63
|
|
46
|
-
|
64
|
+
# Hides some methods.
|
65
|
+
# @param [Symbol] name Hides a method of the name.
|
66
|
+
# @param [Array] names A list of a Symbol that will be processing as name.
|
67
|
+
# @return [Control] Processed new {Necromancy::Control} object.
|
68
|
+
# @example
|
69
|
+
# require 'necromancy'
|
70
|
+
# N = Necromancy.Alternative.hiding(:*, :**).new
|
71
|
+
# ary = [1, nil, 2, nil, 3]
|
72
|
+
# ary.map &(N | proc{0}) * 10 # => [10, 0, 20, 0, 3]
|
73
|
+
def hiding(name, *names)
|
74
|
+
names.unshift(name)
|
47
75
|
branch { protected *names }
|
48
76
|
end
|
49
77
|
|
50
|
-
def
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
78
|
+
def self.extended(mod)
|
79
|
+
return unless mod.name and mod.name.start_with? self.name
|
80
|
+
mthname = mod.name.sub("#{self.name}::", '')
|
81
|
+
define_method mthname do |*args, &block|
|
55
82
|
if args.empty?
|
56
83
|
branch { include mod }
|
57
84
|
else
|
58
85
|
branch { include mod; protected *mod.instance_methods }[*args, &block]
|
59
86
|
end
|
60
|
-
else
|
61
|
-
super
|
62
87
|
end
|
63
88
|
end
|
64
89
|
end
|
data/lib/necromancy/version.rb
CHANGED
data/lib/necromancy.rb
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
# @example
|
2
|
+
# require 'necromancy'
|
3
|
+
# N = Necromancy.Alternative(:>>, :|).new
|
4
|
+
# puts (1..100).map &(N%15).zero? >> proc{"FizzBuzz"} |
|
5
|
+
# (N%3).zero? >> proc{"Fizz"} |
|
6
|
+
# (N%5).zero? >> proc{"Buzz"} |
|
7
|
+
# N
|
1
8
|
module Necromancy
|
2
9
|
|
3
10
|
require 'necromancy/version'
|
@@ -9,4 +9,14 @@ describe Necromancy::Control::Category do
|
|
9
9
|
%w(0 1 2).map(&l.to_i > "foo".method(:[])).
|
10
10
|
should == %w(0 1 2).map {|x| "foo"[x.to_i] }
|
11
11
|
end
|
12
|
+
|
13
|
+
example do
|
14
|
+
lambda(&l.to_i > l * 2).('42').
|
15
|
+
should == '42'.to_i * 2
|
16
|
+
end
|
17
|
+
|
18
|
+
example do
|
19
|
+
lambda(&l.to_i < l * 2).('42').
|
20
|
+
should == ('42' * 2).to_i
|
21
|
+
end
|
12
22
|
end
|