shenanigans 1.0.13 → 1.0.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.
- checksums.yaml +4 -4
- data/Gemfile +2 -1
- data/doc/Array.html +104 -74
- data/doc/Hash.html +77 -56
- data/doc/{Fixnum.html → Integer.html} +31 -27
- data/doc/Kernel.html +114 -74
- data/doc/Module.html +11 -15
- data/doc/Object.html +24 -95
- data/doc/String.html +31 -30
- data/doc/_index.html +13 -13
- data/doc/class_list.html +3 -3
- data/doc/css/style.css +6 -9
- data/doc/file.README.html +19 -48
- data/doc/file_list.html +2 -2
- data/doc/frames.html +2 -2
- data/doc/index.html +19 -48
- data/doc/js/app.js +69 -3
- data/doc/method_list.html +12 -20
- data/doc/top-level-namespace.html +7 -7
- data/lib/shenanigans.rb +7 -7
- data/lib/shenanigans/array.rb +3 -3
- data/lib/shenanigans/array/caret.rb +3 -2
- data/lib/shenanigans/array/random_subarray.rb +7 -5
- data/lib/shenanigans/array/reductions.rb +13 -10
- data/lib/shenanigans/array/zip_with.rb +9 -12
- data/lib/shenanigans/hash.rb +3 -3
- data/lib/shenanigans/hash/extract.rb +5 -4
- data/lib/shenanigans/hash/has_shape_pred.rb +6 -7
- data/lib/shenanigans/hash/to_ostruct.rb +8 -9
- data/lib/shenanigans/integer.rb +1 -0
- data/lib/shenanigans/integer/string_length.rb +13 -0
- data/lib/shenanigans/kernel.rb +4 -4
- data/lib/shenanigans/kernel/fn.rb +7 -6
- data/lib/shenanigans/kernel/prompt.rb +6 -7
- data/lib/shenanigans/kernel/require_optional.rb +8 -8
- data/lib/shenanigans/kernel/with.rb +4 -3
- data/lib/shenanigans/module.rb +1 -1
- data/lib/shenanigans/module/private_accessor.rb +6 -6
- data/lib/shenanigans/object.rb +1 -2
- data/lib/shenanigans/object/display.rb +5 -4
- data/lib/shenanigans/string.rb +2 -2
- data/lib/shenanigans/string/cmpi.rb +4 -3
- data/lib/shenanigans/string/in_groups_of.rb +4 -6
- data/test/array/caret_test.rb +9 -0
- data/test/array/{test_random_subarray.rb → random_subarray_test.rb} +3 -3
- data/test/array/reductions_test.rb +27 -0
- data/test/array/zip_with_test.rb +14 -0
- data/test/hash/extract_test.rb +11 -0
- data/test/hash/{test_has_shape_pred.rb → has_shape_pred_test.rb} +3 -3
- data/test/hash/{test_to_ostruct.rb → to_ostruct_test.rb} +3 -3
- data/test/integer/string_length_test.rb +16 -0
- data/test/kernel/fn_test.rb +14 -0
- data/test/kernel/{test_prompt.rb → prompt_test.rb} +4 -4
- data/test/kernel/require_optional_test.rb +15 -0
- data/test/kernel/with_test.rb +12 -0
- data/test/module/{test_private_accessor.rb → private_accessor_test.rb} +3 -3
- data/test/object/{test_display.rb → display_test.rb} +4 -5
- data/test/string/{test_cmpi.rb → cmpi_test.rb} +3 -3
- data/test/string/in_groups_of_test.rb +11 -0
- metadata +22 -25
- data/lib/shenanigans/fixnum.rb +0 -1
- data/lib/shenanigans/fixnum/string_length.rb +0 -14
- data/lib/shenanigans/object/it.rb +0 -9
- data/test/array/test_caret.rb +0 -9
- data/test/array/test_reductions.rb +0 -27
- data/test/array/test_zip_with.rb +0 -14
- data/test/fixnum/test_string_length.rb +0 -16
- data/test/hash/test_extract.rb +0 -11
- data/test/kernel/test_fn.rb +0 -14
- data/test/kernel/test_require_optional.rb +0 -17
- data/test/kernel/test_with.rb +0 -12
- data/test/object/test_it.rb +0 -10
- data/test/string/test_in_groups_of.rb +0 -11
@@ -6,15 +6,15 @@
|
|
6
6
|
<title>
|
7
7
|
Top Level Namespace
|
8
8
|
|
9
|
-
— Documentation by YARD 0.9.
|
9
|
+
— Documentation by YARD 0.9.24
|
10
10
|
|
11
11
|
</title>
|
12
12
|
|
13
|
-
<link rel="stylesheet" href="css/style.css" type="text/css"
|
13
|
+
<link rel="stylesheet" href="css/style.css" type="text/css" />
|
14
14
|
|
15
|
-
<link rel="stylesheet" href="css/common.css" type="text/css"
|
15
|
+
<link rel="stylesheet" href="css/common.css" type="text/css" />
|
16
16
|
|
17
|
-
<script type="text/javascript"
|
17
|
+
<script type="text/javascript">
|
18
18
|
pathId = "";
|
19
19
|
relpath = '';
|
20
20
|
</script>
|
@@ -86,7 +86,7 @@
|
|
86
86
|
|
87
87
|
|
88
88
|
|
89
|
-
<strong class="classes">Classes:</strong> <span class='object_link'><a href="Array.html" title="Array (class)">Array</a></span>, <span class='object_link'><a href="
|
89
|
+
<strong class="classes">Classes:</strong> <span class='object_link'><a href="Array.html" title="Array (class)">Array</a></span>, <span class='object_link'><a href="Hash.html" title="Hash (class)">Hash</a></span>, <span class='object_link'><a href="Integer.html" title="Integer (class)">Integer</a></span>, <span class='object_link'><a href="Module.html" title="Module (class)">Module</a></span>, <span class='object_link'><a href="Object.html" title="Object (class)">Object</a></span>, <span class='object_link'><a href="String.html" title="String (class)">String</a></span>
|
90
90
|
|
91
91
|
|
92
92
|
</p>
|
@@ -102,9 +102,9 @@
|
|
102
102
|
</div>
|
103
103
|
|
104
104
|
<div id="footer">
|
105
|
-
Generated on
|
105
|
+
Generated on Tue May 5 19:54:28 2020 by
|
106
106
|
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
107
|
-
0.9.
|
107
|
+
0.9.24 (ruby-2.7.1).
|
108
108
|
</div>
|
109
109
|
|
110
110
|
</div>
|
data/lib/shenanigans.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
1
|
+
require "shenanigans/array"
|
2
|
+
require "shenanigans/fixnum"
|
3
|
+
require "shenanigans/hash"
|
4
|
+
require "shenanigans/kernel"
|
5
|
+
require "shenanigans/module"
|
6
|
+
require "shenanigans/object"
|
7
|
+
require "shenanigans/string"
|
data/lib/shenanigans/array.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
require_relative
|
2
|
-
require_relative
|
3
|
-
require_relative
|
1
|
+
require_relative "array/caret"
|
2
|
+
require_relative "array/random_subarray"
|
3
|
+
require_relative "array/zip_with"
|
@@ -2,15 +2,17 @@ class Array
|
|
2
2
|
# Generates random subarrays. Uses random numbers and
|
3
3
|
# bit-fiddling to assure performant uniform distributions
|
4
4
|
# even for large arrays.
|
5
|
+
#
|
6
|
+
# @example
|
5
7
|
# a = *1..5
|
6
|
-
# a.random_subarray(3)
|
7
|
-
# #=> [[1, 3, 5], [2, 4], [1, 3, 4, 5]]
|
8
|
+
# a.random_subarray(3) #=> [[1, 3, 5], [2, 4], [1, 3, 4, 5]]
|
8
9
|
|
9
|
-
def random_subarray(n=1)
|
10
|
+
def random_subarray(n = 1)
|
10
11
|
raise ArgumentError, "negative argument" if n < 0
|
12
|
+
|
11
13
|
(1..n).map do
|
12
|
-
r = rand(2**
|
13
|
-
|
14
|
+
r = rand(2**size)
|
15
|
+
select.with_index { |_, i| r[i] == 1 }
|
14
16
|
end
|
15
17
|
end
|
16
18
|
end
|
@@ -1,13 +1,16 @@
|
|
1
1
|
class Array
|
2
|
-
# Similar to +reduce+/+inject+, but also returns intermediate values. Has the
|
2
|
+
# Similar to +reduce+/+inject+, but also returns intermediate values. Has the
|
3
|
+
# same interface as +reduce+/+inject+, so an initial value, an operator or
|
4
|
+
# both can be supplied. This method may eventually be moved to the
|
5
|
+
# +Enumerable+ module.
|
3
6
|
#
|
4
|
-
#
|
5
|
-
# a
|
6
|
-
# #=> 10
|
7
|
-
#
|
8
|
-
# #=> 60
|
9
|
-
#
|
10
|
-
# #=> ["a", "ab", "abc"]
|
7
|
+
# @example Symbol argument
|
8
|
+
# a = (1..4).to_a
|
9
|
+
# a.reductions(:+) #=> 10
|
10
|
+
# @example Initial value and symbol argument
|
11
|
+
# a.reductions(50, :+) #=> 60
|
12
|
+
# @example Block argument
|
13
|
+
# %w(a b c).reductions { |s1, s2| s1+s2 } #=> ["a", "ab", "abc"]
|
11
14
|
def reductions(*args, &block)
|
12
15
|
arr = dup
|
13
16
|
|
@@ -21,9 +24,9 @@ class Array
|
|
21
24
|
|
22
25
|
initial ||= arr.shift
|
23
26
|
|
24
|
-
arr.inject([initial, [initial]])
|
27
|
+
arr.inject([initial, [initial]]) { |(acc, result), el|
|
25
28
|
val = op ? acc.send(op, el) : yield(acc, el)
|
26
29
|
[val, result << val]
|
27
|
-
|
30
|
+
}.last
|
28
31
|
end
|
29
32
|
end
|
@@ -1,21 +1,18 @@
|
|
1
1
|
class Array
|
2
|
-
|
3
2
|
# Zip <tt>self</tt> with <tt>other</tt>, combining the elements
|
4
3
|
# with the provided block or symbol.
|
5
4
|
# The resulting array will be as long as the shorter of
|
6
5
|
# the two arrays.
|
7
|
-
#
|
8
|
-
# #=> [7, 7, 7]
|
9
|
-
# %w(a b).zip_with(%w(c d), :+)
|
10
|
-
#
|
11
|
-
#
|
12
|
-
# For more complex combinations, a block can be provided:
|
13
|
-
#
|
14
|
-
# [1,2,3].zip_with([6,5,4]) { |a,b| 3*a+2*b }
|
6
|
+
# @example With a symbol
|
7
|
+
# [1,2,3].zip_with([6,5,4], :+) #=> [7, 7, 7]
|
8
|
+
# %w(a b).zip_with(%w(c d), :+) #=> ["ac", "bd"]
|
9
|
+
# @example With a block
|
10
|
+
# [1,2,3].zip_with([6,5,4]) { |a,b| 3 * a + 2 * b }
|
15
11
|
# #=> [15, 16, 17]
|
16
|
-
def zip_with(other, op=nil)
|
17
|
-
return [] if
|
18
|
-
|
12
|
+
def zip_with(other, op = nil)
|
13
|
+
return [] if empty? || other.empty?
|
14
|
+
|
15
|
+
clipped = self[0..other.length - 1]
|
19
16
|
zipped = clipped.zip(other)
|
20
17
|
|
21
18
|
if op
|
data/lib/shenanigans/hash.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
require_relative
|
2
|
-
require_relative
|
3
|
-
require_relative
|
1
|
+
require_relative "hash/extract"
|
2
|
+
require_relative "hash/has_shape_pred"
|
3
|
+
require_relative "hash/to_ostruct"
|
@@ -1,10 +1,11 @@
|
|
1
1
|
class Hash
|
2
2
|
# Returns a new hash only with the specified keys (if present).
|
3
|
+
#
|
4
|
+
# @example Key order does not matter
|
3
5
|
# hash = { a: 1, b: 2, c: 3 }
|
4
|
-
# hash.extract(:b, :a)
|
5
|
-
#
|
6
|
-
# hash.extract(:a, :d)
|
7
|
-
# #=> { a: 1}
|
6
|
+
# hash.extract(:b, :a) #=> { a: 1, b: 2 }
|
7
|
+
# @example Missing keys are ignored
|
8
|
+
# hash.extract(:a, :d) #=> { a: 1}
|
8
9
|
def extract(*ks)
|
9
10
|
existing = keys & ks
|
10
11
|
Hash[existing.zip(values_at(*existing))]
|
@@ -1,15 +1,14 @@
|
|
1
1
|
class Hash
|
2
2
|
# Checks if a hash has a certain structure.
|
3
|
+
#
|
4
|
+
# @example Simple hash
|
3
5
|
# h = { k1: 1, k2: "1" }
|
4
|
-
# h.has_shape?(k1: Fixnum, k2: String)
|
5
|
-
# #=>
|
6
|
-
#
|
7
|
-
# #=> false
|
8
|
-
# It also works with compound data structures.
|
6
|
+
# h.has_shape?(k1: Fixnum, k2: String) #=> true
|
7
|
+
# h.has_shape?(k1: Class, k2: String) #=> false
|
8
|
+
# @example Nested hashes
|
9
9
|
# h = { k1: [], k2: { k3: Struct.new("Foo") } }
|
10
10
|
# shape = { k1: Array, k2: { k3: Module } }
|
11
|
-
# h.has_shape?(shape)
|
12
|
-
# #=> true
|
11
|
+
# h.has_shape?(shape) #=> true
|
13
12
|
def has_shape?(shape)
|
14
13
|
all? do |k, v|
|
15
14
|
Hash === v ? v.has_shape?(shape[k]) : shape[k] === v
|
@@ -1,8 +1,10 @@
|
|
1
|
-
require
|
1
|
+
require "ostruct"
|
2
2
|
|
3
3
|
class Hash
|
4
4
|
# Recursively converts a <tt>Hash</tt> and all nested <tt>Hash</tt>es to
|
5
5
|
# <tt>OpenStruct</tt>s. Especially useful for parsing YAML.
|
6
|
+
#
|
7
|
+
# @example
|
6
8
|
# yaml=<<EOY
|
7
9
|
# subject: Programming Languages
|
8
10
|
# languages:
|
@@ -14,14 +16,11 @@ class Hash
|
|
14
16
|
# creator : Larry Wall
|
15
17
|
# EOY
|
16
18
|
# struct = YAML.load(yaml).to_ostruct
|
17
|
-
# struct.subject
|
18
|
-
# #=> "
|
19
|
-
# struct.languages.first
|
20
|
-
# #=> #<OpenStruct name="Ruby", creator="Matz">
|
21
|
-
# struct.languages.first.creator
|
22
|
-
# #=> "Matz"
|
19
|
+
# struct.subject #=> "Programming Languages"
|
20
|
+
# struct.languages.first #=> #<OpenStruct name="Ruby", creator="Matz">
|
21
|
+
# struct.languages.first.creator #=> "Matz"
|
23
22
|
def to_ostruct
|
24
|
-
arr = map
|
23
|
+
arr = map { |k, v|
|
25
24
|
case v
|
26
25
|
when Hash
|
27
26
|
[k, v.to_ostruct]
|
@@ -30,7 +29,7 @@ class Hash
|
|
30
29
|
else
|
31
30
|
[k, v]
|
32
31
|
end
|
33
|
-
|
32
|
+
}
|
34
33
|
OpenStruct.new(Hash[arr])
|
35
34
|
end
|
36
35
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require_relative "integer/string_length"
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class Integer
|
2
|
+
# Returns the length of the number's string representation.
|
3
|
+
# @example
|
4
|
+
# 0.string_length #=> 1
|
5
|
+
# 123.string_length #=> 3
|
6
|
+
# -1.string_length #=> 2
|
7
|
+
def string_length
|
8
|
+
return 1 if zero?
|
9
|
+
|
10
|
+
len = Math.log10(abs).floor.next
|
11
|
+
positive? ? len : len.next
|
12
|
+
end
|
13
|
+
end
|
data/lib/shenanigans/kernel.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require_relative
|
2
|
-
require_relative
|
3
|
-
require_relative
|
4
|
-
require_relative
|
1
|
+
require_relative "kernel/fn"
|
2
|
+
require_relative "kernel/prompt"
|
3
|
+
require_relative "kernel/with"
|
4
|
+
require_relative "kernel/require_optional"
|
@@ -1,14 +1,15 @@
|
|
1
1
|
module Kernel
|
2
2
|
# Composes a list of functions.
|
3
3
|
# Functions can be specified as symbols or lambdas.
|
4
|
-
# ["foo bar", "baz qux"].map &fn(:split, :last)
|
5
|
-
# #=> ["bar", "qux"]
|
6
4
|
#
|
7
|
-
#
|
5
|
+
# @example Composing symbols
|
6
|
+
# ["foo bar", "baz qux"].map(&fn(:split, :last)) #=> ["bar", "qux"]
|
7
|
+
# @example Composing symbplds and lambdas
|
8
|
+
# (1..3).map(&fn(:next, -> x { x * x }, -> x { x.to_f / 2 } ))
|
8
9
|
# #=> [2.0, 4.5, 8.0]
|
9
|
-
def fn(*funs)
|
10
|
-
->
|
11
|
-
funs.inject(x) do |v,f|
|
10
|
+
def fn(*funs)
|
11
|
+
->(x) do
|
12
|
+
funs.inject(x) do |v, f|
|
12
13
|
Proc === f ? f.call(v) : v.send(f)
|
13
14
|
end
|
14
15
|
end
|
@@ -1,5 +1,4 @@
|
|
1
1
|
module Kernel
|
2
|
-
|
3
2
|
# Currently only used by <tt>prompt</tt>:
|
4
3
|
# <tt>:to_i</tt>, <tt>:to_f</tt>, <tt>:to_r</tt>, <tt>:to_sym</tt>, <tt>:to_c</tt>
|
5
4
|
CONVERSIONS = [:to_i, :to_f, :to_r, :to_sym, :to_c]
|
@@ -7,14 +6,14 @@ module Kernel
|
|
7
6
|
# Displays a prompt and returns chomped input.
|
8
7
|
# Modelled after the Python method <tt>raw_input</tt>, but also can
|
9
8
|
# be supplied with an optional conversion method.
|
9
|
+
#
|
10
|
+
# @example A simple prompt
|
10
11
|
# prompt("Prompt> ")
|
11
|
-
# Prompt> 12
|
12
|
-
#
|
13
|
-
#
|
12
|
+
# Prompt> 12 #=> "12"
|
13
|
+
# @example A prompt with conversion
|
14
14
|
# prompt("Prompt> ", :to_f)
|
15
|
-
# Prompt> 12
|
16
|
-
|
17
|
-
def prompt(text='', conversion=nil) #:doc:
|
15
|
+
# Prompt> 12 #=> 12.0
|
16
|
+
def prompt(text = "", conversion = nil)
|
18
17
|
print text unless text.empty?
|
19
18
|
input = gets.chomp
|
20
19
|
CONVERSIONS.include?(conversion) ? input.send(conversion) : input
|
@@ -2,17 +2,17 @@ module Kernel
|
|
2
2
|
# Optionally require a gem. If it is not available, <tt>nil</tt>
|
3
3
|
# will be returned. Alternatively, a block can be provided with code
|
4
4
|
# to run.
|
5
|
-
# require 'non_existent'
|
6
|
-
# #=> nil
|
7
5
|
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
|
6
|
+
# @example Without a block
|
7
|
+
# require "non_existent" #=> nil
|
8
|
+
# @example With a custom block
|
9
|
+
# require "non_existent" do
|
10
|
+
# puts "Something went wrong"
|
11
|
+
# end #=> Outputs "Something went wrong"
|
12
|
+
def require_optional(gem, &block)
|
13
13
|
require gem
|
14
14
|
rescue LoadError
|
15
|
-
block
|
15
|
+
block&.call
|
16
16
|
end
|
17
17
|
|
18
18
|
private :require_optional
|
@@ -1,12 +1,13 @@
|
|
1
1
|
module Kernel
|
2
2
|
# A Pascal/ActionScript like <tt>with</tt> method. Yields its
|
3
3
|
# argument to the provided block and then returns it.
|
4
|
+
#
|
5
|
+
# @example
|
4
6
|
# with([]) do |a|
|
5
7
|
# a << "a"
|
6
8
|
# a << "b"
|
7
|
-
# end
|
8
|
-
|
9
|
-
def with(o, &blk) #:doc:
|
9
|
+
# end #=> ["a", "b"]
|
10
|
+
def with(o, &blk)
|
10
11
|
o.tap(&blk)
|
11
12
|
end
|
12
13
|
|
data/lib/shenanigans/module.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
require_relative
|
1
|
+
require_relative "module/private_accessor"
|
@@ -1,10 +1,10 @@
|
|
1
1
|
class Module
|
2
|
-
# Works like <tt>attr_accessor</tt> but generates private
|
3
|
-
#
|
4
|
-
#
|
2
|
+
# Works like <tt>attr_accessor</tt> but generates private getter/setter
|
3
|
+
# methods for class internal use only. Useful for enforcing Smalltalk-style
|
4
|
+
# internal encapsulation.
|
5
5
|
#
|
6
6
|
# For a more complete implementation of a similar feature see {ivar_encapsulation}[https://github.com/citizen428/ivar_encapsulation].
|
7
|
-
def private_accessor(*names)
|
7
|
+
def private_accessor(*names)
|
8
8
|
names.each do |name|
|
9
9
|
instance_var_name = "@#{name}"
|
10
10
|
|
@@ -16,8 +16,8 @@ class Module
|
|
16
16
|
instance_variable_set(instance_var_name, value)
|
17
17
|
end
|
18
18
|
|
19
|
-
|
20
|
-
|
19
|
+
send(:private, name)
|
20
|
+
send(:private, "#{name}=")
|
21
21
|
end
|
22
22
|
nil # like attr_accessor
|
23
23
|
end
|
data/lib/shenanigans/object.rb
CHANGED
@@ -1,2 +1 @@
|
|
1
|
-
require_relative
|
2
|
-
require_relative 'object/display'
|
1
|
+
require_relative "object/display"
|
@@ -2,16 +2,17 @@ class Object
|
|
2
2
|
# Outputs the object and also returns it.
|
3
3
|
# Will use <tt>puts</tt> if <tt>new_line</tt> is <tt>true</tt> and
|
4
4
|
# <tt>print</tt> otherwise.
|
5
|
+
#
|
6
|
+
# @example
|
5
7
|
# "foo".display
|
6
|
-
# foo
|
7
|
-
# #=> "foo"
|
8
|
+
# foo #=> "foo"
|
8
9
|
#
|
9
10
|
# "foo".display(false)
|
10
11
|
# foo#=> "foo"
|
11
12
|
def display(new_line = true)
|
12
13
|
m = new_line ? :puts : :print
|
13
|
-
|
14
|
+
tap { |o| send(m, o) }
|
14
15
|
end
|
15
16
|
|
16
|
-
alias
|
17
|
+
alias d display
|
17
18
|
end
|
data/lib/shenanigans/string.rb
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
require_relative
|
2
|
-
require_relative
|
1
|
+
require_relative "string/in_groups_of"
|
2
|
+
require_relative "string/cmpi"
|