davidrichards-sirb 0.6.14
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/README.rdoc +227 -0
- data/VERSION.yml +4 -0
- data/bin/sirb +33 -0
- data/lib/overrides/array.rb +6 -0
- data/lib/overrides/file.rb +17 -0
- data/lib/overrides/module.rb +70 -0
- data/lib/overrides/symbol.rb +39 -0
- data/lib/sirb/enumerable_statistics.rb +350 -0
- data/lib/sirb/functional.rb +114 -0
- data/lib/sirb/general_statistics.rb +72 -0
- data/lib/sirb/inter_enumerable_statistics.rb +139 -0
- data/lib/sirb/lib_loader.rb +45 -0
- data/lib/sirb/runner.rb +274 -0
- data/lib/sirb/sproc/proc.rb +5 -0
- data/lib/sirb/sproc/proc_source.rb +130 -0
- data/lib/sirb/sproc/sproc.rb +79 -0
- data/lib/sirb/sproc/usage_notes.txt +25 -0
- data/lib/sirb/sproc.rb +29 -0
- data/lib/sirb/thread_support.rb +20 -0
- data/lib/sirb/unbound_method.rb +5 -0
- data/lib/sirb.rb +52 -0
- data/lib/stored_procedures.rb +10 -0
- data/spec/lib/overrides/array_spec.rb +7 -0
- data/spec/lib/overrides/file_spec.rb +13 -0
- data/spec/lib/overrides/module_spec.rb +86 -0
- data/spec/lib/overrides/symbol_spec.rb +39 -0
- data/spec/lib/sirb/enumerable_statistics_spec.rb +85 -0
- data/spec/lib/sirb/functional_spec.rb +75 -0
- data/spec/lib/sirb/general_statistics_spec.rb +40 -0
- data/spec/lib/sirb/inter_enumerable_statistics_spec.rb +55 -0
- data/spec/lib/sirb/lib_loader_spec.rb +39 -0
- data/spec/lib/sirb/runner_spec.rb +9 -0
- data/spec/lib/sirb/sproc/proc_spec.rb +9 -0
- data/spec/lib/sirb/sproc/sproc_spec.rb +25 -0
- data/spec/lib/sirb/unbound_method_spec.rb +12 -0
- data/spec/lib/sirb_spec.rb +9 -0
- data/spec/spec_helper.rb +15 -0
- metadata +97 -0
data/README.rdoc
ADDED
@@ -0,0 +1,227 @@
|
|
1
|
+
= Sirb
|
2
|
+
|
3
|
+
* http://github.com/davidrichards/sirb/tree/master
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
Statistics + IRB. This offers a series of useful tools that a console should probably have, if your goal is to crunch a few numbers. It includes all the packages that I use, if you have them. Statisticus will have a standard library of statistical methods that you may want to have access to, so it's probably worth loading that gem as well.
|
8
|
+
|
9
|
+
== FEATURES/PROBLEMS:
|
10
|
+
|
11
|
+
=== Statistical Functions
|
12
|
+
|
13
|
+
Sirb has a set of rather useful functions setup:
|
14
|
+
|
15
|
+
* max
|
16
|
+
* min
|
17
|
+
* sum
|
18
|
+
* mean
|
19
|
+
* median
|
20
|
+
* range
|
21
|
+
* variance (also var)
|
22
|
+
* standard_deviation (also std)
|
23
|
+
* sort
|
24
|
+
* rank
|
25
|
+
* order
|
26
|
+
* quantile
|
27
|
+
* cumulative_sum (also cum_sum)
|
28
|
+
* cumulative_product (also cum_prod)
|
29
|
+
* cumulative_max (also cum_max)
|
30
|
+
* cumulative_min (also cum_min)
|
31
|
+
|
32
|
+
For comparing lists, you can use:
|
33
|
+
|
34
|
+
* correlation (also cor)
|
35
|
+
* p_max
|
36
|
+
* p_min
|
37
|
+
|
38
|
+
For other things, you can use:
|
39
|
+
|
40
|
+
* max
|
41
|
+
* min
|
42
|
+
* product
|
43
|
+
* to_pairs
|
44
|
+
|
45
|
+
=== Libraries Loaded
|
46
|
+
|
47
|
+
Right now, Sirb attempts to load the following libraries (when available):
|
48
|
+
|
49
|
+
* NArray
|
50
|
+
* RGL
|
51
|
+
* matrix
|
52
|
+
* set
|
53
|
+
* RNum
|
54
|
+
* Statisticus
|
55
|
+
* RBTree
|
56
|
+
* mathn
|
57
|
+
* This library
|
58
|
+
|
59
|
+
=== Stored Procedures
|
60
|
+
|
61
|
+
As you work, you can choose to store a procedure and use it between sessions. I do this with pstore (part of Ruby's standard library) and some code I found on Ruby Quiz by Florian Groß. The storage process is a little draconian, so in the short-term, you can call sirb with -w (sirb -w) and this feature is taken away from the runtime.
|
62
|
+
|
63
|
+
This is a very useful tool to have if you have some R code that you tend to use often, say, or some other functions that you discover while working with some data.
|
64
|
+
|
65
|
+
== SYNOPSIS:
|
66
|
+
|
67
|
+
=== Functions
|
68
|
+
|
69
|
+
From command line:
|
70
|
+
sirb
|
71
|
+
>> @a = [3,2,6,7,14]
|
72
|
+
=> [3, 2, 6, 7, 14]
|
73
|
+
>> @b = [4,6,2,1,19]
|
74
|
+
=> [4, 6, 2, 1, 19]
|
75
|
+
>> @a.max
|
76
|
+
=> 14
|
77
|
+
>> @a.min
|
78
|
+
=> 2
|
79
|
+
>> @a.sum
|
80
|
+
=> 32.0
|
81
|
+
>> # Most methods have meaningful block semantics
|
82
|
+
?> @a.sum {|x| x ** x}
|
83
|
+
=> 1.11120068264282e+16
|
84
|
+
>> @a.mean
|
85
|
+
=> 6.4
|
86
|
+
>> @a.median
|
87
|
+
=> 6
|
88
|
+
>> @a.range
|
89
|
+
=> [2, 14]
|
90
|
+
>> @a.var
|
91
|
+
=> 22.3
|
92
|
+
>> @a.std
|
93
|
+
=> 4.72228758124704
|
94
|
+
>> @a.sort
|
95
|
+
=> [2, 3, 6, 7, 14]
|
96
|
+
>> @a.rank
|
97
|
+
=> [2, 1, 3, 4, 5]
|
98
|
+
>> @a.order
|
99
|
+
=> [2, 1, 3, 4, 5]
|
100
|
+
>> @a.quantile
|
101
|
+
=> [2, 3, 6, 7, 14]
|
102
|
+
>> @a.cum_sum
|
103
|
+
=> [3.0, 5.0, 11.0, 18.0, 32.0]
|
104
|
+
>> @a.cum_prod
|
105
|
+
=> [3.0, 6.0, 36.0, 252.0, 3528.0]
|
106
|
+
>> @a.cum_max
|
107
|
+
=> [3, 3, 6, 7, 14]
|
108
|
+
>> @a.cum_min
|
109
|
+
=> [3, 2, 2, 2, 2]
|
110
|
+
>> # And some methods between lists
|
111
|
+
?> cor(@a,@b)
|
112
|
+
=> 0.755599551729267
|
113
|
+
>> # This is the max of each pair (or set)
|
114
|
+
?> p_max(@a,@b)
|
115
|
+
=> [4, 6, 6, 7, 19]
|
116
|
+
>> # These take an arbitrary sized list
|
117
|
+
?> p_max(@a,@b, [1,2,3,4,5])
|
118
|
+
=> [4, 6, 6, 7, 19]
|
119
|
+
>> # And the min
|
120
|
+
?> p_min(@a,@b)
|
121
|
+
=> [3, 2, 2, 1, 14]
|
122
|
+
>> p_min(@a,@b, [1,2,3,4,5])
|
123
|
+
=> [1, 2, 2, 1, 5]
|
124
|
+
>> # Finally, some methods out in the wild for general use:
|
125
|
+
?> max(1,2,3,4,5)
|
126
|
+
=> 5
|
127
|
+
>> min(1,2,3,4,5)
|
128
|
+
=> 1
|
129
|
+
>> product(1,2,3,4,5)
|
130
|
+
=> 120.0
|
131
|
+
>> to_pairs(@a,@b) { |a, b| a * b }
|
132
|
+
=> [12, 12, 12, 7, 266]
|
133
|
+
>> sum_pairs(@a,@b) { |a, b| a * b }
|
134
|
+
=> 309.0
|
135
|
+
|
136
|
+
=== Stored Procedures
|
137
|
+
|
138
|
+
[sirb]$: bin/sirb
|
139
|
+
Loading sirb (Statistics + Irb: 0.6.3)
|
140
|
+
>> set :add, lambda {|x,y| x + y}, "This is my general-use adder, that adds a set of numbers"
|
141
|
+
=> "add added"
|
142
|
+
>> add 1, 2, 3
|
143
|
+
=> 6
|
144
|
+
>> sirb_help :add
|
145
|
+
* add (takes 2 arguments, returns a single value--reduce function)
|
146
|
+
This is my general-use adder, that adds a set of numbers
|
147
|
+
Source: |x,y| x + y
|
148
|
+
=> nil
|
149
|
+
>> sirb_help
|
150
|
+
|
151
|
+
This is Irb, with some extra libraries and commands loaded.
|
152
|
+
You have loaded the following libraries:
|
153
|
+
narray
|
154
|
+
rgl
|
155
|
+
matrix
|
156
|
+
rnum
|
157
|
+
set
|
158
|
+
statisticus
|
159
|
+
rbtree
|
160
|
+
rubygems
|
161
|
+
command runner
|
162
|
+
enumerable statistics
|
163
|
+
general statistics
|
164
|
+
mathn
|
165
|
+
|
166
|
+
You have setup the following commands:
|
167
|
+
|
168
|
+
* add (takes 2 arguments, returns a single value--reduce function)
|
169
|
+
This is my general-use adder, that adds a set of numbers
|
170
|
+
Source: |x,y| x + y
|
171
|
+
|
172
|
+
You can store a command like this:
|
173
|
+
set :command_name, lambda{|list params| command }, "Optional description"
|
174
|
+
|
175
|
+
>> commands
|
176
|
+
=> [:add]
|
177
|
+
>> remove_command :add
|
178
|
+
=> #<Sirb::Runner:0x23df728 @block=proc {|x,y| x + y}, @name="add", @description="This is my general-use adder, that adds a set of numbers">
|
179
|
+
>> commands
|
180
|
+
=> []
|
181
|
+
|
182
|
+
=== Functional-style Programming
|
183
|
+
|
184
|
+
Sometimes it is useful to have a bit of functional flair when implementing equations. I've slurped up a bit of that and included it:
|
185
|
+
|
186
|
+
.... Fill these in
|
187
|
+
|
188
|
+
== Known Issues
|
189
|
+
|
190
|
+
I'm generally dissatisfied with quantile, which I think matches the way that R does their quantile. However, R is inconsistent, and the community has inconsistent interpretations of how to handle that, so I just used R as the standard for today.
|
191
|
+
|
192
|
+
I only mix this into Array right now. I need to work through the various other classes that I use, and see if this will mix into all of those: Vector, Matrix, Hash, RBTree, etc.
|
193
|
+
|
194
|
+
I am a little uncomfortable with my stored procedures library. I want to review it, because it so aggressively walk on Proc. There are other ideas out there that I will want to review when I get the chance.
|
195
|
+
|
196
|
+
== REQUIREMENTS:
|
197
|
+
|
198
|
+
* All the libraries are optional, but every time you log in, you will get a list of libraries that you may want to install.
|
199
|
+
|
200
|
+
== INSTALL:
|
201
|
+
|
202
|
+
* sudo gem install davidrichards-sirb
|
203
|
+
|
204
|
+
== LICENSE:
|
205
|
+
|
206
|
+
(The MIT License)
|
207
|
+
|
208
|
+
Copyright (c) 2009 David Richards
|
209
|
+
|
210
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
211
|
+
a copy of this software and associated documentation files (the
|
212
|
+
'Software'), to deal in the Software without restriction, including
|
213
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
214
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
215
|
+
permit persons to whom the Software is furnished to do so, subject to
|
216
|
+
the following conditions:
|
217
|
+
|
218
|
+
The above copyright notice and this permission notice shall be
|
219
|
+
included in all copies or substantial portions of the Software.
|
220
|
+
|
221
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
222
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
223
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
224
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
225
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
226
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
227
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/VERSION.yml
ADDED
data/bin/sirb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
#!/usr/bin/env ruby -wKU
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
version_hash = YAML.load_file(File.join(File.dirname(__FILE__), %w(.. VERSION.yml)))
|
5
|
+
version = [version_hash[:major].to_s, version_hash[:minor].to_s, version_hash[:patch].to_s].join(".")
|
6
|
+
sirb_file = File.join(File.dirname(__FILE__), %w(.. lib sirb))
|
7
|
+
stored_procedures_file = File.join(File.dirname(__FILE__), %w(.. lib stored_procedures))
|
8
|
+
|
9
|
+
irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
|
10
|
+
|
11
|
+
require 'optparse'
|
12
|
+
options = { :sandbox => false, :irb => irb, :without_stored_procedures => false }
|
13
|
+
OptionParser.new do |opt|
|
14
|
+
opt.banner = "Usage: console [environment] [options]"
|
15
|
+
opt.on("--irb=[#{irb}]", 'Invoke a different irb.') { |v| options[:irb] = v }
|
16
|
+
opt.on("--without-stored_procedures",
|
17
|
+
'Run without storing proedures.') { |v| options[:without_stored_procedures] = true }
|
18
|
+
opt.on("-w", 'Run without storing procedures') { |v| options[:without_stored_procedures] = true }
|
19
|
+
opt.parse!(ARGV)
|
20
|
+
end
|
21
|
+
|
22
|
+
libs = " -r irb/completion -r #{sirb_file}"
|
23
|
+
libs += " -r #{stored_procedures_file}" unless options[:without_stored_procedures]
|
24
|
+
|
25
|
+
puts "Loading sirb (Statistics + Irb: #{version})"
|
26
|
+
|
27
|
+
if options[:sandbox]
|
28
|
+
puts "I'll have to think about how the whole sandbox concept should work for the sirb"
|
29
|
+
elsif options[:without_stored_procedures]
|
30
|
+
puts "You cannot read or write stored procedures in this session."
|
31
|
+
end
|
32
|
+
|
33
|
+
exec "#{options[:irb]} #{libs} --simple-prompt"
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class File
|
2
|
+
# From setup.rb. Since I only need one method, I've added it here
|
3
|
+
# instead of using the whole setup.rb lib.
|
4
|
+
def self.mkdir_p(dirname, prefix = nil)
|
5
|
+
dirname = prefix + File.expand_path(dirname) if prefix
|
6
|
+
# Does not check '/', it's too abnormal.
|
7
|
+
dirs = File.expand_path(dirname).split(%r<(?=/)>)
|
8
|
+
if /\A[a-z]:\z/i =~ dirs[0]
|
9
|
+
disk = dirs.shift
|
10
|
+
dirs[0] = disk + dirs[0]
|
11
|
+
end
|
12
|
+
dirs.each_index do |idx|
|
13
|
+
path = dirs[0..idx].join('')
|
14
|
+
Dir.mkdir path unless File.directory?(path)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
class Module
|
2
|
+
# Stolen wholesale out of active_support. I didn't want the whole gem
|
3
|
+
# in this gem.
|
4
|
+
def alias_method_chain(target, feature)
|
5
|
+
# Strip out punctuation on predicates or bang methods since
|
6
|
+
# e.g. target?_without_feature is not a valid method name.
|
7
|
+
aliased_target, punctuation = target.to_s.sub(/([?!=])$/, ''), $1
|
8
|
+
yield(aliased_target, punctuation) if block_given?
|
9
|
+
|
10
|
+
with_method, without_method = "#{aliased_target}_with_#{feature}#{punctuation}", "#{aliased_target}_without_#{feature}#{punctuation}"
|
11
|
+
|
12
|
+
alias_method without_method, target
|
13
|
+
alias_method target, with_method
|
14
|
+
|
15
|
+
case
|
16
|
+
when public_method_defined?(without_method)
|
17
|
+
public target
|
18
|
+
when protected_method_defined?(without_method)
|
19
|
+
protected target
|
20
|
+
when private_method_defined?(without_method)
|
21
|
+
private target
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Moves a method safely into a new name, only if it exists. The default
|
26
|
+
# name is original_#{method_name}. So, archive_method(:x) creates
|
27
|
+
# original_x as a method, and removes x, so that a module can then use
|
28
|
+
# the x method name for something else. To be honest, I'm not really
|
29
|
+
# sure why I can't create a new method without overriding the old one,
|
30
|
+
# it seems like it used to work, and I may have something boinked in my
|
31
|
+
# system, but it's late and I could be wrong too.
|
32
|
+
def archive_method(target, new_name=nil)
|
33
|
+
new_name ||= ("original_" + target.to_s).to_sym
|
34
|
+
begin
|
35
|
+
alias_method(new_name, target)
|
36
|
+
|
37
|
+
case
|
38
|
+
when public_method_defined?(target)
|
39
|
+
public new_name
|
40
|
+
when protected_method_defined?(target)
|
41
|
+
protected new_name
|
42
|
+
when private_method_defined?(target)
|
43
|
+
private new_name
|
44
|
+
end
|
45
|
+
|
46
|
+
remove_method(target)
|
47
|
+
rescue
|
48
|
+
# The instance_methods show that the soon-to-be-defined methods are
|
49
|
+
# defined before they are, really weird. Need to see if this is a
|
50
|
+
# problem with 1.9. For now, fail silently.
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Access instance methods with array notation. Returns UnboundMethod,
|
55
|
+
alias [] instance_method
|
56
|
+
|
57
|
+
# Define a instance method with name sym and body f.
|
58
|
+
# Example: String[:backwards] = lambda { reverse }
|
59
|
+
def []=(sym, f)
|
60
|
+
self.instance_eval { define_method(sym, f) }
|
61
|
+
end
|
62
|
+
alias :save_lambda :[]=
|
63
|
+
|
64
|
+
# Only defines the method if it hasn't been defined before. It's a call
|
65
|
+
# for monkey patching, instead of gorilla patching.
|
66
|
+
def safe_def(sym, &block)
|
67
|
+
return true if self.instance_methods.include?(sym.to_s)
|
68
|
+
self.[]=(sym, block)
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
class Symbol
|
2
|
+
def to_proc
|
3
|
+
lambda {|receiver, *args| receiver.method(self)[*args]}
|
4
|
+
end
|
5
|
+
|
6
|
+
# Add [] and []= operators to the Symbol class for accessing and setting
|
7
|
+
# singleton methods of objects. Read : as "method" and [] as "of".
|
8
|
+
# So :m[o] reads "method m of o".
|
9
|
+
|
10
|
+
# Return the Method of obj named by this symbol. This may be a singleton
|
11
|
+
# method of obj (such as a class method) or an instance method defined
|
12
|
+
# by obj.class or inherited from a superclass.
|
13
|
+
# Examples:
|
14
|
+
# creator = :new[Object] # Class method Object.new
|
15
|
+
# doubler = :*[2] # * method of Fixnum 2
|
16
|
+
#
|
17
|
+
def [](obj)
|
18
|
+
obj.method(self)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Define a singleton method on object o, using Proc or Method f as its body.
|
22
|
+
# This symbol is used as the name of the method.
|
23
|
+
# Examples:
|
24
|
+
#
|
25
|
+
# :singleton[o] = lambda { puts "this is a singleton method of o" }
|
26
|
+
# :class_method[String] = lambda { puts "this is a class method" }
|
27
|
+
#
|
28
|
+
# Note that you can't create instance methods this way. See Module.[]=
|
29
|
+
#
|
30
|
+
def []=(o,f)
|
31
|
+
# We can't use self in the block below, as it is evaluated in the
|
32
|
+
# context of a different object. So we have to assign self to a variable.
|
33
|
+
sym = self
|
34
|
+
# This is the object we define singleton methods on.
|
35
|
+
eigenclass = (class << o; self end)
|
36
|
+
# define_method is private, so we have to use instance_eval to execute it.
|
37
|
+
eigenclass.instance_eval { define_method(sym, f) }
|
38
|
+
end
|
39
|
+
end
|