ramda-ruby 0.12.0 → 0.14.0
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/CHANGELOG.md +12 -0
- data/README.md +69 -2
- data/ROADMAP.md +0 -9
- data/docs/FUNCTIONS.md +9 -0
- data/docs/FUNCTORS.md +39 -0
- data/lib/ramda/function.rb +22 -3
- data/lib/ramda/internal/class_which_respond_to.rb +17 -0
- data/lib/ramda/internal/dispatchable.rb +30 -2
- data/lib/ramda/internal/functors.rb +72 -1
- data/lib/ramda/internal/integrations.rb +48 -0
- data/lib/ramda/internal/transducers.rb +1 -30
- data/lib/ramda/internal/transducers/drop_repeats_transducer.rb +19 -0
- data/lib/ramda/internal/transducers/drop_repeats_with_transducer.rb +19 -0
- data/lib/ramda/internal/transducers/filter_transdurer.rb +19 -0
- data/lib/ramda/internal/transducers/map_transducer.rb +15 -0
- data/lib/ramda/internal/transducers/take_transducer.rb +21 -0
- data/lib/ramda/list.rb +78 -27
- data/lib/ramda/logic.rb +17 -5
- data/lib/ramda/math.rb +32 -1
- data/lib/ramda/object.rb +14 -1
- data/lib/ramda/string.rb +23 -4
- data/lib/ramda/version.rb +1 -1
- data/spec/ramda/function_spec.rb +20 -7
- data/spec/ramda/list_spec.rb +86 -20
- data/spec/ramda/logic_spec.rb +30 -0
- data/spec/ramda/math_spec.rb +29 -0
- data/spec/ramda/object_spec.rb +11 -0
- data/spec/ramda/string_spec.rb +43 -0
- data/spec/ramda_spec.rb +8 -0
- data/spec/spec_helper.rb +9 -1
- metadata +11 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a9c61500382b8a30650338a2359340adaa39ed58
|
4
|
+
data.tar.gz: b80d5832f21113ddb52436deecdde3971a44f2b4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 11b0927aa3a7d6170bebbf1f5e337d8df033701fa71261c01a55d5e9cbfb31cc72c2a78c7019dcdad7e503368a37165a1bae2cb15681a7f16027ed37f4347fe1
|
7
|
+
data.tar.gz: ef83e01457589590d595e90d78c1a67b283489fd33a4532c21d10f497471994d7660d24868b604767d2cecd5a3b7b65add056cf57d80111448e2314e95d00389
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,18 @@
|
|
1
1
|
Not Released
|
2
2
|
---------------
|
3
3
|
|
4
|
+
Added:
|
5
|
+
|
6
|
+
* (pending) uncurry_n
|
7
|
+
* [adjust](http://ramdajs.com/docs/#adjust)
|
8
|
+
* [drop_repeats](http://ramdajs.com/docs/#dropRepeats)
|
9
|
+
* [drop_repeats_with](http://ramdajs.com/docs/#dropRepeatsWith)
|
10
|
+
* [intersperse](http://ramdajs.com/docs/#intersperse)
|
11
|
+
* [mean](http://ramdajs.com/docs/#mean)
|
12
|
+
* [median](http://ramdajs.com/docs/#median)
|
13
|
+
* [to_string](http://ramdajs.com/docs/#toString)
|
14
|
+
* [where_eq](http://ramdajs.com/docs/#whereEq)
|
15
|
+
|
4
16
|
Release 0.12.0
|
5
17
|
---------------
|
6
18
|
|
data/README.md
CHANGED
@@ -4,7 +4,7 @@ Ramda Ruby
|
|
4
4
|
This is a ruby version of [Ramda Js](http://ramdajs.com) library.
|
5
5
|
|
6
6
|
[](http://badge.fury.io/rb/ramda-ruby)
|
7
|
-
[](docs/FUNCTIONS.md)
|
8
8
|
[](https://travis-ci.org/lazebny/ramda-ruby)
|
9
9
|
[](https://ci.appveyor.com/project/lazebny/ramda-ruby)
|
10
10
|
[](https://coveralls.io/r/lazebny/ramda-ruby)
|
@@ -59,6 +59,45 @@ Documentation
|
|
59
59
|
You can use Ramda [docs](http://ramdajs.com/docs/) as a documentation
|
60
60
|
or to check Ruby [examples](spec/ramda).
|
61
61
|
|
62
|
+
|
63
|
+
Algebraic structures
|
64
|
+
-------------
|
65
|
+
|
66
|
+
Methods which supports algebraic types:
|
67
|
+
|
68
|
+
* ap
|
69
|
+
* both
|
70
|
+
* chain
|
71
|
+
* complement
|
72
|
+
* either
|
73
|
+
* lift
|
74
|
+
* lift_n
|
75
|
+
* map
|
76
|
+
* pluck
|
77
|
+
|
78
|
+
Supported libraries ([comparison](docs/FUNCTORS.md)):
|
79
|
+
|
80
|
+
* [dry-monads](https://github.com/dry-rb/dry-monads)
|
81
|
+
* [kleisli](https://github.com/txus/kleisli)
|
82
|
+
|
83
|
+
dry-monads
|
84
|
+
|
85
|
+
works with ruby >= 2.1
|
86
|
+
|
87
|
+
kleisli works from this fork:
|
88
|
+
|
89
|
+
```ruby
|
90
|
+
|
91
|
+
gem 'kleisli', git: 'git@github.com:lazebny/kleisli.git', branch: 'ramda-ruby'
|
92
|
+
|
93
|
+
```
|
94
|
+
|
95
|
+
Differences:
|
96
|
+
|
97
|
+
* https://github.com/txus/kleisli/pull/28
|
98
|
+
* https://github.com/txus/kleisli/pull/29
|
99
|
+
|
100
|
+
|
62
101
|
Usage
|
63
102
|
-------------
|
64
103
|
|
@@ -112,6 +151,30 @@ Transducers:
|
|
112
151
|
|
113
152
|
```
|
114
153
|
|
154
|
+
With algebraic structures:
|
155
|
+
|
156
|
+
```ruby
|
157
|
+
|
158
|
+
# ap
|
159
|
+
R.ap(R.ap(Maybe.of(R.add), Maybe.of(3)), Maybe.of(5)) # Some(8)
|
160
|
+
|
161
|
+
# chain
|
162
|
+
R.chain(->(x) { Maybe.of(R.add(5, x)) }, Maybe.of(3)) # Some(8)
|
163
|
+
|
164
|
+
# map
|
165
|
+
R.map(R.add(3), Maybe.of(5)) # Some(8)
|
166
|
+
|
167
|
+
# lift
|
168
|
+
add_m = R.lift(R.add)
|
169
|
+
add_m.call(Maybe.of(3), Maybe.of(5)) # Some(8)
|
170
|
+
|
171
|
+
# lift_n
|
172
|
+
add_m = R.lift_n(3, -> (a, b, c) { a + b + c })
|
173
|
+
add_m.call(Maybe.of(3), Maybe.of(5), Maybe.of(10)) # Some(18)
|
174
|
+
|
175
|
+
```
|
176
|
+
|
177
|
+
|
115
178
|
Change exceptions handler:
|
116
179
|
|
117
180
|
```ruby
|
@@ -141,7 +204,7 @@ Enable debug mode:
|
|
141
204
|
|
142
205
|
# Example:
|
143
206
|
|
144
|
-
Ramda.filter(Ramda.curry(
|
207
|
+
Ramda.filter(Ramda.curry(:even?.to_proc, [1, 2, 3, 4])
|
145
208
|
|
146
209
|
# -> curry(#<Proc:0x...@/srv/app/spec/ramda/list_spec.rb:130 (lambda)>) # #<Proc:0x... (lambda)>
|
147
210
|
# -> curry(1) # false
|
@@ -152,6 +215,10 @@ Enable debug mode:
|
|
152
215
|
|
153
216
|
```
|
154
217
|
|
218
|
+
Resources
|
219
|
+
-------------------
|
220
|
+
* [Cleaner Ruby validations using the Either monad and Kleisli gem](https://blog.abevoelker.com/you-got-haskell-in-my-ruby-cleaner-ruby-validations-using-either-monad-kleisli-gem/)
|
221
|
+
|
155
222
|
|
156
223
|
Benchmarks
|
157
224
|
-------------
|
data/ROADMAP.md
CHANGED
data/docs/FUNCTIONS.md
CHANGED
@@ -5,6 +5,7 @@
|
|
5
5
|
* (pending) math_mod
|
6
6
|
* (pending) pipe_p
|
7
7
|
* (pending) to_pairs_in
|
8
|
+
* (pending) uncurry_n
|
8
9
|
* (pending) values_in
|
9
10
|
|
10
11
|
Function
|
@@ -49,6 +50,7 @@ Function
|
|
49
50
|
List
|
50
51
|
------------
|
51
52
|
|
53
|
+
* [adjust](http://ramdajs.com/docs/#adjust)
|
52
54
|
* [all](http://ramdajs.com/docs/#all)
|
53
55
|
* [any](http://ramdajs.com/docs/#any)
|
54
56
|
* [aperture](http://ramdajs.com/docs/#aperture)
|
@@ -57,6 +59,8 @@ List
|
|
57
59
|
* [concat](http://ramdajs.com/docs/#concat)
|
58
60
|
* [contains](http://ramdajs.com/docs/#contains)
|
59
61
|
* [drop](http://ramdajs.com/docs/#drop)
|
62
|
+
* [drop_repeats](http://ramdajs.com/docs/#dropRepeats)
|
63
|
+
* [drop_repeats_with](http://ramdajs.com/docs/#dropRepeatsWith)
|
60
64
|
* [drop_while](http://ramdajs.com/docs/#dropWhile)
|
61
65
|
* [filter](http://ramdajs.com/docs/#filter) - transducer
|
62
66
|
* [find](http://ramdajs.com/docs/#find)
|
@@ -72,6 +76,7 @@ List
|
|
72
76
|
* [init](http://ramdajs.com/docs/#init)
|
73
77
|
* [insert](http://ramdajs.com/docs/#insert)
|
74
78
|
* [insert_all](http://ramdajs.com/docs/#insertAll)
|
79
|
+
* [intersperse](http://ramdajs.com/docs/#intersperse)
|
75
80
|
* [into](http://ramdajs.com/docs/#into)
|
76
81
|
* [join](http://ramdajs.com/docs/#join)
|
77
82
|
* [last](http://ramdajs.com/docs/#last)
|
@@ -134,6 +139,8 @@ Math
|
|
134
139
|
* [dec](http://ramdajs.com/docs/#dec)
|
135
140
|
* [divide](http://ramdajs.com/docs/#divide)
|
136
141
|
* [inc](http://ramdajs.com/docs/#inc)
|
142
|
+
* [mean](http://ramdajs.com/docs/#mean)
|
143
|
+
* [median](http://ramdajs.com/docs/#median)
|
137
144
|
* [modulo](http://ramdajs.com/docs/#modulo)
|
138
145
|
* [multiply](http://ramdajs.com/docs/#multiply)
|
139
146
|
* [negate](http://ramdajs.com/docs/#negate)
|
@@ -176,6 +183,7 @@ Object
|
|
176
183
|
* [values](http://ramdajs.com/docs/#values)
|
177
184
|
* [view](http://ramdajs.com/docs/#view)
|
178
185
|
* [where](http://ramdajs.com/docs/#where)
|
186
|
+
* [where_eq](http://ramdajs.com/docs/#whereEq)
|
179
187
|
|
180
188
|
|
181
189
|
Relation
|
@@ -209,6 +217,7 @@ String
|
|
209
217
|
* [split](http://ramdajs.com/docs/#split)
|
210
218
|
* [test](http://ramdajs.com/docs/#test)
|
211
219
|
* [to_lower](http://ramdajs.com/docs/#toLower)
|
220
|
+
* [to_string](http://ramdajs.com/docs/#toString)
|
212
221
|
* [to_upper](http://ramdajs.com/docs/#toUpper)
|
213
222
|
* [trim](http://ramdajs.com/docs/#trim)
|
214
223
|
|
data/docs/FUNCTORS.md
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
From [fantasy-land](https://github.com/fantasyland/fantasy-land)
|
2
|
+
|
3
|
+
[Functor](https://github.com/fantasyland/fantasy-land#functor)
|
4
|
+
---------------
|
5
|
+
map :: Functor f => f a ~> (a -> b) -> f b
|
6
|
+
|
7
|
+
[Apply](https://github.com/fantasyland/fantasy-land#apply)
|
8
|
+
---------------
|
9
|
+
ap :: Apply f => f a ~> f (a -> b) -> f b
|
10
|
+
|
11
|
+
[Applicative](https://github.com/fantasyland/fantasy-land#applicative)
|
12
|
+
---------------
|
13
|
+
of :: Applicative f => a -> f a
|
14
|
+
|
15
|
+
```javascript
|
16
|
+
|
17
|
+
Array.of = x => [x]
|
18
|
+
Either.of = x => Right(x)
|
19
|
+
Function.of = x => _ => x
|
20
|
+
Maybe.of = x => Just(x)
|
21
|
+
Task.of = x => new Task((_, res) => res(x))
|
22
|
+
|
23
|
+
```
|
24
|
+
|
25
|
+
[Chain](https://github.com/fantasyland/fantasy-land#Chain)
|
26
|
+
---------------
|
27
|
+
chain :: Chain m => m a ~> (a -> m b) -> m b
|
28
|
+
|
29
|
+
|
30
|
+
Comparison
|
31
|
+
---------------
|
32
|
+
|
33
|
+
|Language |Library |Functor |Apply |Applicative |Chain |
|
34
|
+
|-----------|----------------|--------|------|------------|------|
|
35
|
+
|Haskel |out of box |<$>|fmap|<*> |pure |>>= |
|
36
|
+
|JavaScript |ramda-fantasy |map |ap |of |chain |
|
37
|
+
|Ruby |dry-monads |fmap | |pure |bind |
|
38
|
+
|Ruby |kleisli |fmap |* | |> |
|
39
|
+
|Ruby |ramda-ruby |map |ap | |chain |
|
data/lib/ramda/function.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require_relative 'internal/class_which_respond_to'
|
1
2
|
require_relative 'internal/curried_method'
|
2
3
|
require_relative 'internal/dispatchable'
|
3
4
|
require_relative 'internal/function_with_arity'
|
@@ -8,6 +9,7 @@ module Ramda
|
|
8
9
|
module Function
|
9
10
|
extend ::Ramda::Internal::CurriedMethod
|
10
11
|
extend ::Ramda::Internal::Dispatchable
|
12
|
+
extend ::Ramda::Internal::ClassWhichRespondTo
|
11
13
|
|
12
14
|
# Returns a function that always returns the given value. Note that
|
13
15
|
# for non-primitives the value returned is a reference to the original
|
@@ -28,8 +30,19 @@ module Ramda
|
|
28
30
|
# [a -> b] -> [a] -> [b]
|
29
31
|
# Apply f => f (a -> b) -> f a -> f b
|
30
32
|
#
|
31
|
-
|
32
|
-
|
33
|
+
class_with_ap = class_which_responds_to(:ap)
|
34
|
+
class_with_m = class_which_responds_to(:*)
|
35
|
+
curried(:ap, &dispatchable(:ap, [::Array, class_with_ap, class_with_m]) do |apply_f, apply_x|
|
36
|
+
case apply_f
|
37
|
+
when ::Array
|
38
|
+
apply_f.flat_map { |fn| apply_x.map(&fn) }
|
39
|
+
|
40
|
+
when class_with_ap
|
41
|
+
apply_f.ap(apply_x)
|
42
|
+
|
43
|
+
when class_with_m
|
44
|
+
apply_f * apply_x
|
45
|
+
end
|
33
46
|
end)
|
34
47
|
|
35
48
|
# Applies function fn to the argument list args. This is useful
|
@@ -242,7 +255,13 @@ module Ramda
|
|
242
255
|
# Number -> (*... -> *) -> ([*]... -> [*])
|
243
256
|
#
|
244
257
|
curried_method(:lift_n) do |arity, fn, a, *xs|
|
245
|
-
|
258
|
+
# Applicative
|
259
|
+
if a.respond_to?(:ap)
|
260
|
+
xs.reduce(a.map(::Ramda.curry_n(arity, fn)), &::Ramda.ap)
|
261
|
+
# Array
|
262
|
+
else
|
263
|
+
([a] + xs).reduce([::Ramda.curry_n(arity, fn)], &::Ramda.ap)
|
264
|
+
end
|
246
265
|
end
|
247
266
|
|
248
267
|
# Creates a new function that, when invoked, caches the result of calling
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Ramda
|
2
|
+
module Internal
|
3
|
+
# Defines a class which responds to method and can be used in case construction
|
4
|
+
# for equality check.
|
5
|
+
module ClassWhichRespondTo
|
6
|
+
def class_which_responds_to(*method_names)
|
7
|
+
Class.new do
|
8
|
+
@method_names = method_names
|
9
|
+
|
10
|
+
def self.===(other)
|
11
|
+
@method_names.find(&other.method(:respond_to?))
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -3,7 +3,6 @@ module Ramda
|
|
3
3
|
# Dispatchable
|
4
4
|
# rubocop:disable Performance/CaseWhenSplat
|
5
5
|
# rubocop:disable Metrics/MethodLength
|
6
|
-
# rubocop:disable Style/GuardClause
|
7
6
|
module Dispatchable
|
8
7
|
# Returns a function that dispatches with different strategies based on the
|
9
8
|
# object in list position (last argument). If it is an array, executes [fn].
|
@@ -19,6 +18,7 @@ module Ramda
|
|
19
18
|
# - @param {Function} fn default ramda implementation
|
20
19
|
# - @return {Function} A function that dispatches on object in list position
|
21
20
|
#
|
21
|
+
# Works with fn(arity>1)
|
22
22
|
def dispatchable(method_names, described_types, xf = nil, &fn)
|
23
23
|
method_names = Array(method_names)
|
24
24
|
|
@@ -36,11 +36,39 @@ module Ramda
|
|
36
36
|
if method_name
|
37
37
|
xs.public_send(method_name, *args)
|
38
38
|
else
|
39
|
-
|
39
|
+
dispatchable_error(xs, method_name)
|
40
40
|
end
|
41
41
|
end
|
42
42
|
end
|
43
43
|
end
|
44
|
+
|
45
|
+
# Works with fn(arity=1)
|
46
|
+
def dispatchable1(method_names, described_types, xf = nil, &fn)
|
47
|
+
method_names = Array(method_names)
|
48
|
+
|
49
|
+
FunctionWithArity.call(fn.arity) do |xs|
|
50
|
+
case xs
|
51
|
+
when *described_types # default behaviour
|
52
|
+
yield(xs)
|
53
|
+
|
54
|
+
when Proc # transducer behaviour
|
55
|
+
xf.call(xs)
|
56
|
+
|
57
|
+
else # method dispatch behaviour
|
58
|
+
method_name = method_names.find { |name| xs.respond_to?(name) }
|
59
|
+
|
60
|
+
if method_name
|
61
|
+
xs.public_send(method_name)
|
62
|
+
else
|
63
|
+
dispatchable_error(xs, method_name)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def dispatchable_error(xs, method_name)
|
70
|
+
raise ArgumentError, "Unexpected type #{xs.class} in method: #{method_name}"
|
71
|
+
end
|
44
72
|
end
|
45
73
|
end
|
46
74
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Ramda
|
2
|
-
module
|
2
|
+
module Internal
|
3
3
|
module Functors
|
4
4
|
# `const` is a functor that effectively ignores the function given to `map`.
|
5
5
|
class Const
|
@@ -39,6 +39,77 @@ module Ramda
|
|
39
39
|
@value = value
|
40
40
|
end
|
41
41
|
end
|
42
|
+
|
43
|
+
# The `Maybe` type represents the possibility of some value or nothing.
|
44
|
+
class Maybe
|
45
|
+
def self.of(x)
|
46
|
+
Some.new(x)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Some value
|
50
|
+
class Some
|
51
|
+
attr_reader :value
|
52
|
+
|
53
|
+
def initialize(value)
|
54
|
+
@value = value
|
55
|
+
end
|
56
|
+
|
57
|
+
def ==(other)
|
58
|
+
instance_of?(other.class) && value == other.value
|
59
|
+
end
|
60
|
+
|
61
|
+
def ap(m)
|
62
|
+
m.map(@value)
|
63
|
+
end
|
64
|
+
|
65
|
+
def chain(f)
|
66
|
+
f.call(@value)
|
67
|
+
end
|
68
|
+
|
69
|
+
def map(f)
|
70
|
+
Maybe.of(f.call(@value))
|
71
|
+
end
|
72
|
+
|
73
|
+
def none?
|
74
|
+
false
|
75
|
+
end
|
76
|
+
|
77
|
+
def some?
|
78
|
+
true
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# None value
|
83
|
+
class None
|
84
|
+
attr_reader :value
|
85
|
+
|
86
|
+
def initialize(*); end
|
87
|
+
|
88
|
+
def ==(other)
|
89
|
+
instance_of?(other.class)
|
90
|
+
end
|
91
|
+
|
92
|
+
def ap(_m)
|
93
|
+
self
|
94
|
+
end
|
95
|
+
|
96
|
+
def chain(_f)
|
97
|
+
self
|
98
|
+
end
|
99
|
+
|
100
|
+
def map(_f)
|
101
|
+
self
|
102
|
+
end
|
103
|
+
|
104
|
+
def none?
|
105
|
+
true
|
106
|
+
end
|
107
|
+
|
108
|
+
def some?
|
109
|
+
false
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
42
113
|
end
|
43
114
|
end
|
44
115
|
end
|