put 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 833121595321bacc22e213e447580f40bbbe1500670d5072c582ae54624b468f
4
- data.tar.gz: 07dd91f2ae928542e6d4ed42d046ed628fd6a28ef13978cba7ab811796128d92
3
+ metadata.gz: 91d380401f71b040bc67875987d94a474c6075e28e25197acf9eeea15bfa7d24
4
+ data.tar.gz: 1f2c56fcb6258bb2d6762eff8aacebad67c83f405d0fc2bf9b863e8355daad8e
5
5
  SHA512:
6
- metadata.gz: 37a54ae5099e675f9819d4f53e754b481d9ed7b8ad10623ca1978a0277f94e61b6acbc4eac6b0949f1a8dd9ea1e780571f4a6e5b655f493f6ecf11f1687c26f9
7
- data.tar.gz: 568dcf85f64510b6b8d8fedc70adc1740339893413a2dfad8a9f42d4f512a2dbbdf2b344356d0fcd38b4b320dbd09bb939a471e1d384b92078d4a74f37a3d631
6
+ metadata.gz: a0048ac2c7ff377dc9f3944ff540786c8b352a6475e01c20db38839fe159ba109960e40c2ca6aa92b2d81b26097dc2c627d5270bdefa36f8f6d5858ed01493a1
7
+ data.tar.gz: c11d0add1538cf3457d29b8a9a6d03ad11e8107f0e910af80a82c6699553852abb4e43180370e768dda8e8fbcc60d2518e3c93e4760a55d7f492fe3b1adb43ff
data/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
- ## [Unreleased]
1
+ ## [0.1.0] - 2022-09-22
2
2
 
3
- ## [0.1.0] - 2022-09-21
3
+ - Add Put.nils_first, Put.nils_last
4
+ - Add Put.anywhere
5
+
6
+ ## [0.0.2] - 2022-09-21
7
+
8
+ - Add support for Put.asc, Put.desc, and whether nils go first or last
9
+
10
+ ## [0.0.1] - 2022-09-21
4
11
 
5
12
  - Initial release
data/Gemfile CHANGED
@@ -1,12 +1,8 @@
1
- # frozen_string_literal: true
2
-
3
1
  source "https://rubygems.org"
4
2
 
5
- # Specify your gem's dependencies in put.gemspec
6
3
  gemspec
7
4
 
8
- gem "rake", "~> 13.0"
9
-
10
- gem "minitest", "~> 5.0"
11
-
12
- gem "standard", "~> 1.3"
5
+ gem "debug"
6
+ gem "rake"
7
+ gem "minitest"
8
+ gem "standard"
data/Gemfile.lock CHANGED
@@ -1,12 +1,18 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- put (0.0.1)
4
+ put (0.1.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
9
  ast (2.4.2)
10
+ debug (1.6.2)
11
+ irb (>= 1.3.6)
12
+ reline (>= 0.3.1)
13
+ io-console (0.5.11)
14
+ irb (1.4.1)
15
+ reline (>= 0.3.0)
10
16
  json (2.6.2)
11
17
  minitest (5.16.3)
12
18
  parallel (1.22.1)
@@ -15,6 +21,8 @@ GEM
15
21
  rainbow (3.1.1)
16
22
  rake (13.0.6)
17
23
  regexp_parser (2.5.0)
24
+ reline (0.3.1)
25
+ io-console (~> 0.5)
18
26
  rexml (3.2.5)
19
27
  rubocop (1.35.1)
20
28
  json (~> 2.3)
@@ -39,12 +47,15 @@ GEM
39
47
 
40
48
  PLATFORMS
41
49
  arm64-darwin-21
50
+ arm64-darwin-22
51
+ x86_64-linux
42
52
 
43
53
  DEPENDENCIES
44
- minitest (~> 5.0)
54
+ debug
55
+ minitest
45
56
  put!
46
- rake (~> 13.0)
47
- standard (~> 1.3)
57
+ rake
58
+ standard
48
59
 
49
60
  BUNDLED WITH
50
61
  2.3.22
data/README.md CHANGED
@@ -1,33 +1,229 @@
1
- # Put
1
+ # Put - put your things in order 💎
2
+
3
+ Put pairs with
4
+ [Enumerable#sort_by](https://ruby-doc.org/core-3.1.2/Enumerable.html#method-i-sort_by)
5
+ to provide a more expressive, fault-tolerant, and configurable approach to
6
+ sorting Ruby objects with multiple criteria.
7
+
8
+ # First, put Put in your Gemfile
9
+
10
+ You've probably already put a few gems in there, so why not put Put, too:
11
+
12
+ ```ruby
13
+ gem "put"
14
+ ```
15
+
16
+ Of course after you push Put, your colleagues will wonder why you put Put there.
17
+
18
+ ## Before you tell me where to put it
19
+
20
+ A neat trick when applying complex sorting rules to a collection is to map them
21
+ to an array of arrays of comparable values in priority order. It's a common
22
+ approach (and a special subtype of what's called a [Schwartzian
23
+ transform](https://en.wikipedia.org/wiki/Schwartzian_transform)), but this
24
+ pattern doesn't have an widely-accepted name yet, so let's use code to explain.
25
+
26
+ Suppose you have some people:
27
+
28
+ ```ruby
29
+ Person = Struct.new(:name, :age, :rubyist?, keyword_init: true)
30
+
31
+ people = [
32
+ Person.new(name: "Tam", age: 22),
33
+ Person.new(name: "Zak", age: 33),
34
+ Person.new(name: "Axe", age: 33),
35
+ Person.new(name: "Qin", age: 18, rubyist?: true),
36
+ Person.new(name: "Zoe", age: 28, rubyist?: true)
37
+ ]
38
+ ```
39
+
40
+ And you want to sort these people in the following priority order:
41
+
42
+ 1. Put any Rubyists at the _top_ of the list, as is right and good
43
+ 2. If both are (or are not) Rubyists, break the tie by sorting by age descending
44
+ 3. Finally, break any remaining ties by sorting by name ascending
45
+
46
+ Here's what the aforementioned pattern to accomplish this usually looks like
47
+ using
48
+ [Enumerable#sort_by](https://ruby-doc.org/core-3.1.2/Enumerable.html#method-i-sort_by):
49
+
50
+ ```ruby
51
+ people.sort_by { |person|
52
+ [
53
+ person.rubyist? ? 0 : 1,
54
+ person.age * -1,
55
+ person.name
56
+ ]
57
+ } # => Zoe, Qin, Axe, Zak, Tam
58
+ ```
2
59
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/put`. To experiment with that code, run `bin/console` for an interactive prompt.
60
+ The above will return everyone in the right order. This has a few drawbacks,
61
+ though:
62
+
63
+ * Unless you're already familiar with this pattern that nobody's bothered to
64
+ give a name before, this code isn't very expressive. As a result, each line
65
+ is almost begging for a code comment above it to explain its intent
66
+ * Ternary operators are confusing, especially with predicate methods like
67
+ `rubyist?` and especially when returning [magic
68
+ number](https://en.wikipedia.org/wiki/Magic_number_(programming))'s like `1` and
69
+ `0`.
70
+ * Any `nil` values will result in a bad time. If a person's `age` is nil, you'll
71
+ get "_undefined method `*' for nil:NilClass_" `NoMethodError`
72
+ * Relatedly, if any two items aren't comparable (e.g. `<=>` returns nil), you'll
73
+ be greeted with an inscrutable `ArgumentError` that just says "_comparison of
74
+ Array with Array failed_"
75
+
76
+ Here's the same code example if you put Put in there:
77
+
78
+ ```ruby
79
+ people.sort_by { |person|
80
+ [
81
+ (Put.first if person.rubyist?),
82
+ Put.desc(person.age),
83
+ Put.asc(person.name)
84
+ ]
85
+ } # => Zoe, Qin, Axe, Zak, Tam
86
+ ```
87
+
88
+ The Put gem solves every one of the above issues:
89
+
90
+ * Put's methods have actual names. In fact, let's just call this the "Put
91
+ pattern" while we're at it
92
+ * No ternaries necessary
93
+ * It's quite `nil` friendly
94
+ * It ships with a `Put.debug` method that helps you introspect those
95
+ impenetrable `ArgumentError` messages whenever any two values turn out not to
96
+ be comparable
97
+
98
+ After reading this, your teammates are sure be glad they put you in charge of
99
+ putting little gems like Put in the Gemfile.
100
+
101
+ ## When you Put it that way
102
+
103
+ Put's API is short and sweet. In fact, you've already put up with most of it.
104
+
105
+ ### Put.first
106
+
107
+ When a particular condition indicates an item should go to the top of a list,
108
+ you'll want to designate a position in your mapped `sort_by` arrays to return
109
+ either `Put.first` or `nil`, like this:
110
+
111
+ ```ruby
112
+ [42, 12, 65, 99, 49].sort_by { |n|
113
+ [(Put.first if n.odd?)]
114
+ } # => 65, 99, 49, 42, 12
115
+ ```
116
+
117
+ ### Put.last
118
+
119
+ When items that meet a certain condition should go to the bottom of the list,
120
+ you can do the same sort of conditional expression with `Put.last`:
121
+
122
+ ```ruby
123
+ %w[Jin drinks Gin on Gym day].sort_by { |s|
124
+ [(Put.last unless s.match?(/[A-Z]/))]
125
+ } # => ["Jin", "Gin", "Gym", "drinks", "on", "day"]
126
+ ```
127
+
128
+ ### Put.asc(value, nils_first: false)
129
+
130
+ The `Put.asc` method provides a nil-safe way to sort a value in ascending order:
131
+
132
+ ```ruby
133
+ %w[The quick brown fox].sort_by { |s|
134
+ [Put.asc(s)]
135
+ } # => ["The", "brown", "fox", "quick"]
136
+ ```
137
+
138
+ It also supports an optional `nils_first` keyword argument that defaults to
139
+ false (translation: nils are sorted last by default), which looks like this:
140
+
141
+ ```ruby
142
+ [3, nil, 1, 5].sort_by { |n|
143
+ [Put.asc(n, nils_first: true)]
144
+ } # => [nil, 1, 3, 5]
145
+ ```
146
+
147
+ ### Put.desc(value, nils_first: false)
148
+
149
+ The opposite of `Put.asc` is `Put.desc`, and it works as you might suspect:
150
+
151
+ ```ruby
152
+ %w[Aardvark Zebra].sort_by { |s|
153
+ [Put.desc(s)]
154
+ } # => ["Zebra", "Aardvark"]
155
+ ```
156
+
157
+ And also like `Put.asc`, `Put.desc` has an optional `nils_first` keyword
158
+ argument when you want nils on top:
159
+
160
+ ```ruby
161
+ [1, nil, 2, 3].sort_by { |n|
162
+ [Put.desc(n, nils_first: true)]
163
+ } # => [nil, 3, 2, 1]
164
+ ```
165
+
166
+ ### Put.anywhere
167
+
168
+ You're sorting stuff, so naturally _order matters_. But when building a compound
169
+ `sort_by` expression, order matters less as you add more and more tiebreaking
170
+ criteria. In fact, sometimes shuffling items is the more appropriate than
171
+ leaving things in their original order. Enter `Put.anywhere`, which can be
172
+ called without any argument at any index in the mapped sorting array:
4
173
 
5
- TODO: Delete this and the text above, and describe your gem
174
+ ```ruby
175
+ [1, 3, 4, 7, 8, 9].sort_by { |n|
176
+ [
177
+ (Put.first if n.even?),
178
+ Put.anywhere
179
+ ]
180
+ } # => [8, 4, 1, 7, 9, 3]
181
+ ```
6
182
 
7
- ## Installation
183
+ ### Put.nils_first(value)
8
184
 
9
- Install the gem and add to the application's Gemfile by executing:
185
+ If you're sorting items and you know some not-comparable `nil` values are going
186
+ to appear, you can put all the nils on top with `Put.nil_first(value)`. Note
187
+ that _unlike_ `Put.asc` and `Put.desc`, it won't actually sort the values—it'll
188
+ just pull all the nils up!
10
189
 
11
- $ bundle add put
190
+ ```ruby
191
+ [:fun, :stuff, nil, :here].sort_by { |val|
192
+ [Put.nils_first(val)]
193
+ } # => [nil, :fun, :stuff, :here]
194
+ ```
12
195
 
13
- If bundler is not being used to manage dependencies, install the gem by executing:
196
+ ### Put.nils_last(value)
14
197
 
15
- $ gem install put
198
+ As you might be able to guess, `Put.nils_last` puts the nils last:
16
199
 
17
- ## Usage
200
+ ```ruby
201
+ [:every, nil, :counts].sort_by { |val|
202
+ [Put.nils_last(val)]
203
+ } # => [:every, :counts, nil]
204
+ ```
18
205
 
19
- TODO: Write usage instructions here
206
+ ### Put.debug(sorting_arrays)
20
207
 
21
- ## Development
208
+ If you see "comparison of Array with Array failed" and you don't have any idea
209
+ what is going on, try debugging by changing `sort_by` to `map` and passing it
210
+ to `Put.debug`.
22
211
 
23
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
212
+ For an interactive example of how to debug this issue with `Put.debug`, take a
213
+ look [at this test case](/test/put_test.rb#L53-L98).
24
214
 
25
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
215
+ ## Put your hands together! 👏
26
216
 
27
- ## Contributing
217
+ Many thanks to [Matt Jones](https://github.com/al2o3cr) and [Matthew
218
+ Draper](https://github.com/matthewd) for answering a bunch of obscure questions
219
+ about comparisons in Ruby and implementing the initial prototype, respectively.
220
+ 👏👏👏
28
221
 
29
- Bug reports and pull requests are welcome on GitHub at https://github.com/searls/put.
222
+ ## Code of Conduct
30
223
 
31
- ## License
32
-
33
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
224
+ This project follows Test Double's [code of
225
+ conduct](https://testdouble.com/code-of-conduct) for all community interactions,
226
+ including (but not limited to) one-on-one communications, public posts/comments,
227
+ code reviews, pull requests, and GitHub issues. If violations occur, Test Double
228
+ will take any action they deem appropriate for the infraction, up to and
229
+ including blocking a user from the organization's repositories.
data/Rakefile CHANGED
@@ -1,12 +1,10 @@
1
- # frozen_string_literal: true
2
-
3
1
  require "bundler/gem_tasks"
4
2
  require "rake/testtask"
5
3
 
6
4
  Rake::TestTask.new(:test) do |t|
7
5
  t.libs << "test"
8
6
  t.libs << "lib"
9
- t.test_files = FileList["test/**/test_*.rb"]
7
+ t.test_files = FileList["test/**/*_test.rb"]
10
8
  end
11
9
 
12
10
  require "standard/rake"
data/lib/put/debug.rb ADDED
@@ -0,0 +1,45 @@
1
+ module Put
2
+ class Debug
3
+ Result = Struct.new(:success?, :incomparables, keyword_init: true)
4
+ Incomparable = Struct.new(
5
+ :sorting_index, :left, :left_index, :left_value,
6
+ :right, :right_index, :right_value, keyword_init: true
7
+ ) {
8
+ def inspect
9
+ both_puts_things = left.is_a?(PutsThing) && right.is_a?(PutsThing)
10
+ left_desc = (both_puts_things ? left_value : left).inspect
11
+ right_desc = (both_puts_things ? right_value : right).inspect
12
+ "Sorting comparator at index #{sorting_index} failed, because items at indices #{left_index} and #{right_index} were not comparable. Their values were `#{left_desc}' and `#{right_desc}', respectively."
13
+ end
14
+ }
15
+
16
+ def call(sorting_arrays)
17
+ sorting_arrays.sort
18
+ Result.new(success?: true, incomparables: [])
19
+ rescue ArgumentError
20
+ # TODO this is O(n^lol)
21
+ incomparables = sorting_arrays.transpose.map.with_index { |comparables, sorting_index|
22
+ comparables.map.with_index { |comparable, comparable_index|
23
+ comparables.map.with_index { |other, other_index|
24
+ next if comparable_index == other_index
25
+ if (comparable <=> other).nil?
26
+ Incomparable.new(
27
+ sorting_index: sorting_index,
28
+ left: comparable,
29
+ left_index: comparable_index,
30
+ left_value: (comparable.value if comparable.is_a?(PutsThing)),
31
+ right: other,
32
+ right_index: other_index,
33
+ right_value: (other.value if other.is_a?(PutsThing))
34
+ )
35
+ end
36
+ }
37
+ }
38
+ }.flatten.compact.uniq { |inc|
39
+ # Remove dupes where two items are incomparable in both <=> directions:
40
+ [inc.sorting_index] + [inc.left_index, inc.right_index].sort
41
+ }
42
+ Result.new(success?: false, incomparables: incomparables)
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,12 @@
1
+ module Put
2
+ module NilExtension
3
+ def <=>(other)
4
+ if ::Put::PutsThing === other
5
+ -(other <=> self)
6
+ else
7
+ super
8
+ end
9
+ end
10
+ end
11
+ ::NilClass.prepend(NilExtension)
12
+ end
@@ -0,0 +1,13 @@
1
+ module Put
2
+ class PutsThing
3
+ class Anywhere < PutsThing
4
+ def initialize(seed)
5
+ @random = seed.nil? ? Random.new : Random.new(seed)
6
+ end
7
+
8
+ def value
9
+ @random.rand
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,6 @@
1
+ module Put
2
+ class PutsThing
3
+ class Ascending < InOrder
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,9 @@
1
+ module Put
2
+ class PutsThing
3
+ class Descending < InOrder
4
+ def reverse?
5
+ true
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Put
2
+ class PutsThing
3
+ class First < PutsThing
4
+ def value
5
+ -Float::INFINITY
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,16 @@
1
+ module Put
2
+ class PutsThing
3
+ class InOrder < PutsThing
4
+ def initialize(value, nils_first:)
5
+ @value = value
6
+ @nils_first = nils_first
7
+ end
8
+
9
+ attr_reader :value
10
+
11
+ def nils_first?
12
+ @nils_first
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,13 @@
1
+ module Put
2
+ class PutsThing
3
+ class Last < PutsThing
4
+ def value
5
+ Float::INFINITY
6
+ end
7
+
8
+ def nils_first?
9
+ true
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,17 @@
1
+ module Put
2
+ class PutsThing
3
+ class NilOrder < PutsThing
4
+ def initialize(value)
5
+ @value = value
6
+ end
7
+
8
+ def value
9
+ if @value.nil?
10
+ nil
11
+ else
12
+ 0
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,9 @@
1
+ module Put
2
+ class PutsThing
3
+ class NilsFirst < NilOrder
4
+ def nils_first?
5
+ true
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Put
2
+ class PutsThing
3
+ class NilsLast < NilOrder
4
+ def nils_first?
5
+ false
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,27 @@
1
+ module Put
2
+ class PutsThing
3
+ def <=>(other)
4
+ if value.nil? && (other.nil? || other&.value.nil?)
5
+ 0
6
+ elsif value.nil?
7
+ nils_first? ? -1 : 1
8
+ elsif other.nil? || other&.value.nil?
9
+ nils_first? ? 1 : -1
10
+ elsif other && !other.reverse?
11
+ value <=> other.value
12
+ elsif other&.reverse?
13
+ other.value <=> value
14
+ else
15
+ value <=> 0
16
+ end
17
+ end
18
+
19
+ def reverse?
20
+ false
21
+ end
22
+
23
+ def nils_first?
24
+ false
25
+ end
26
+ end
27
+ end
data/lib/put/version.rb CHANGED
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
- class Put
4
- VERSION = "0.0.1"
1
+ module Put
2
+ VERSION = "0.1.0"
5
3
  end
data/lib/put.rb CHANGED
@@ -1,38 +1,47 @@
1
+ require_relative "put/debug"
1
2
  require_relative "put/version"
3
+ require_relative "put/nil_ext"
4
+ require_relative "put/puts_thing"
5
+ require_relative "put/puts_thing/anywhere"
6
+ require_relative "put/puts_thing/first"
7
+ require_relative "put/puts_thing/last"
8
+ require_relative "put/puts_thing/in_order"
9
+ require_relative "put/puts_thing/ascending"
10
+ require_relative "put/puts_thing/descending"
11
+ require_relative "put/puts_thing/nil_order"
12
+ require_relative "put/puts_thing/nils_first"
13
+ require_relative "put/puts_thing/nils_last"
2
14
 
3
- class Put
15
+ module Put
4
16
  def self.first
5
- First
17
+ @@first ||= PutsThing::First.new.freeze
6
18
  end
7
19
 
8
20
  def self.last
9
- Last
21
+ @@last ||= PutsThing::Last.new.freeze
10
22
  end
11
23
 
12
- def initialize(value)
13
- @value = value
24
+ def self.desc(value, nils_first: false)
25
+ PutsThing::Descending.new(value, nils_first: nils_first)
14
26
  end
15
27
 
16
- First = new(-1).freeze
17
- Last = new(1).freeze
28
+ def self.asc(value, nils_first: false)
29
+ PutsThing::Ascending.new(value, nils_first: nils_first)
30
+ end
31
+
32
+ def self.nils_first(value)
33
+ PutsThing::NilsFirst.new(value)
34
+ end
18
35
 
19
- def <=>(other)
20
- @value <=> if other
21
- other.value
22
- else
23
- 0
24
- end
36
+ def self.nils_last(value)
37
+ PutsThing::NilsLast.new(value)
25
38
  end
26
39
 
27
- module NilExtension
28
- def <=>(other)
29
- if ::Put === other
30
- -(other <=> self)
31
- else
32
- super
33
- end
34
- end
40
+ def self.anywhere(seed: nil)
41
+ PutsThing::Anywhere.new(seed)
35
42
  end
36
43
 
37
- ::NilClass.prepend(NilExtension)
44
+ def self.debug(sorting_arrays)
45
+ Debug.new.call(sorting_arrays)
46
+ end
38
47
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: put
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Searls
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-09-21 00:00:00.000000000 Z
11
+ date: 2022-09-22 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email:
@@ -25,6 +25,18 @@ files:
25
25
  - README.md
26
26
  - Rakefile
27
27
  - lib/put.rb
28
+ - lib/put/debug.rb
29
+ - lib/put/nil_ext.rb
30
+ - lib/put/puts_thing.rb
31
+ - lib/put/puts_thing/anywhere.rb
32
+ - lib/put/puts_thing/ascending.rb
33
+ - lib/put/puts_thing/descending.rb
34
+ - lib/put/puts_thing/first.rb
35
+ - lib/put/puts_thing/in_order.rb
36
+ - lib/put/puts_thing/last.rb
37
+ - lib/put/puts_thing/nil_order.rb
38
+ - lib/put/puts_thing/nils_first.rb
39
+ - lib/put/puts_thing/nils_last.rb
28
40
  - lib/put/version.rb
29
41
  - put.gemspec
30
42
  - sig/put.rbs