jgomo3-func 0.1.0 → 1.0.1
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/.mailmap +1 -0
- data/CHANGELOG.md +15 -0
- data/Gemfile +0 -4
- data/Gemfile.lock +1 -1
- data/README.md +4 -0
- data/changelogs/releases/1.0.0.md +10 -0
- data/changelogs/releases/1.0.1.md +5 -0
- data/jgomo3-func.gemspec +5 -0
- data/lib/jgomo3/func/core_ext/object.rb +38 -17
- data/lib/jgomo3/func/version.rb +1 -1
- data/todo.org +86 -0
- metadata +64 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a9f0b16949f99318dbcb8a0439d9c441178b7858bc6c341be8a86e4b2c52e64e
|
4
|
+
data.tar.gz: c982c140130a959f36b2fc3e93a228bea440a648938c8ba430d24d11a6c01e1c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c92f1538e10821e7101510372b23886b59d351da6bfb49ab70794657f022867d9300d9504fdb83b7c2638b9777341142d8b807fbb7bd6a76170462ac9343b7a0
|
7
|
+
data.tar.gz: 74d4541b3fefe3aba9cc95b3dd5321d1f6902e2527f878513ea46bbab5b9022cb55281c4fdf3a3a2c7bcaeb2a671cb6f7821d6d2521f8fb96e65b807dd7f6edd
|
data/.mailmap
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Jesús Gómez <jgomo3@gmail.com>
|
data/CHANGELOG.md
CHANGED
@@ -3,6 +3,21 @@ All notable changes to this project will be documented in this file.
|
|
3
3
|
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
4
4
|
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
5
5
|
|
6
|
+
## 1.0.1 - 2023-04-07
|
7
|
+
### Fixed
|
8
|
+
- Bump the number just to force use of new artifact from Rubygems. I made a mistake publishing the previous version
|
9
|
+
|
10
|
+
---
|
11
|
+
## 1.0.0 - 2023-04-07
|
12
|
+
### Changed
|
13
|
+
- `then_if` accept non callable values and interpret them by their truth value
|
14
|
+
- `then_unless` accept non callable values and interpret them by their truth value
|
15
|
+
- `complement` will negate the receiver's values directly if it is not a callable
|
16
|
+
|
17
|
+
### Removed
|
18
|
+
- `complement` doesn't rais an ArgumentError when it's receiver was not a callable
|
19
|
+
|
20
|
+
---
|
6
21
|
## 0.1.0 - 2022-11-15
|
7
22
|
### Added
|
8
23
|
- Object extensions
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -0,0 +1,10 @@
|
|
1
|
+
## 1.0.0 - 2023-04-07
|
2
|
+
### Changed
|
3
|
+
- `then_if` accept non callable values and interpret them by their truth value
|
4
|
+
- `then_unless` accept non callable values and interpret them by their truth value
|
5
|
+
- `complement` will negate the receiver's values directly if it is not a callable
|
6
|
+
|
7
|
+
### Removed
|
8
|
+
- `complement` doesn't rais an ArgumentError when it's receiver was not a callable
|
9
|
+
|
10
|
+
---
|
data/jgomo3-func.gemspec
CHANGED
@@ -26,4 +26,9 @@ Gem::Specification.new do |spec|
|
|
26
26
|
spec.bindir = "exe"
|
27
27
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
28
28
|
spec.require_paths = ["lib"]
|
29
|
+
|
30
|
+
spec.add_development_dependency "codelog"
|
31
|
+
spec.add_development_dependency "rake", "~> 12.0"
|
32
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
33
|
+
spec.add_development_dependency 'yard'
|
29
34
|
end
|
@@ -10,49 +10,70 @@ class Object
|
|
10
10
|
Proc.new { self }
|
11
11
|
end
|
12
12
|
|
13
|
-
#
|
14
|
-
# callable object.
|
13
|
+
# If the receiver object is callabale, returns a Proc which negates
|
14
|
+
# the result of calling the argumented callable object.
|
15
|
+
#
|
16
|
+
# If it is not a callable, it returns it's negated value
|
15
17
|
#
|
16
18
|
# :positive?.complement.call(1) => false
|
17
19
|
# :nil?.complement.call(nil) => false
|
20
|
+
# false.complement => true
|
18
21
|
def complement
|
19
22
|
callable = case
|
20
23
|
when respond_to?(:call)
|
21
24
|
self
|
22
|
-
|
25
|
+
when respond_to?(:to_proc)
|
23
26
|
self.to_proc
|
24
27
|
end
|
25
|
-
|
26
|
-
|
27
|
-
case error.name
|
28
|
-
when :to_proc
|
29
|
-
raise ArgumentError, "Object is not 'Callable' so it can't have a complement function", caller
|
28
|
+
if callable
|
29
|
+
->(*args, **kwargs, &blk) { !callable.call(*args, **kwargs, &blk) }
|
30
30
|
else
|
31
|
-
|
31
|
+
!self
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
-
# Applies the given block to the object if the
|
35
|
+
# Applies the given block to the object if the criteria applied on
|
36
36
|
# it holds true. If not, it defaults to the object as if `then_if`
|
37
37
|
# was not called.
|
38
38
|
#
|
39
|
+
# The criteria can be a callable predicate, in which case the
|
40
|
+
# criteria is evaluated with the object as argument. It not, then
|
41
|
+
# the criteria will be interpreted by it's truth value.
|
42
|
+
#
|
39
43
|
# +1.then_if(:positive?) { _1 * 1000 } => 1_000
|
40
44
|
# -1.then_if(:positive?) { _1 * 1000 } => -1
|
41
|
-
|
42
|
-
|
45
|
+
# +1.then_if(true) { _1 * 1000 } => 1_000
|
46
|
+
# +1.then_if(false) { _1 * 1000 } => 1
|
47
|
+
def then_if(criteria)
|
48
|
+
callable = case
|
49
|
+
when criteria.respond_to?(:call)
|
50
|
+
criteria
|
51
|
+
when criteria.respond_to?(:to_proc)
|
52
|
+
criteria.to_proc
|
53
|
+
end
|
54
|
+
|
55
|
+
condition = callable ? callable.call(self) : criteria
|
56
|
+
|
57
|
+
if condition
|
43
58
|
yield self
|
44
59
|
else
|
45
60
|
self
|
46
61
|
end
|
47
62
|
end
|
48
63
|
|
49
|
-
# Applies the given block to the object if the
|
64
|
+
# Applies the given block to the object if the criteria applied on
|
50
65
|
# it doesn't hold true. If not, it defaults to the object as if
|
51
66
|
# `then_unless` was not called.
|
52
67
|
#
|
53
|
-
#
|
54
|
-
#
|
55
|
-
|
56
|
-
|
68
|
+
# The criteria can be a callable predicate, in which case the
|
69
|
+
# criteria is evaluated with the object as argument. It not, then
|
70
|
+
# the criteria will be interpreted by it's truth value.
|
71
|
+
#
|
72
|
+
# +1.then_unless(:positive?) { _1 * 1000 } => 1
|
73
|
+
# -1.then_unless(:positive?) { _1 * 1000 } => -1_000
|
74
|
+
# +1.then_unless(false) { _1 * 1000 } => 1_000
|
75
|
+
# +1.then_unless(true) { _1 * 1000 } => 1
|
76
|
+
def then_unless(criteria, &block)
|
77
|
+
then_if(criteria.complement, &block)
|
57
78
|
end
|
58
79
|
end
|
data/lib/jgomo3/func/version.rb
CHANGED
data/todo.org
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
#+title: Potential changes
|
2
|
+
#+author: Jesús Gómez <jgomo3@gmail.com>
|
3
|
+
* TODO Define alias yield_self_if of then_if (and for unless case too)
|
4
|
+
* TODO Explain in API and README that for cases with both ~if~ and ~else~ clauses, it is better to just avoid these functions
|
5
|
+
* TODO Define nil_if and nil_unless
|
6
|
+
For the pattern ~object.then_if(condition){ nil }~, this could be used
|
7
|
+
instead: ~object.nil_if(condition)~.
|
8
|
+
|
9
|
+
This pattern appears when chaining with the "safe navigation operator" (&.). E.g:
|
10
|
+
|
11
|
+
#+begin_ruby
|
12
|
+
object.tx_1.nil_if(condition)&.tx_2&._&._&.tx_3
|
13
|
+
#+end_ruby
|
14
|
+
* TODO Define map_if and map_unless
|
15
|
+
Applies the block to the processed element only if the condition is
|
16
|
+
true.
|
17
|
+
|
18
|
+
~data.map_if(condition){ f(_1) }~ would be equivalent to:
|
19
|
+
|
20
|
+
#+begin_ruby
|
21
|
+
data.map{ condition(_1) ? f(_1) : _1 }
|
22
|
+
#+end_ruby
|
23
|
+
|
24
|
+
Not the same to neither of the following patterns:
|
25
|
+
|
26
|
+
#+begin_ruby
|
27
|
+
data.filter{ condition(_1) }.map{ f_1 }
|
28
|
+
data.map{ f_1 }.filter{ condition(_1) }
|
29
|
+
#+end_ruby
|
30
|
+
|
31
|
+
~map_if~ and ~map~ will produce collection of the same
|
32
|
+
cardinality. ~filter{}.map{}~ or ~map{}.filter{}~ can produce
|
33
|
+
collection with lower cardinality of ~map~.
|
34
|
+
|
35
|
+
* TODO Define each_if and each_unless
|
36
|
+
In the same spirit as the other functions of this gem,
|
37
|
+
~data.each_if(condition) { f(_1) }~ should be the same as:
|
38
|
+
|
39
|
+
#+begin_ruby
|
40
|
+
data.each do
|
41
|
+
if condition(_1)
|
42
|
+
f(_1)
|
43
|
+
else
|
44
|
+
_1
|
45
|
+
end
|
46
|
+
end
|
47
|
+
#+end_ruby
|
48
|
+
|
49
|
+
It should also support the other forms of ~each~ where it receives
|
50
|
+
arguments that will be "appended" to the enumerator call, and the form
|
51
|
+
where it doesn't receive nor arguments neither block.
|
52
|
+
|
53
|
+
In all cases, it should be in a way that "makes sense".
|
54
|
+
|
55
|
+
* TODO Define tap_if and tap_unless
|
56
|
+
|
57
|
+
This one is the easiest to "understand" as it can be read as "make
|
58
|
+
side effect if ...".
|
59
|
+
|
60
|
+
* TODO Merge procer default to_proc implementation as an explicit call
|
61
|
+
|
62
|
+
[[../procer/ge][../proce.gemspec]] defines a default =to_proc= to all objects. If you
|
63
|
+
don't want to add that behaviour to your system, you can use this
|
64
|
+
proposed method to explicitly as for the default procer propose.
|
65
|
+
|
66
|
+
The idea... With procer, you can do:
|
67
|
+
|
68
|
+
#+begin_ruby
|
69
|
+
['1', 2, 3 '4', '5'].filter(&Numeric) # => [2, 3]
|
70
|
+
#+end_ruby
|
71
|
+
|
72
|
+
Because *procer* defines a default ~to_proc~ method for classes, which
|
73
|
+
is to compare the class with it's argument using the "Case Equality
|
74
|
+
(~===~)" operator.
|
75
|
+
|
76
|
+
But without procer, this new method, let's say it is called =procer=,
|
77
|
+
we could do:
|
78
|
+
|
79
|
+
#+begin_ruby
|
80
|
+
# Option 1
|
81
|
+
['1', 2, 3 '4', '5'].filter(&procer(Numeric)) # => [2, 3]
|
82
|
+
|
83
|
+
# Option 2
|
84
|
+
['1', 2, 3 '4', '5'].filter(&Numeric.procer) # => [2, 3]
|
85
|
+
#+end_ruby
|
86
|
+
|
metadata
CHANGED
@@ -1,15 +1,71 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jgomo3-func
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jesús Gómez
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
12
|
-
dependencies:
|
11
|
+
date: 2023-04-08 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: codelog
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '12.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '12.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: yard
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
13
69
|
description:
|
14
70
|
email:
|
15
71
|
- jgomo3@gmail.com
|
@@ -18,6 +74,7 @@ extensions: []
|
|
18
74
|
extra_rdoc_files: []
|
19
75
|
files:
|
20
76
|
- ".gitignore"
|
77
|
+
- ".mailmap"
|
21
78
|
- ".rspec"
|
22
79
|
- ".travis.yml"
|
23
80
|
- CHANGELOG.md
|
@@ -33,12 +90,15 @@ files:
|
|
33
90
|
- changelogs/header.txt
|
34
91
|
- changelogs/releases/.gitkeep
|
35
92
|
- changelogs/releases/0.1.0.md
|
93
|
+
- changelogs/releases/1.0.0.md
|
94
|
+
- changelogs/releases/1.0.1.md
|
36
95
|
- changelogs/template.yml
|
37
96
|
- changelogs/unreleased/.gitkeep
|
38
97
|
- jgomo3-func.gemspec
|
39
98
|
- lib/jgomo3/func.rb
|
40
99
|
- lib/jgomo3/func/core_ext/object.rb
|
41
100
|
- lib/jgomo3/func/version.rb
|
101
|
+
- todo.org
|
42
102
|
homepage: https://github.com/jgomo3/jgomo3-func
|
43
103
|
licenses:
|
44
104
|
- MIT
|
@@ -61,7 +121,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
61
121
|
- !ruby/object:Gem::Version
|
62
122
|
version: '0'
|
63
123
|
requirements: []
|
64
|
-
rubygems_version: 3.
|
124
|
+
rubygems_version: 3.1.4
|
65
125
|
signing_key:
|
66
126
|
specification_version: 4
|
67
127
|
summary: Library of functions I find useful enough to be included always
|