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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b89810eb9aeb97f4360a2ef5cdfff495a46d2495
4
- data.tar.gz: 0ef2de2a457e9b889311f4af94a1b7f52c122abf
3
+ metadata.gz: a9c61500382b8a30650338a2359340adaa39ed58
4
+ data.tar.gz: b80d5832f21113ddb52436deecdde3971a44f2b4
5
5
  SHA512:
6
- metadata.gz: e7b826795f824e977f6f9c0b8d8d87bb482bc96b861f3c2ce4e0aa9d81c4c4f15efe3b5f5f0d32ee9abbb8f45342c9d0c548b0fdd9f579453508f8906edb7e12
7
- data.tar.gz: cd22adad8b7b4ce649844de486c1a0f6f67daebdd9901a5a9cf9ed8f2d50fab7895b5d903ff39990fd3f1723ebb9a1ef92cc5f7f9a2544ba7615c8074d821317
6
+ metadata.gz: 11b0927aa3a7d6170bebbf1f5e337d8df033701fa71261c01a55d5e9cbfb31cc72c2a78c7019dcdad7e503368a37165a1bae2cb15681a7f16027ed37f4347fe1
7
+ data.tar.gz: ef83e01457589590d595e90d78c1a67b283489fd33a4532c21d10f497471994d7660d24868b604767d2cecd5a3b7b65add056cf57d80111448e2314e95d00389
@@ -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
  [![Gem Version](https://badge.fury.io/rb/ramda-ruby.svg)](http://badge.fury.io/rb/ramda-ruby)
7
- [![Functions](https://img.shields.io/badge/Functions-178-green.svg)](docs/FUNCTIONS.md)
7
+ [![Functions](https://img.shields.io/badge/Functions-184-green.svg)](docs/FUNCTIONS.md)
8
8
  [![Travis badge](https://travis-ci.org/lazebny/ramda-ruby.svg?branch=master)](https://travis-ci.org/lazebny/ramda-ruby)
9
9
  [![AppVeyor status](https://ci.appveyor.com/api/projects/status/ponccdax7aj4ufw2?svg=true)](https://ci.appveyor.com/project/lazebny/ramda-ruby)
10
10
  [![Coverage Status](https://coveralls.io/repos/lazebny/ramda-ruby/badge.png)](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(->(n) { n.even? }), [1, 2, 3, 4])
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
@@ -3,15 +3,6 @@ Release 0.13.0
3
3
 
4
4
  Release 0.14.0
5
5
  ---------------
6
- * adjust
7
- * drop_repeats
8
- * drop_repeats_with
9
- * intersperse
10
- * mean
11
- * median
12
- * to_string
13
- * uncurry_n
14
- * where_eq
15
6
 
16
7
  Releaes 0.15.0
17
8
  ---------------
@@ -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
 
@@ -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 |
@@ -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
- curried(:ap, &dispatchable(:ap, ::Array) do |apply_f, apply_x|
32
- apply_f.flat_map { |fn| apply_x.map(&fn) }
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
- ([a] + xs).reduce([::Ramda.curry_n(arity, fn)], &::Ramda.ap)
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
- raise ArgumentError, "Unexpected type #{xs.class} in method: #{method_name}"
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 Internals
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