ludy 0.0.9 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +88 -57
- data/Manifest.txt +96 -0
- data/NOTICE +10 -23
- data/README +173 -10
- data/Rakefile +33 -0
- data/TODO +5 -0
- data/bin/ludy +11 -0
- data/lib/ludy/all.rb +3 -0
- data/lib/ludy/array/body.rb +9 -0
- data/lib/ludy/array/combine.rb +16 -0
- data/lib/ludy/array/combos.rb +23 -0
- data/lib/ludy/array/filter.rb +4 -0
- data/lib/ludy/array/foldl.rb +5 -0
- data/lib/ludy/array/foldr.rb +8 -0
- data/lib/ludy/array/reverse_map.rb +7 -0
- data/lib/ludy/array/rotate.rb +22 -0
- data/lib/ludy/array.rb +3 -0
- data/lib/ludy/blackhole.rb +17 -0
- data/lib/ludy/class/undef_all_methods.rb +9 -0
- data/lib/ludy/class.rb +3 -0
- data/lib/ludy/deprecated/aspect.rb +26 -0
- data/lib/ludy/deprecated/callstack.rb +24 -0
- data/lib/ludy/deprecated/curry.rb +29 -0
- data/lib/ludy/deprecated/rambda.rb +23 -0
- data/lib/ludy/deprecated/this.rb +14 -0
- data/lib/ludy/deprecated/untranspose.rb +12 -0
- data/lib/ludy/deprecated/unzip.rb +7 -0
- data/lib/ludy/{dice.rb → dices.rb} +18 -22
- data/lib/ludy/kernel/defun.rb +10 -0
- data/lib/ludy/kernel/ergo.rb +16 -0
- data/lib/ludy/kernel/id.rb +6 -0
- data/lib/ludy/kernel/if_else.rb +14 -0
- data/lib/ludy/kernel/m.rb +5 -0
- data/lib/ludy/kernel/public_send.rb +13 -0
- data/lib/ludy/kernel/singleton_method.rb +13 -0
- data/lib/ludy/kernel/tap.rb +10 -0
- data/lib/ludy/kernel.rb +3 -0
- data/lib/ludy/lazy.rb +9 -16
- data/lib/ludy/message_dispatcher.rb +58 -0
- data/lib/ludy/pattern_matcher.rb +41 -0
- data/lib/ludy/proc/bind.rb +21 -0
- data/lib/ludy/proc/chain.rb +17 -0
- data/lib/ludy/proc/compose.rb +9 -0
- data/lib/ludy/proc/curry.rb +39 -0
- data/lib/ludy/proc.rb +3 -0
- data/lib/ludy/symbol/curry.rb +10 -0
- data/lib/ludy/symbol/to_msg.rb +10 -0
- data/lib/ludy/symbol/to_proc.rb +7 -0
- data/lib/ludy/symbol.rb +3 -0
- data/lib/ludy/tasks/erb_cpp/attr_builder.rb +49 -0
- data/lib/ludy/tasks/erb_cpp/header_guard.rb +12 -0
- data/lib/ludy/tasks/erb_cpp/template_forward_parameters.rb +43 -0
- data/lib/ludy/tasks/erb_cpp.rb +35 -0
- data/lib/ludy/tasks.rb +3 -0
- data/lib/ludy/test/helper.rb +3 -0
- data/lib/ludy/variable.rb +9 -17
- data/lib/ludy/y_combinator.rb +3 -22
- data/lib/ludy/z_combinator.rb +2 -16
- data/lib/ludy.rb +74 -23
- data/lib/puzzle_generator/chain.rb +2 -2
- data/lib/puzzle_generator/chained_map.rb +7 -10
- data/lib/puzzle_generator/colored_map.rb +2 -2
- data/lib/puzzle_generator/map.rb +8 -12
- data/lib/puzzle_generator/misc.rb +5 -4
- data/lib/puzzle_generator/puzzle.rb +4 -4
- data/lib/puzzle_generator.rb +2 -2
- data/spec/ludy_spec.rb +22 -0
- data/tasks/annotations.rake +30 -0
- data/tasks/doc.rake +50 -0
- data/tasks/gem.rake +89 -0
- data/tasks/manifest.rake +41 -0
- data/tasks/rubyforge.rake +57 -0
- data/tasks/setup.rb +151 -0
- data/tasks/spec.rake +40 -0
- data/tasks/svn.rake +44 -0
- data/tasks/test.rake +40 -0
- data/test/deprecated/callstack.rb +18 -0
- data/test/deprecated/curry.rb +34 -0
- data/test/deprecated/rambda.rb +15 -0
- data/test/{tc_this.rb → deprecated/this.rb} +2 -18
- data/test/{ts_ludy.rb → deprecated/ts_ludy.rb} +2 -17
- data/test/deprecated/unzip_and_untranspose.rb +13 -0
- data/test/{test_puzzle.rb → example_puzzle.rb} +3 -2
- data/test/test_all.rb +21 -0
- data/test/test_array.rb +47 -0
- data/test/test_class.rb +13 -0
- data/test/test_defun.rb +37 -0
- data/test/test_dices.rb +32 -0
- data/test/test_kernel.rb +36 -0
- data/test/test_lazy.rb +18 -0
- data/test/test_proc.rb +57 -0
- data/test/test_symbol.rb +15 -0
- data/test/test_variable.rb +29 -0
- data/test/test_y_combinator.rb +21 -0
- data/test/test_z_combinator.rb +20 -0
- metadata +134 -51
- data/lib/lib/amulti.rb +0 -40
- data/lib/lib/multi.rb +0 -139
- data/lib/lib/smulti.rb +0 -56
- data/lib/ludy/aspect.rb +0 -41
- data/lib/ludy/bind.rb +0 -31
- data/lib/ludy/callstack.rb +0 -39
- data/lib/ludy/curry.rb +0 -49
- data/lib/ludy/ludy_ext.rb +0 -145
- data/lib/ludy/rambda.rb +0 -42
- data/lib/ludy/this.rb +0 -34
- data/ludy.gemspec +0 -44
- data/test/tc_bind.rb +0 -29
- data/test/tc_callstack.rb +0 -34
- data/test/tc_curry.rb +0 -51
- data/test/tc_dice.rb +0 -48
- data/test/tc_lazy.rb +0 -34
- data/test/tc_ludy_ext.rb +0 -154
- data/test/tc_rambda.rb +0 -31
- data/test/tc_variable.rb +0 -45
- data/test/tc_y_combinator.rb +0 -37
- data/test/tc_z_combinator.rb +0 -36
@@ -0,0 +1,17 @@
|
|
1
|
+
|
2
|
+
require 'ludy/class/undef_all_methods'
|
3
|
+
require 'singleton'
|
4
|
+
|
5
|
+
module Ludy
|
6
|
+
# a blackhole would eat any message it received.
|
7
|
+
class Blackhole
|
8
|
+
undef_all_methods
|
9
|
+
include Singleton
|
10
|
+
def method_missing msg, *args, &block
|
11
|
+
self
|
12
|
+
end
|
13
|
+
def nil?
|
14
|
+
true
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/ludy/class.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
|
2
|
+
module Ludy
|
3
|
+
|
4
|
+
|
5
|
+
end
|
6
|
+
|
7
|
+
module Kernel
|
8
|
+
def cut target, &block
|
9
|
+
(class << target; self; end)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class Name
|
14
|
+
def name
|
15
|
+
'name'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
cut Name do
|
20
|
+
def name
|
21
|
+
"<#{super}>"
|
22
|
+
end
|
23
|
+
def g
|
24
|
+
'??'
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
|
2
|
+
module Ludy
|
3
|
+
# TRACE_EVENT = 0
|
4
|
+
# TRACE_FILE = 1
|
5
|
+
# TRACE_LINE = 2
|
6
|
+
# TRACE_MSG = 3
|
7
|
+
# TRACE_BINDING = 4
|
8
|
+
# TRACE_CLASS = 5
|
9
|
+
|
10
|
+
def callstack levels = -1
|
11
|
+
st = Thread.current[:callstack]
|
12
|
+
if levels then st && st[levels - 2] else st end
|
13
|
+
end
|
14
|
+
module_function :callstack
|
15
|
+
end # of Ludy
|
16
|
+
|
17
|
+
set_trace_func lambda{ |*args|
|
18
|
+
case args[0]
|
19
|
+
when /call$/
|
20
|
+
(Thread.current[:callstack] ||= []).push args
|
21
|
+
when /return$/
|
22
|
+
(Thread.current[:callstack] ||= []).pop
|
23
|
+
end
|
24
|
+
}
|
@@ -0,0 +1,29 @@
|
|
1
|
+
|
2
|
+
require 'ludy/proc/curry'
|
3
|
+
|
4
|
+
module Ludy
|
5
|
+
|
6
|
+
module Curry
|
7
|
+
def self.included target
|
8
|
+
target.module_eval{
|
9
|
+
instance_methods.each{ |m|
|
10
|
+
next unless m =~ /^\w/
|
11
|
+
module_eval <<-END
|
12
|
+
def c#{m} *args, &block
|
13
|
+
if args.size == method(:#{m}).arity
|
14
|
+
self.__send__ :#{m}, *args, &block
|
15
|
+
else
|
16
|
+
method(:c#{m}).to_proc.send :__curry__, *args
|
17
|
+
end
|
18
|
+
end
|
19
|
+
END
|
20
|
+
}
|
21
|
+
}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
=begin
|
28
|
+
method(:#{m}).to_proc.curry.call *args, &block
|
29
|
+
=end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
|
2
|
+
require 'rubygems'
|
3
|
+
raise LoadError.new('you need ruby2ruby gem to use this tool') unless require 'ruby2ruby'
|
4
|
+
|
5
|
+
require 'ludy/symbol/to_proc'
|
6
|
+
|
7
|
+
module Ludy
|
8
|
+
|
9
|
+
class Rambda
|
10
|
+
def initialize &block
|
11
|
+
@this = eval block.to_ruby
|
12
|
+
define_instance_method :call, &@this
|
13
|
+
alias_instance_method :[], :call
|
14
|
+
end
|
15
|
+
attr_reader :this
|
16
|
+
alias_method :to_proc, :this
|
17
|
+
end
|
18
|
+
|
19
|
+
def rambda &block
|
20
|
+
Rambda.new &block
|
21
|
+
end
|
22
|
+
|
23
|
+
end # of Ludy
|
@@ -0,0 +1,14 @@
|
|
1
|
+
|
2
|
+
require 'ludy/callstack'
|
3
|
+
|
4
|
+
module Ludy
|
5
|
+
def this
|
6
|
+
info = callstack(-2)
|
7
|
+
# lambda{ |*args|
|
8
|
+
# Thread.current[:temp_args] = args
|
9
|
+
# eval("send :#{info[3]}, *Thread.current[:temp_args]", info[4])
|
10
|
+
# }
|
11
|
+
eval('self', info[TRACE_BINDING]).method(info[TRACE_MSG])
|
12
|
+
end
|
13
|
+
module_function :this
|
14
|
+
end # of Ludy
|
@@ -1,34 +1,25 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
# Copyright (c) 2007, Lin Jen-Shin(a.k.a. godfat 真常)
|
4
|
-
#
|
5
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
-
# you may not use this file except in compliance with the License.
|
7
|
-
# You may obtain a copy of the License at
|
8
|
-
#
|
9
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
-
#
|
11
|
-
# Unless required by applicable law or agreed to in writing, software
|
12
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
-
# See the License for the specific language governing permissions and
|
15
|
-
# limitations under the License.
|
16
1
|
|
17
2
|
module Ludy
|
18
3
|
|
19
|
-
|
4
|
+
# dices, e.g., 4d6, 2d20, etc.
|
5
|
+
class Dices
|
20
6
|
attr_reader :amounts, :faces
|
7
|
+
# the default dice is 1d20
|
21
8
|
def initialize amounts = 1, faces = 20
|
22
9
|
@amounts = amounts
|
23
10
|
@faces = faces
|
24
11
|
end
|
12
|
+
# roll the dices
|
25
13
|
def roll
|
26
14
|
@amounts.roll @faces
|
27
15
|
end
|
16
|
+
# the possible min value these dices would roll out.
|
28
17
|
def min; @amounts; end
|
18
|
+
# the possible max value these dices would roll out.
|
29
19
|
def max; @amounts*@faces; end
|
30
20
|
end
|
31
21
|
|
22
|
+
# a dice set could contain 4d6 + 2d20 and more dices.
|
32
23
|
class DiceSet
|
33
24
|
attr_reader :min, :max
|
34
25
|
def initialize *args
|
@@ -39,15 +30,17 @@ module Ludy
|
|
39
30
|
@max += i.max
|
40
31
|
}
|
41
32
|
end
|
33
|
+
# roll the dice set
|
42
34
|
def roll
|
43
35
|
result = 0
|
44
36
|
@diceset.each { |i| result += i.roll }
|
45
37
|
result
|
46
38
|
end
|
47
|
-
|
48
|
-
|
49
|
-
@
|
50
|
-
@
|
39
|
+
# put dices into this dice set
|
40
|
+
def << dices
|
41
|
+
@diceset << dices
|
42
|
+
@min += dices.min
|
43
|
+
@max += dices.max
|
51
44
|
self
|
52
45
|
end
|
53
46
|
end
|
@@ -55,6 +48,7 @@ module Ludy
|
|
55
48
|
end
|
56
49
|
|
57
50
|
class Numeric
|
51
|
+
# roll dices (with amounts equal to self.to_i) with faces = ?
|
58
52
|
def roll faces = 20
|
59
53
|
return nil unless self > 0 && self.integer? &&
|
60
54
|
faces > 0 && faces.integer?
|
@@ -62,7 +56,9 @@ class Numeric
|
|
62
56
|
1.step(self){ |i| result += rand(faces) + 1 }
|
63
57
|
result
|
64
58
|
end
|
65
|
-
|
66
|
-
|
59
|
+
|
60
|
+
# create dices with faces = ?
|
61
|
+
def dices faces = 20
|
62
|
+
Ludy::Dices.new self, faces
|
67
63
|
end
|
68
64
|
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
|
2
|
+
require 'ludy/message_dispatcher'
|
3
|
+
|
4
|
+
module Kernel
|
5
|
+
# you can use defun for overloading(ad-hoc polymorphism),
|
6
|
+
# multi-method, pattern matching, and perhaps others?
|
7
|
+
def defun name, *args, &fun
|
8
|
+
Ludy::MessageDispatcher.create self, name, args, &fun
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
|
2
|
+
require 'ludy/blackhole'
|
3
|
+
|
4
|
+
module Kernel
|
5
|
+
# it simply return self, see NilClass#ergo
|
6
|
+
def ergo
|
7
|
+
self
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class NilClass
|
12
|
+
# return blackhole to eat any message, see Kernel#ergo
|
13
|
+
def ergo
|
14
|
+
Ludy::Blackhole.instance
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
|
2
|
+
module Kernel
|
3
|
+
if RUBY_VERSION < '1.9.0'
|
4
|
+
# it would be defined if RUBY_VERSION < '1.9.0', see rdoc in ruby 1.9
|
5
|
+
def public_send msg, *args, &block
|
6
|
+
if self.respond_to? msg
|
7
|
+
self.__send__ msg, *args, &block
|
8
|
+
else
|
9
|
+
self.method_missing msg, *args, &block
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
|
2
|
+
module Kernel
|
3
|
+
if RUBY_VERSION < '1.9.0'
|
4
|
+
# it would be defined if RUBY_VERSION < '1.9.0', see rdoc in ruby 1.9
|
5
|
+
def define_singleton_method msg, &block
|
6
|
+
self.class.__send__ :define_method, msg, &block
|
7
|
+
end
|
8
|
+
end
|
9
|
+
# it simply alias singleton(instance) method
|
10
|
+
def alias_singleton_method new_msg, old_msg
|
11
|
+
self.class.__send__ :alias_method, new_msg, old_msg
|
12
|
+
end
|
13
|
+
end
|
data/lib/ludy/kernel.rb
ADDED
data/lib/ludy/lazy.rb
CHANGED
@@ -1,24 +1,15 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
1
|
|
3
|
-
|
4
|
-
|
5
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
-
# you may not use this file except in compliance with the License.
|
7
|
-
# You may obtain a copy of the License at
|
8
|
-
#
|
9
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
-
#
|
11
|
-
# Unless required by applicable law or agreed to in writing, software
|
12
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
-
# See the License for the specific language governing permissions and
|
15
|
-
# limitations under the License.
|
2
|
+
require 'ludy/kernel/public_send'
|
3
|
+
require 'ludy/class/undef_all_methods'
|
16
4
|
|
17
5
|
module Ludy
|
18
6
|
|
7
|
+
# a lazy object would be evaluated until the time it called,
|
8
|
+
# and save the result for futher use.
|
19
9
|
class Lazy
|
20
|
-
|
10
|
+
undef_all_methods
|
21
11
|
|
12
|
+
# supply the evaluation function through first argument or block
|
22
13
|
def initialize func = nil, &block
|
23
14
|
if block_given? then @func = block
|
24
15
|
else
|
@@ -27,11 +18,13 @@ module Ludy
|
|
27
18
|
end
|
28
19
|
end
|
29
20
|
|
21
|
+
# :nodoc:
|
30
22
|
def method_missing msg, *arg, &block
|
31
|
-
(@obj ||= @func.call).
|
23
|
+
(@obj ||= @func.call).public_send msg, *arg, &block
|
32
24
|
end
|
33
25
|
end
|
34
26
|
|
27
|
+
# provided for creating lazy object more convient
|
35
28
|
def lazy arg = nil, &block
|
36
29
|
Lazy.new arg, &block
|
37
30
|
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
|
2
|
+
require 'ludy/pattern_matcher'
|
3
|
+
if RUBY_VERSION < '1.9.0'
|
4
|
+
require 'ludy/kernel/singleton_method'
|
5
|
+
end
|
6
|
+
|
7
|
+
module Ludy
|
8
|
+
|
9
|
+
class MessageDispatcher
|
10
|
+
# create a dispatcher or append arg_list to the existed dispatcher,
|
11
|
+
# see Kernel#defun
|
12
|
+
def self.create actor, msg, args, &fun
|
13
|
+
if (@patchers ||= {})[[actor, msg]].nil?
|
14
|
+
@patchers[[actor, msg]] = MessageDispatcher.new actor, msg, args, &fun
|
15
|
+
else
|
16
|
+
@patchers[[actor, msg]].listen args, &fun
|
17
|
+
end
|
18
|
+
end
|
19
|
+
# actor is the listener who listen to the message
|
20
|
+
def initialize actor, msg, args, &fun
|
21
|
+
@actor = actor
|
22
|
+
@msg = msg
|
23
|
+
@matcher = PatternMatcher.new args, &fun
|
24
|
+
define_method_in_actor
|
25
|
+
end
|
26
|
+
# open your ear and listen, and call me when you hear
|
27
|
+
def listen arg_list, &fun
|
28
|
+
@matcher << [arg_list, fun]
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
def define_method_in_actor
|
33
|
+
# if @actor.respond_to? @msg
|
34
|
+
# raise RuntimeError.new("#{@actor.inspect}'s method \"#{@msg}\" already defined.")
|
35
|
+
# else
|
36
|
+
matcher = @matcher
|
37
|
+
msg = @msg # make them close in the closure
|
38
|
+
define_method = @actor.kind_of?(Class) ? :define_method : :define_singleton_method
|
39
|
+
|
40
|
+
# comment off &block in lambda for ruby 1.8 compatibility
|
41
|
+
@actor.public_send define_method, msg do |*args|#, &block|
|
42
|
+
fun = matcher.first_match args
|
43
|
+
if fun.nil?
|
44
|
+
if self.respond_to? :method_missing
|
45
|
+
self.method_missing msg, *args#, &block
|
46
|
+
else
|
47
|
+
raise NoMethodError.new("#{self.inspect} doesn't respond to \"#{msg}\"")
|
48
|
+
end
|
49
|
+
else
|
50
|
+
fun.call(*args)#, &block)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
# end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end # of Ludy
|
58
|
+
|
@@ -0,0 +1,41 @@
|
|
1
|
+
|
2
|
+
require 'ludy/kernel/public_send'
|
3
|
+
|
4
|
+
module Ludy
|
5
|
+
# someone who does the pattern matching thing
|
6
|
+
# see Kernel#defun
|
7
|
+
class PatternMatcher
|
8
|
+
# init for the first parameter
|
9
|
+
def initialize args, &fun; @params = [[args, fun]]; end
|
10
|
+
# find the first match of this arguments. notice,
|
11
|
+
# this is not the best match. maybe someday i could
|
12
|
+
# implement the match policy accordingly or selectable policy.
|
13
|
+
def first_match args
|
14
|
+
@params.find{ |parameters, fun|
|
15
|
+
match? parameters, args
|
16
|
+
}.ergo.last
|
17
|
+
end
|
18
|
+
# delegate all the rest message to @params array
|
19
|
+
def method_missing msg, *args, &block
|
20
|
+
if @params.respond_to? msg
|
21
|
+
@params.public_send msg, *args, &block
|
22
|
+
else
|
23
|
+
raise NoMethodError.new("PatternMatcher doesn't respond to #{msg}")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
def match? parameters, arguments
|
29
|
+
return false unless parameters.size == arguments.size
|
30
|
+
parameters.zip(arguments).each{ |param, arg|
|
31
|
+
if param.kind_of? Class
|
32
|
+
return false unless arg.kind_of?(param)
|
33
|
+
else
|
34
|
+
return false unless arg == param
|
35
|
+
end
|
36
|
+
}
|
37
|
+
return true
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end # of Ludy
|
@@ -0,0 +1,21 @@
|
|
1
|
+
|
2
|
+
class Proc
|
3
|
+
# C++ TR1 style bind
|
4
|
+
# use _#{n} for placeholders
|
5
|
+
# _1 => 1st arg
|
6
|
+
# _2 => 2nd arg
|
7
|
+
# ...and so on
|
8
|
+
def bind *args
|
9
|
+
lambda{ |*new_args|
|
10
|
+
self[*(args.map{ |arg|
|
11
|
+
if (arg.kind_of? Symbol) && arg.to_s =~ /^_(\d+)$/
|
12
|
+
# is placeholder
|
13
|
+
new_args[$1.to_i-1]
|
14
|
+
else
|
15
|
+
# is not placeholder
|
16
|
+
arg
|
17
|
+
end
|
18
|
+
} + new_args).first(self.arity)]
|
19
|
+
}
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
|
2
|
+
class Proc
|
3
|
+
# TODO: missing traversal of chain
|
4
|
+
# create a chain of proc. whenever you call the chain,
|
5
|
+
# each proc would be called. the return value would be
|
6
|
+
# all the results saved orderly in a array.
|
7
|
+
def chain *procs, &block
|
8
|
+
procs << block if block
|
9
|
+
lambda{ |*args|
|
10
|
+
result = []
|
11
|
+
([self] + procs).each{ |i|
|
12
|
+
result += [i[*args]].flatten
|
13
|
+
}
|
14
|
+
result
|
15
|
+
}
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
|
2
|
+
require 'ludy/kernel/public_send'
|
3
|
+
|
4
|
+
class Proc
|
5
|
+
def __curry__ *pre # :nodoc:
|
6
|
+
lambda{ |*post| self[*(pre + post)] }
|
7
|
+
end
|
8
|
+
|
9
|
+
# make the caller be a curried function
|
10
|
+
# lambda{|a,b,c| [a,b,c]}.curry[1][2][3]
|
11
|
+
# => [1,2,3]
|
12
|
+
def curry
|
13
|
+
class << self
|
14
|
+
alias_method :__call__, :call
|
15
|
+
def call *args, &block
|
16
|
+
if self.arity == -1
|
17
|
+
begin # let's try if arguments are ready
|
18
|
+
# is there any better way to determine this?
|
19
|
+
# it's hard to detect correct arity value when
|
20
|
+
# Symbol#to_proc happened
|
21
|
+
# e.g., :message_that_you_never_know.to_proc.arity => ?
|
22
|
+
# i'd tried put hacks in Symbol#to_proc, but it's
|
23
|
+
# difficult to implement in correct way
|
24
|
+
# i would try it again in other day
|
25
|
+
self.public_send :__call__, *args, &block
|
26
|
+
rescue ArgumentError # oops, let's curry it
|
27
|
+
method(:call).to_proc.public_send :__curry__, *args
|
28
|
+
end
|
29
|
+
elsif args.size == self.arity
|
30
|
+
self.public_send :__call__, *args, &block
|
31
|
+
else
|
32
|
+
method(:call).to_proc.public_send :__curry__, *args
|
33
|
+
end
|
34
|
+
end
|
35
|
+
alias_method :[], :call
|
36
|
+
end
|
37
|
+
self
|
38
|
+
end
|
39
|
+
end
|
data/lib/ludy/proc.rb
ADDED
data/lib/ludy/symbol.rb
ADDED