rubico 2.11.0 → 2.13.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.
Files changed (369) hide show
  1. package/README.md +16 -20
  2. package/Transducer.js +87 -72
  3. package/__.js +3 -3
  4. package/_internal/functionArrayAllSeries.js +4 -3
  5. package/_internal/functionObjectAllSeries.js +65 -0
  6. package/_internal/genericTransform.js +0 -1
  7. package/all.js +36 -16
  8. package/always.js +4 -4
  9. package/and.js +34 -26
  10. package/assign.js +5 -5
  11. package/compose.js +7 -6
  12. package/curry.js +48 -28
  13. package/dist/Transducer.es.js +1 -1
  14. package/dist/Transducer.es.min.js +1 -1
  15. package/dist/Transducer.js +1 -1
  16. package/dist/Transducer.min.js +1 -1
  17. package/dist/Transducer.mjs +1 -1
  18. package/dist/__.es.js +1 -1
  19. package/dist/__.es.min.js +1 -1
  20. package/dist/__.js +1 -1
  21. package/dist/__.min.js +1 -1
  22. package/dist/__.mjs +1 -1
  23. package/dist/all.es.js +112 -8
  24. package/dist/all.es.min.js +2 -2
  25. package/dist/all.js +112 -8
  26. package/dist/all.min.js +2 -2
  27. package/dist/all.mjs +112 -8
  28. package/dist/always.es.js +1 -1
  29. package/dist/always.es.min.js +1 -1
  30. package/dist/always.js +1 -1
  31. package/dist/always.min.js +1 -1
  32. package/dist/always.mjs +1 -1
  33. package/dist/and.es.js +1 -1
  34. package/dist/and.es.min.js +1 -1
  35. package/dist/and.js +1 -1
  36. package/dist/and.min.js +1 -1
  37. package/dist/and.mjs +1 -1
  38. package/dist/assign.es.js +1 -1
  39. package/dist/assign.es.min.js +1 -1
  40. package/dist/assign.js +1 -1
  41. package/dist/assign.min.js +1 -1
  42. package/dist/assign.mjs +1 -1
  43. package/dist/compose.es.js +1 -1
  44. package/dist/compose.es.min.js +1 -1
  45. package/dist/compose.js +1 -1
  46. package/dist/compose.min.js +1 -1
  47. package/dist/compose.mjs +1 -1
  48. package/dist/curry.es.js +1 -1
  49. package/dist/curry.es.min.js +1 -1
  50. package/dist/curry.js +1 -1
  51. package/dist/curry.min.js +1 -1
  52. package/dist/curry.mjs +1 -1
  53. package/dist/eq.es.js +1 -1
  54. package/dist/eq.es.min.js +1 -1
  55. package/dist/eq.js +1 -1
  56. package/dist/eq.min.js +1 -1
  57. package/dist/eq.mjs +1 -1
  58. package/dist/every.es.js +1 -1
  59. package/dist/every.es.min.js +1 -1
  60. package/dist/every.js +1 -1
  61. package/dist/every.min.js +1 -1
  62. package/dist/every.mjs +1 -1
  63. package/dist/filter.es.js +113 -19
  64. package/dist/filter.es.min.js +2 -2
  65. package/dist/filter.js +113 -19
  66. package/dist/filter.min.js +2 -2
  67. package/dist/filter.mjs +113 -19
  68. package/dist/flatMap.es.js +1 -1
  69. package/dist/flatMap.es.min.js +1 -1
  70. package/dist/flatMap.js +1 -1
  71. package/dist/flatMap.min.js +1 -1
  72. package/dist/flatMap.mjs +1 -1
  73. package/dist/forEach.es.js +1 -1
  74. package/dist/forEach.es.min.js +1 -1
  75. package/dist/forEach.js +1 -1
  76. package/dist/forEach.min.js +1 -1
  77. package/dist/forEach.mjs +1 -1
  78. package/dist/get.es.js +1 -1
  79. package/dist/get.es.min.js +1 -1
  80. package/dist/get.js +1 -1
  81. package/dist/get.min.js +1 -1
  82. package/dist/get.mjs +1 -1
  83. package/dist/gt.es.js +1 -1
  84. package/dist/gt.es.min.js +1 -1
  85. package/dist/gt.js +1 -1
  86. package/dist/gt.min.js +1 -1
  87. package/dist/gt.mjs +1 -1
  88. package/dist/gte.es.js +1 -1
  89. package/dist/gte.es.min.js +1 -1
  90. package/dist/gte.js +1 -1
  91. package/dist/gte.min.js +1 -1
  92. package/dist/gte.mjs +1 -1
  93. package/dist/lt.es.js +1 -1
  94. package/dist/lt.es.min.js +1 -1
  95. package/dist/lt.js +1 -1
  96. package/dist/lt.min.js +1 -1
  97. package/dist/lt.mjs +1 -1
  98. package/dist/lte.es.js +1 -1
  99. package/dist/lte.es.min.js +1 -1
  100. package/dist/lte.js +1 -1
  101. package/dist/lte.min.js +1 -1
  102. package/dist/lte.mjs +1 -1
  103. package/dist/map.es.js +1 -1
  104. package/dist/map.es.min.js +1 -1
  105. package/dist/map.js +1 -1
  106. package/dist/map.min.js +1 -1
  107. package/dist/map.mjs +1 -1
  108. package/dist/not.es.js +1 -1
  109. package/dist/not.es.min.js +1 -1
  110. package/dist/not.js +1 -1
  111. package/dist/not.min.js +1 -1
  112. package/dist/not.mjs +1 -1
  113. package/dist/omit.es.js +1 -1
  114. package/dist/omit.es.min.js +1 -1
  115. package/dist/omit.js +1 -1
  116. package/dist/omit.min.js +1 -1
  117. package/dist/omit.mjs +1 -1
  118. package/dist/or.es.js +1 -1
  119. package/dist/or.es.min.js +1 -1
  120. package/dist/or.js +1 -1
  121. package/dist/or.min.js +1 -1
  122. package/dist/or.mjs +1 -1
  123. package/dist/pick.es.js +1 -1
  124. package/dist/pick.es.min.js +1 -1
  125. package/dist/pick.js +1 -1
  126. package/dist/pick.min.js +1 -1
  127. package/dist/pick.mjs +1 -1
  128. package/dist/pipe.es.js +1 -1
  129. package/dist/pipe.es.min.js +1 -1
  130. package/dist/pipe.js +1 -1
  131. package/dist/pipe.min.js +1 -1
  132. package/dist/pipe.mjs +1 -1
  133. package/dist/reduce.es.js +1 -1
  134. package/dist/reduce.es.min.js +1 -1
  135. package/dist/reduce.js +1 -1
  136. package/dist/reduce.min.js +1 -1
  137. package/dist/reduce.mjs +1 -1
  138. package/dist/rubico.es.js +168 -79
  139. package/dist/rubico.es.min.js +2 -2
  140. package/dist/rubico.global.js +168 -79
  141. package/dist/rubico.global.min.js +2 -2
  142. package/dist/rubico.js +168 -79
  143. package/dist/rubico.min.js +2 -2
  144. package/dist/rubico.mjs +168 -79
  145. package/dist/set.es.js +1 -1
  146. package/dist/set.es.min.js +1 -1
  147. package/dist/set.js +1 -1
  148. package/dist/set.min.js +1 -1
  149. package/dist/set.mjs +1 -1
  150. package/dist/some.es.js +1 -1
  151. package/dist/some.es.min.js +1 -1
  152. package/dist/some.js +1 -1
  153. package/dist/some.min.js +1 -1
  154. package/dist/some.mjs +1 -1
  155. package/dist/switchCase.es.js +1 -1
  156. package/dist/switchCase.es.min.js +1 -1
  157. package/dist/switchCase.js +1 -1
  158. package/dist/switchCase.min.js +1 -1
  159. package/dist/switchCase.mjs +1 -1
  160. package/dist/tap.es.js +1 -1
  161. package/dist/tap.es.min.js +1 -1
  162. package/dist/tap.js +1 -1
  163. package/dist/tap.min.js +1 -1
  164. package/dist/tap.mjs +1 -1
  165. package/dist/thunkify.es.js +1 -1
  166. package/dist/thunkify.es.min.js +1 -1
  167. package/dist/thunkify.js +1 -1
  168. package/dist/thunkify.min.js +1 -1
  169. package/dist/thunkify.mjs +1 -1
  170. package/dist/transform.es.js +1 -3
  171. package/dist/transform.es.min.js +2 -2
  172. package/dist/transform.js +1 -3
  173. package/dist/transform.min.js +1 -1
  174. package/dist/transform.mjs +1 -3
  175. package/dist/tryCatch.es.js +1 -1
  176. package/dist/tryCatch.es.min.js +1 -1
  177. package/dist/tryCatch.js +1 -1
  178. package/dist/tryCatch.min.js +1 -1
  179. package/dist/tryCatch.mjs +1 -1
  180. package/dist/x/append.es.js +1 -1
  181. package/dist/x/append.es.min.js +1 -1
  182. package/dist/x/append.js +1 -1
  183. package/dist/x/append.min.js +1 -1
  184. package/dist/x/append.mjs +1 -1
  185. package/dist/x/callProp.es.js +1 -1
  186. package/dist/x/callProp.es.min.js +1 -1
  187. package/dist/x/callProp.js +1 -1
  188. package/dist/x/callProp.min.js +1 -1
  189. package/dist/x/callProp.mjs +1 -1
  190. package/dist/x/defaultsDeep.es.js +1 -1
  191. package/dist/x/defaultsDeep.es.min.js +1 -1
  192. package/dist/x/defaultsDeep.js +1 -1
  193. package/dist/x/defaultsDeep.min.js +1 -1
  194. package/dist/x/defaultsDeep.mjs +1 -1
  195. package/dist/x/differenceWith.es.js +1 -1
  196. package/dist/x/differenceWith.es.min.js +1 -1
  197. package/dist/x/differenceWith.js +1 -1
  198. package/dist/x/differenceWith.min.js +1 -1
  199. package/dist/x/differenceWith.mjs +1 -1
  200. package/dist/x/filterOut.es.js +113 -19
  201. package/dist/x/filterOut.es.min.js +2 -2
  202. package/dist/x/filterOut.js +113 -19
  203. package/dist/x/filterOut.min.js +2 -2
  204. package/dist/x/filterOut.mjs +113 -19
  205. package/dist/x/find.es.js +1 -1
  206. package/dist/x/find.es.min.js +1 -1
  207. package/dist/x/find.js +1 -1
  208. package/dist/x/find.min.js +1 -1
  209. package/dist/x/find.mjs +1 -1
  210. package/dist/x/findIndex.es.js +1 -1
  211. package/dist/x/findIndex.es.min.js +1 -1
  212. package/dist/x/findIndex.js +1 -1
  213. package/dist/x/findIndex.min.js +1 -1
  214. package/dist/x/findIndex.mjs +1 -1
  215. package/dist/x/first.es.js +1 -1
  216. package/dist/x/first.es.min.js +1 -1
  217. package/dist/x/first.js +1 -1
  218. package/dist/x/first.min.js +1 -1
  219. package/dist/x/first.mjs +1 -1
  220. package/dist/x/flatten.es.js +1 -1
  221. package/dist/x/flatten.es.min.js +1 -1
  222. package/dist/x/flatten.js +1 -1
  223. package/dist/x/flatten.min.js +1 -1
  224. package/dist/x/flatten.mjs +1 -1
  225. package/dist/x/groupBy.es.js +1 -1
  226. package/dist/x/groupBy.es.min.js +1 -1
  227. package/dist/x/groupBy.js +1 -1
  228. package/dist/x/groupBy.min.js +1 -1
  229. package/dist/x/groupBy.mjs +1 -1
  230. package/dist/x/has.es.js +1 -1
  231. package/dist/x/has.es.min.js +1 -1
  232. package/dist/x/has.js +1 -1
  233. package/dist/x/has.min.js +1 -1
  234. package/dist/x/has.mjs +1 -1
  235. package/dist/x/identity.es.js +1 -1
  236. package/dist/x/identity.es.min.js +1 -1
  237. package/dist/x/identity.js +1 -1
  238. package/dist/x/identity.min.js +1 -1
  239. package/dist/x/identity.mjs +1 -1
  240. package/dist/x/includes.es.js +1 -1
  241. package/dist/x/includes.es.min.js +1 -1
  242. package/dist/x/includes.js +1 -1
  243. package/dist/x/includes.min.js +1 -1
  244. package/dist/x/includes.mjs +1 -1
  245. package/dist/x/isDeepEqual.es.js +1 -1
  246. package/dist/x/isDeepEqual.es.min.js +1 -1
  247. package/dist/x/isDeepEqual.js +1 -1
  248. package/dist/x/isDeepEqual.min.js +1 -1
  249. package/dist/x/isDeepEqual.mjs +1 -1
  250. package/dist/x/isEmpty.es.js +1 -1
  251. package/dist/x/isEmpty.es.min.js +1 -1
  252. package/dist/x/isEmpty.js +1 -1
  253. package/dist/x/isEmpty.min.js +1 -1
  254. package/dist/x/isEmpty.mjs +1 -1
  255. package/dist/x/isEqual.es.js +1 -1
  256. package/dist/x/isEqual.es.min.js +1 -1
  257. package/dist/x/isEqual.js +1 -1
  258. package/dist/x/isEqual.min.js +1 -1
  259. package/dist/x/isEqual.mjs +1 -1
  260. package/dist/x/isFunction.es.js +1 -1
  261. package/dist/x/isFunction.es.min.js +1 -1
  262. package/dist/x/isFunction.js +1 -1
  263. package/dist/x/isFunction.min.js +1 -1
  264. package/dist/x/isFunction.mjs +1 -1
  265. package/dist/x/isIn.es.js +1 -1
  266. package/dist/x/isIn.es.min.js +1 -1
  267. package/dist/x/isIn.js +1 -1
  268. package/dist/x/isIn.min.js +1 -1
  269. package/dist/x/isIn.mjs +1 -1
  270. package/dist/x/isObject.es.js +1 -1
  271. package/dist/x/isObject.es.min.js +1 -1
  272. package/dist/x/isObject.js +1 -1
  273. package/dist/x/isObject.min.js +1 -1
  274. package/dist/x/isObject.mjs +1 -1
  275. package/dist/x/isString.es.js +1 -1
  276. package/dist/x/isString.es.min.js +1 -1
  277. package/dist/x/isString.js +1 -1
  278. package/dist/x/isString.min.js +1 -1
  279. package/dist/x/isString.mjs +1 -1
  280. package/dist/x/keys.es.js +1 -1
  281. package/dist/x/keys.es.min.js +1 -1
  282. package/dist/x/keys.js +1 -1
  283. package/dist/x/keys.min.js +1 -1
  284. package/dist/x/keys.mjs +1 -1
  285. package/dist/x/last.es.js +1 -1
  286. package/dist/x/last.es.min.js +1 -1
  287. package/dist/x/last.js +1 -1
  288. package/dist/x/last.min.js +1 -1
  289. package/dist/x/last.mjs +1 -1
  290. package/dist/x/maxBy.es.js +1 -1
  291. package/dist/x/maxBy.es.min.js +1 -1
  292. package/dist/x/maxBy.js +1 -1
  293. package/dist/x/maxBy.min.js +1 -1
  294. package/dist/x/maxBy.mjs +1 -1
  295. package/dist/x/noop.es.js +1 -1
  296. package/dist/x/noop.es.min.js +1 -1
  297. package/dist/x/noop.js +1 -1
  298. package/dist/x/noop.min.js +1 -1
  299. package/dist/x/noop.mjs +1 -1
  300. package/dist/x/pluck.es.js +1 -1
  301. package/dist/x/pluck.es.min.js +1 -1
  302. package/dist/x/pluck.js +1 -1
  303. package/dist/x/pluck.min.js +1 -1
  304. package/dist/x/pluck.mjs +1 -1
  305. package/dist/x/prepend.es.js +1 -1
  306. package/dist/x/prepend.es.min.js +1 -1
  307. package/dist/x/prepend.js +1 -1
  308. package/dist/x/prepend.min.js +1 -1
  309. package/dist/x/prepend.mjs +1 -1
  310. package/dist/x/size.es.js +1 -1
  311. package/dist/x/size.es.min.js +1 -1
  312. package/dist/x/size.js +1 -1
  313. package/dist/x/size.min.js +1 -1
  314. package/dist/x/size.mjs +1 -1
  315. package/dist/x/trace.es.js +1 -1
  316. package/dist/x/trace.es.min.js +1 -1
  317. package/dist/x/trace.js +1 -1
  318. package/dist/x/trace.min.js +1 -1
  319. package/dist/x/trace.mjs +1 -1
  320. package/dist/x/unionWith.es.js +1 -1
  321. package/dist/x/unionWith.es.min.js +1 -1
  322. package/dist/x/unionWith.js +1 -1
  323. package/dist/x/unionWith.min.js +1 -1
  324. package/dist/x/unionWith.mjs +1 -1
  325. package/dist/x/uniq.es.js +1 -1
  326. package/dist/x/uniq.es.min.js +1 -1
  327. package/dist/x/uniq.js +1 -1
  328. package/dist/x/uniq.min.js +1 -1
  329. package/dist/x/uniq.mjs +1 -1
  330. package/dist/x/unless.es.js +1 -1
  331. package/dist/x/unless.es.min.js +1 -1
  332. package/dist/x/unless.js +1 -1
  333. package/dist/x/unless.min.js +1 -1
  334. package/dist/x/unless.mjs +1 -1
  335. package/dist/x/values.es.js +1 -1
  336. package/dist/x/values.es.min.js +1 -1
  337. package/dist/x/values.js +1 -1
  338. package/dist/x/values.min.js +1 -1
  339. package/dist/x/values.mjs +1 -1
  340. package/dist/x/when.es.js +1 -1
  341. package/dist/x/when.es.min.js +1 -1
  342. package/dist/x/when.js +1 -1
  343. package/dist/x/when.min.js +1 -1
  344. package/dist/x/when.mjs +1 -1
  345. package/eq.js +29 -30
  346. package/es.js +168 -79
  347. package/every.js +16 -22
  348. package/filter.js +41 -78
  349. package/flatMap.js +16 -16
  350. package/forEach.js +14 -14
  351. package/get.js +3 -3
  352. package/gt.js +18 -25
  353. package/gte.js +22 -29
  354. package/index.js +168 -79
  355. package/lt.js +33 -31
  356. package/lte.js +24 -31
  357. package/map.js +43 -46
  358. package/not.js +12 -17
  359. package/or.js +34 -26
  360. package/package.json +1 -1
  361. package/pipe.js +6 -6
  362. package/reduce.js +62 -69
  363. package/some.js +13 -36
  364. package/switchCase.js +9 -9
  365. package/tap.js +7 -12
  366. package/thunkify.js +42 -12
  367. package/transform.js +62 -61
  368. package/tryCatch.js +4 -7
  369. package/_internal/add.js +0 -12
package/README.md CHANGED
@@ -23,7 +23,7 @@ const numbers = [1, 2, 3, 4, 5]
23
23
  pipe(numbers, [
24
24
  filter(isOdd),
25
25
  map(asyncSquare),
26
- console.log, // [1, 9, 25]
26
+ console.log,
27
27
  ])
28
28
  ```
29
29
 
@@ -94,32 +94,37 @@ Rubico is a library for [A]synchronous Functional Programming in JavaScript. The
94
94
 
95
95
  ```javascript
96
96
  const {
97
- // compose functions
97
+
98
+ // function composition
98
99
  pipe, compose, tap,
99
100
 
100
- // control flow
101
+ // conditional operators
101
102
  switchCase,
102
103
 
103
- // handle errors
104
+ // error handling
104
105
  tryCatch,
105
106
 
106
- // compose data
107
+ // data construction
107
108
  all, assign, get, set, pick, omit,
108
109
 
109
- // iterate
110
+ // iteration
110
111
  forEach,
111
112
 
112
- // transform data
113
+ // transformation
113
114
  map, filter, reduce, transform, flatMap,
114
115
 
115
- // compose predicates
116
- and, or, not, some, every,
116
+ // data testing
117
+ some, every,
118
+
119
+ // logical operators
120
+ and, or, not,
117
121
 
118
122
  // comparison operators
119
123
  eq, gt, lt, gte, lte,
120
124
 
121
125
  // partial application
122
126
  thunkify, always, curry, __,
127
+
123
128
  } = rubico
124
129
  ```
125
130
 
@@ -133,7 +138,7 @@ pipe(helloPromise, [ // helloPromise is resolved for 'hello'
133
138
  // the Promise returned from the async function is resolved
134
139
  // and the resolved value is passed to console.log
135
140
 
136
- console.log, // hello world
141
+ console.log,
137
142
  ])
138
143
  ```
139
144
 
@@ -151,7 +156,6 @@ const myDuplicatedSquaredObject = map(myObj, pipe([
151
156
  ]))
152
157
 
153
158
  console.log(myDuplicatedSquaredObject)
154
- // { a: [1, 1], b: [4, 4], c: [9, 9] }
155
159
  ```
156
160
 
157
161
  The Rubico operators are versatile and act on a wide range of vanilla JavaScript types to create declarative, extensible, and async-enabled function compositions. The same operator `map` can act on an array and also a `Map` data structure.
@@ -172,11 +176,6 @@ pipe(todoIDs, [
172
176
  response => response.json(),
173
177
 
174
178
  tap(console.log),
175
- // { userId: 1, id: 4, title: 'et porro tempora', completed: true }
176
- // { userId: 1, id: 1, title: 'delectus aut autem', completed: false }
177
- // { userId: 1, id: 3, title: 'fugiat veniam minus', completed: false }
178
- // { userId: 1, id: 2, title: 'quis ut nam facilis...', completed: false }
179
- // { userId: 1, id: 5, title: 'laboriosam mollitia...', completed: false }
180
179
  ])),
181
180
 
182
181
  // group the todos by userId in a new Map
@@ -201,9 +200,6 @@ pipe(todoIDs, [
201
200
  })),
202
201
 
203
202
  tap(console.log),
204
- // Map(1) {
205
- // 1 => [ { userId: 1, id: 4, title: 'et porro tempora', completed: true } ]
206
- // }
207
203
  ])
208
204
  ```
209
205
 
@@ -227,7 +223,7 @@ pipe(generateNumbers(), [
227
223
  Transducer.filter(isOdd),
228
224
  Transducer.map(asyncSquare),
229
225
  ), []),
230
- console.log, // [1, 9, 25]
226
+ console.log,
231
227
  ])
232
228
  ```
233
229
 
package/Transducer.js CHANGED
@@ -11,8 +11,44 @@ const __ = require('./_internal/placeholder')
11
11
  /**
12
12
  * @name Transducer
13
13
  *
14
+ * @synopsis
15
+ * ```coffeescript [specscript]
16
+ * type Reducer = (accumulator any, value any)=>(nextAccumulator Promise|any)
17
+ *
18
+ * type Transducer = Reducer=>Reducer
19
+ * ```
20
+ *
14
21
  * @description
15
- * Temporary repository of transducer functionality throughout rubico v1
22
+ * A transducer is a function that takes a `Reducer` and returns another `Reducer`. Transducers enable function chains with reducers - pass a reducer to a transducer to create a reducer with chained functionality. A `Reducer` is a function that defines a relationship between an accumulator and an item in a transformation, and can be used in a reducing operation, such as with Rubico's [reduce](/docs/reduce) or vanilla JavaScript [Array.prototype.reduce](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce).
23
+ *
24
+ * ```javascript [playground]
25
+ * const isOdd = number => number % 2 == 1
26
+ *
27
+ * const asyncSquare = async number => number ** 2
28
+ *
29
+ * const numbers = [1, 2, 3, 4, 5]
30
+ *
31
+ * const transducer = compose(
32
+ * Transducer.filter(isOdd),
33
+ * Transducer.map(asyncSquare)
34
+ * )
35
+ *
36
+ * const transformed = await transform(numbers, transducer, [])
37
+ *
38
+ * console.log(transformed)
39
+ * ```
40
+ *
41
+ * The following are the core building blocks for creating transducers with Rubico, and are offered through this [Transducer](/docs/Transducer) module.
42
+ *
43
+ * * [Transducer.map](/docs/Transducer.map)
44
+ * * [Transducer.filter](/docs/Transducer.filter)
45
+ * * [Transducer.flatMap](/docs/Transducer.flatMap)
46
+ * * [Transducer.forEach](/docs/Transducer.forEach)
47
+ * * [Transducer.passthrough](/docs/Transducer.passthrough)
48
+ * * [Transducer.tryCatch](/docs/Transducer.tryCatch)
49
+ *
50
+ * See also:
51
+ * * [Transducers Crash Course](/blog/transducers-crash-course)
16
52
  */
17
53
  const Transducer = {}
18
54
 
@@ -21,22 +57,20 @@ const Transducer = {}
21
57
  *
22
58
  * @synopsis
23
59
  * ```coffeescript [specscript]
24
- * type SyncOrAsyncReducer = (accumulator any, value any)=>(nextAccumulator Promise|any)
25
- * type Transducer = SyncOrAsyncReducer=>SyncOrAsyncReducer
26
- * type UnarySyncOrAsyncMapper = (element any)=>(resultElement Promise|any)
27
- *
28
- * mapper UnarySyncOrAsyncMapper
60
+ * type Reducer = (accumulator any, value any)=>(nextAccumulator Promise|any)
61
+ * type Transducer = Reducer=>Reducer
62
+ * type Mapper = (item any)=>(mappedItem Promise|any)
29
63
  *
30
- * Transducer.map(mapper) -> mappingTransducer Transducer
64
+ * Transducer.map(mapper Mapper) -> mappingTransducer Transducer
31
65
  * ```
32
66
  *
33
67
  * @description
34
- * Creates a mapping transducer. Elements of the transducer's reducing operation are transformed by the mapper function. It is possible to use an asynchronous mapper, however the reducing operation must support asynchronous execution. This library provides such implementations as [reduce](/docs/reduce) and [transform](/docs/transform).
68
+ * Creates a mapping [transducer](/blog/transducers-crash-course). Items of the transducer's reducing operation are transformed by the mapper function. It is possible to use an asynchronous mapper, however the reducing operation must support asynchronous execution. This library provides such implementations as [reduce](/docs/reduce) and [transform](/docs/transform).
35
69
  *
36
70
  * ```javascript [playground]
37
71
  * const square = number => number ** 2
38
72
  *
39
- * const concat = (array, element) => array.concat(element)
73
+ * const concat = (array, item) => array.concat(item)
40
74
  *
41
75
  * const mapSquare = Transducer.map(square)
42
76
  * // mapSquare is a transducer
@@ -45,23 +79,18 @@ const Transducer = {}
45
79
  * // now mapSquare is passed the reducer function concat; squareConcatReducer
46
80
  * // is a reducer with chained functionality square and concat
47
81
  *
48
- * console.log(
49
- * reduce([1, 2, 3, 4, 5], squareConcatReducer, [])
50
- * ) // [1, 4, 9, 16, 25]
82
+ * const squaredNumbersRubicoReduce = reduce([1, 2, 3, 4, 5], squareConcatReducer, [])
83
+ * console.log(squaredNumbersRubicoReduce)
51
84
  *
52
85
  * // the same squareConcatReducer is consumable with vanilla JavaScript
53
- * console.log(
54
- * [1, 2, 3, 4, 5].reduce(squareConcatReducer, [])
55
- * ) // [1, 4, 9, 16, 25]
86
+ * const squaredNumbersVanillaReduce = [1, 2, 3, 4, 5].reduce(squareConcatReducer, [])
87
+ * console.log(squaredNumbersVanillaReduce)
56
88
  *
57
89
  * // concat is implicit when transforming into arrays
58
- * console.log(
59
- * transform([1, 2, 3, 4, 5], Transducer.map(square), [])
60
- * ) // [1, 4, 9, 16, 25]
90
+ * const squaredNumbersTransform = transform([1, 2, 3, 4, 5], Transducer.map(square), [])
91
+ * console.log(squaredNumbersTransform)
61
92
  * ```
62
93
  *
63
- * Read more on [transducers](/blog/transducers-crash-course-rubico-v2).
64
- *
65
94
  * See also:
66
95
  * * [thunkify](/docs/thunkify)
67
96
  * * [Transducer.filter](/docs/Transducer.filter)
@@ -80,35 +109,31 @@ Transducer.map = function transducerMap(mapper) {
80
109
  *
81
110
  * @synopsis
82
111
  * ```coffeescript [specscript]
83
- * type SyncOrAsyncReducer = (accumulator any, value any)=>(nextAccumulator Promise|any)
84
- * type Transducer = SyncOrAsyncReducer=>SyncOrAsyncReducer
85
- * type UnarySyncOrAsyncPredicate = any=>Promise|boolean|any
112
+ * type Reducer = (accumulator any, value any)=>(nextAccumulator Promise|any)
113
+ * type Transducer = Reducer=>Reducer
114
+ * type Predicate = any=>Promise|boolean|any
86
115
  *
87
- * predicate UnarySyncOrAsyncPredicate
88
- *
89
- * Transducer.filter(predicate) -> filteringTransducer Transducer
116
+ * Transducer.filter(predicate Predicate) -> filteringTransducer Transducer
90
117
  * ```
91
118
  *
92
119
  * @description
93
- * Creates a filtering transducer. A filtering transducer filters out elements of its reducing operation if they test false by the predicate. It is possible to use an asynchronous predicate, however the reducing operation must support asynchronous execution. This library provides such implementations as [reduce](/docs/reduce) and [transform](/docs/transform).
120
+ * Creates a filtering [transducer](/blog/transducers-crash-course). A filtering transducer filters out items of its reducing operation if they test false by the predicate. It is possible to use an asynchronous predicate, however the reducing operation must support asynchronous execution. This library provides such implementations as [reduce](/docs/reduce) and [transform](/docs/transform).
94
121
  *
95
122
  * ```javascript [playground]
96
123
  * const isOdd = number => number % 2 == 1
97
124
  *
98
- * const concat = (array, element) => array.concat(element)
125
+ * const concat = (array, item) => array.concat(item)
99
126
  *
100
127
  * const concatOddNumbers = Transducer.filter(isOdd)(concat)
101
128
  *
102
129
  * const array = [1, 2, 3, 4, 5]
103
130
  *
104
131
  * const oddNumbers1 = array.reduce(concatOddNumbers, [])
105
- * console.log(oddNumbers1) // [1, 3, 5]
106
- *
107
132
  * const oddNumbers2 = transform(array, Transducer.filter(isOdd), [])
108
- * console.log(oddNumbers2) // [1, 3, 5]
109
- * ```
110
133
  *
111
- * Read more on [transducers](/blog/transducers-crash-course-rubico-v2).
134
+ * console.log(oddNumbers1)
135
+ * console.log(oddNumbers2)
136
+ * ```
112
137
  *
113
138
  * See also:
114
139
  * * [thunkify](/docs/thunkify)
@@ -128,30 +153,26 @@ Transducer.filter = function transducerFilter(predicate) {
128
153
  *
129
154
  * @synopsis
130
155
  * ```coffeescript [specscript]
131
- * type SyncOrAsyncReducer = (accumulator any, value any)=>(nextAccumulator Promise|any)
132
- * type Transducer = SyncOrAsyncReducer=>SyncOrAsyncReducer
156
+ * type Reducer = (accumulator any, value any)=>(nextAccumulator Promise|any)
157
+ * type Transducer = Reducer=>Reducer
133
158
  * type Monad = Array|String|Set|Generator|AsyncGenerator|{ flatMap: string }|{ chain: string }|Object
134
- * type UnarySyncOrAsyncFlatMapper = (element any)=>(monad Promise|Monad|any)
159
+ * type FlatMapper = (item any)=>(monad Promise|Monad|any)
135
160
  *
136
- * flatMapper UnarySyncOrAsyncFlatMapper
137
- *
138
- * Transducer.flatMap(flatMapper) -> flatMappingTransducer Transducer
161
+ * Transducer.flatMap(flatMapper FlatMapper) -> flatMappingTransducer Transducer
139
162
  * ```
140
163
  *
141
164
  * @description
142
- * Creates a flatMapping transducer. A flatMapping transducer applies the flatMapper function to each element of its reducing operation, concatenating the results of the flatMapper execution onto the accumulator. It is possible to use an asynchronous flatMapper, however the reducing operation must support asynchronous execution. This library provides such implementations as [reduce](/docs/reduce) and [transform](/docs/transform).
165
+ * Creates a flatMapping [transducer](/blog/transducers-crash-course). A flatMapping transducer applies the flatMapper function to each item of its reducing operation, concatenating the results of the flatMapper execution onto the accumulator. It is possible to use an asynchronous flatMapper, however the reducing operation must support asynchronous execution. This library provides such implementations as [reduce](/docs/reduce) and [transform](/docs/transform).
143
166
  *
144
167
  * ```javascript [playground]
145
168
  * const powers = number => [number, number ** 2, number ** 3]
146
169
  *
147
170
  * const numbers = [1, 2, 3, 4, 5]
148
171
  *
149
- * console.log(
150
- * transform(numbers, Transducer.flatMap(powers), [])
151
- * ) // [1, 1, 1, 2, 4, 8, 3, 9, 27, 4, 16, 64, 5, 25, 125]
152
- * ```
172
+ * const result = transform(numbers, Transducer.flatMap(powers), [])
153
173
  *
154
- * Read more on [transducers](/blog/transducers-crash-course-rubico-v2).
174
+ * console.log(result)
175
+ * ```
155
176
  *
156
177
  * See also:
157
178
  * * [thunkify](/docs/thunkify)
@@ -171,28 +192,25 @@ Transducer.flatMap = function transducerFlatMap(flatMapper) {
171
192
  *
172
193
  * @synopsis
173
194
  * ```coffeescript [specscript]
174
- * type SyncOrAsyncReducer = (accumulator any, value any)=>(nextAccumulator Promise|any)
175
- * type Transducer = SyncOrAsyncReducer=>SyncOrAsyncReducer
176
- * type UnarySyncOrAsyncCallback = (element any)=>Promise|undefined
177
- *
178
- * callback UnarySyncOrAsyncCallback
195
+ * type Reducer = (accumulator any, value any)=>(nextAccumulator Promise|any)
196
+ * type Transducer = Reducer=>Reducer
197
+ * type Callback = (item any)=>Promise|undefined
179
198
  *
180
- * Transducer.forEach(callback) -> forEachTransducer Transducer
199
+ * Transducer.forEach(callback Callback) -> forEachTransducer Transducer
181
200
  * ```
182
201
  *
183
202
  * @description
184
- * Executes a callback function for each element of a reducing operation, leaving the reducing operation unmodified. It is possible to use an asynchronous callback function, however the reducing operation must support asynchronous execution. This library provides such implementations as [reduce](/docs/reduce) and [transform](/docs/transform).
203
+ * Creates an iterative [transducer](/blog/transducers-crash-course). Executes a callback function for each item of a reducing operation, leaving each item unmodified. It is possible to use an asynchronous callback function, however the reducing operation must support asynchronous execution. This library provides such implementations as [reduce](/docs/reduce) and [transform](/docs/transform).
185
204
  *
186
205
  * ```javascript [playground]
187
206
  * const numbers = [1, 2, 3, 4, 5]
207
+ *
188
208
  * transform(numbers, compose(
189
209
  * Transducer.map(number => number ** 2),
190
- * Transducer.forEach(console.log), // 1 4 9 16 25
210
+ * Transducer.forEach(console.log),
191
211
  * ), null)
192
212
  * ```
193
213
  *
194
- * Read more on [transducers](/blog/transducers-crash-course-rubico-v2).
195
- *
196
214
  * See also:
197
215
  * * [thunkify](/docs/thunkify)
198
216
  * * [Transducer.map](/docs/Transducer.map)
@@ -211,14 +229,14 @@ Transducer.forEach = function transducerForEach(func) {
211
229
  *
212
230
  * @synopsis
213
231
  * ```coffeescript [specscript]
214
- * type SyncOrAsyncReducer = (accumulator any, value any)=>(nextAccumulator Promise|any)
215
- * type Transducer = SyncOrAsyncReducer=>SyncOrAsyncReducer
232
+ * type Reducer = (accumulator any, value any)=>(nextAccumulator Promise|any)
233
+ * type Transducer = Reducer=>Reducer
216
234
  *
217
- * Transducer.passthrough Transducer
235
+ * Transducer.passthrough -> Transducer
218
236
  * ```
219
237
  *
220
238
  * @description
221
- * Creates a pasthrough transducer. The passthrough transducer simply passes each element of the reducing operation through to the next downstream operation, leaving the reducing operation unmodified.
239
+ * Creates a pasthrough [transducer](/blog/transducers-crash-course). The passthrough transducer simply passes each item of the reducing operation through to the next downstream transducer, leaving each item unmodified.
222
240
  *
223
241
  * ```javascript [playground]
224
242
  * const createAsyncNumbers = async function* () {
@@ -229,11 +247,10 @@ Transducer.forEach = function transducerForEach(func) {
229
247
  * }
230
248
  * }
231
249
  *
232
- * transform(createAsyncNumbers(), Transducer.passthrough, [])
233
- * .then(console.log) // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
234
- * ```
250
+ * const numbers = await transform(createAsyncNumbers(), Transducer.passthrough, [])
235
251
  *
236
- * Read more on [transducers](/blog/transducers-crash-course-rubico-v2).
252
+ * console.log(numbers)
253
+ * ```
237
254
  *
238
255
  * See also:
239
256
  * * [thunkify](/docs/thunkify)
@@ -253,17 +270,17 @@ Transducer.passthrough = function transducerPassthrough(reducer) {
253
270
  *
254
271
  * @synopsis
255
272
  * ```coffeescript [specscript]
256
- * type SyncOrAsyncReducer = (accumulator any, value any)=>(nextAccumulator Promise|any)
257
- * type Transducer = SyncOrAsyncReducer=>SyncOrAsyncReducer
273
+ * type Reducer = (accumulator any, value any)=>(nextAccumulator Promise|any)
274
+ * type Transducer = Reducer=>Reducer
258
275
  *
259
- * transducerTryer Transducer
260
- * catcher (error Error, element any)=>Promise|any
261
- *
262
- * Transducer.tryCatch(transducerTryer, catcher) -> tryCatchTransducer Transducer
276
+ * Transducer.tryCatch(
277
+ * transducerTryer Transducer,
278
+ * catcher (error Error, item any)=>(Promise|any)
279
+ * ) -> tryCatchTransducer Transducer
263
280
  * ```
264
281
  *
265
282
  * @description
266
- * Creates an error handling transducer. The error handling transducer wraps a transducer and catches any errors thrown by the transducer with the catcher function. The catcher function is provided the error as well as the element for which the error was thrown. It is possible for either the transducer or the catcher to be asynchronous, however the reducing operation must support asynchronous execution. This library provides such implementations as [reduce](/docs/reduce) and [transform](/docs/transform).
283
+ * Creates an error handling [transducer](/blog/transducers-crash-course). The error handling transducer wraps a transducer and catches any errors thrown by the transducer with the catcher function. The catcher function is provided the error and the item for which the error was thrown. It is possible for either the transducer or the catcher to be asynchronous, however the reducing operation must support asynchronous execution. This library provides such implementations as [reduce](/docs/reduce) and [transform](/docs/transform).
267
284
  *
268
285
  * ```javascript [playground]
269
286
  * const db = new Map()
@@ -295,8 +312,6 @@ Transducer.passthrough = function transducerPassthrough(reducer) {
295
312
  * ), null)
296
313
  * ```
297
314
  *
298
- * Read more on [transducers](/blog/transducers-crash-course-rubico-v2).
299
- *
300
315
  * See also:
301
316
  * * [thunkify](/docs/thunkify)
302
317
  * * [Transducer.map](/docs/Transducer.map)
package/__.js CHANGED
@@ -12,9 +12,9 @@ const __ = require('./_internal/placeholder')
12
12
  * A special placeholder value `__` (two underscores) that denotes the position of an argument in a curried function.
13
13
  *
14
14
  * ```javascript [playground]
15
- * console.log(
16
- * curry.arity(3, Array.of, __, 2, 3)(1),
17
- * ) // [1, 2, 3]
15
+ * const curriedFunction = curry.arity(3, Array.of, __, 2, 3)
16
+ *
17
+ * console.log(curriedFunction(1))
18
18
  * ```
19
19
  *
20
20
  * See also:
@@ -11,7 +11,7 @@ const objectSet = require('./objectSet')
11
11
  * @synopsis
12
12
  * ```coffeescript [specscript]
13
13
  * asyncFunctionArrayAllSeries(
14
- * funcs Array<function>,
14
+ * funcs Array<function|any>,
15
15
  * args Array,
16
16
  * result Array,
17
17
  * funcsIndex number
@@ -34,14 +34,15 @@ const asyncFunctionArrayAllSeries = async function (funcs, args, result, funcsIn
34
34
  *
35
35
  * @synopsis
36
36
  * ```coffeescript [specscript]
37
- * functionArrayAllSeries(funcs Array<function>, args Array) -> Promise|Array
37
+ * functionArrayAllSeries(funcs Array<function|any>, args Array) -> Promise|Array
38
38
  * ```
39
39
  */
40
40
  const functionArrayAllSeries = function (funcs, args) {
41
41
  const funcsLength = funcs.length, result = []
42
42
  let funcsIndex = -1
43
43
  while (++funcsIndex < funcsLength) {
44
- const resultElement = funcs[funcsIndex](...args)
44
+ const f = funcs[funcsIndex]
45
+ const resultElement = typeof f == 'function' ? f(...args) : f
45
46
  if (isPromise(resultElement)) {
46
47
  return resultElement.then(funcConcat(
47
48
  curry3(objectSet, result, funcsIndex, __),
@@ -0,0 +1,65 @@
1
+ const funcConcat = require('./funcConcat')
2
+ const isPromise = require('./isPromise')
3
+ const __ = require('./placeholder')
4
+ const curry3 = require('./curry3')
5
+ const curry5 = require('./curry5')
6
+ const objectSet = require('./objectSet')
7
+
8
+ /**
9
+ * @name asyncFunctionObjectAllSeries
10
+ *
11
+ * @synopsis
12
+ * ```coffeescript [specscript]
13
+ * asyncFunctionObjectAllSeries(
14
+ * funcs Array<function>,
15
+ * args Array,
16
+ * result Array,
17
+ * keys Array<string>,
18
+ * keysIndex number
19
+ * ) -> Promise|Array
20
+ * ```
21
+ *
22
+ * @TODO benchmark vs regular promise handling
23
+ */
24
+ const asyncFunctionObjectAllSeries = async function (funcs, args, result, keys, keysIndex) {
25
+ const keysLength = keys.length
26
+ while (++keysIndex < keysLength) {
27
+ const key = keys[keysIndex]
28
+ const f = funcs[key]
29
+ let resultElement = typeof f == 'function' ? f(...args) : f
30
+ if (isPromise(resultElement)) {
31
+ resultElement = await resultElement
32
+ }
33
+ result[key] = resultElement
34
+ }
35
+ return result
36
+ }
37
+
38
+ /**
39
+ * @name functionObjectAllSeries
40
+ *
41
+ * @synopsis
42
+ * ```coffeescript [specscript]
43
+ * functionObjectAllSeries(funcs Object<function|any>, args Array) -> Promise|Array
44
+ * ```
45
+ */
46
+ const functionObjectAllSeries = function (funcs, args) {
47
+ const result = {}
48
+ const keys = Object.keys(funcs)
49
+ const keysLength = keys.length
50
+ let keysIndex = -1
51
+ while (++keysIndex < keysLength) {
52
+ const key = keys[keysIndex]
53
+ const f = funcs[key]
54
+ const resultElement = typeof f == 'function' ? f(...args) : f
55
+ if (isPromise(resultElement)) {
56
+ return resultElement.then(funcConcat(
57
+ curry3(objectSet, result, key, __),
58
+ curry5(asyncFunctionObjectAllSeries, funcs, args, __, keys, keysIndex)))
59
+ }
60
+ result[key] = resultElement
61
+ }
62
+ return result
63
+ }
64
+
65
+ module.exports = functionObjectAllSeries
@@ -7,7 +7,6 @@ const curry2 = require('./curry2')
7
7
  const curry3 = require('./curry3')
8
8
  const always = require('./always')
9
9
  const noop = require('./noop')
10
- const add = require('./add')
11
10
  const genericReduce = require('./genericReduce')
12
11
  const objectAssign = require('./objectAssign')
13
12
  const arrayExtend = require('./arrayExtend')
package/all.js CHANGED
@@ -9,6 +9,7 @@ const curry2 = require('./_internal/curry2')
9
9
  const curryArgs2 = require('./_internal/curryArgs2')
10
10
  const functionArrayAll = require('./_internal/functionArrayAll')
11
11
  const functionArrayAllSeries = require('./_internal/functionArrayAllSeries')
12
+ const functionObjectAllSeries = require('./_internal/functionObjectAllSeries')
12
13
  const functionObjectAll = require('./_internal/functionObjectAll')
13
14
 
14
15
  /**
@@ -36,16 +37,16 @@ const _allValues = function (values) {
36
37
  *
37
38
  * @synopsis
38
39
  * ```coffeescript [specscript]
39
- * type SyncOrAsyncResolver = (...arguments)=>Promise|any
40
- * type ResolverOrValue = SyncOrAsyncResolver|Promise|any
40
+ * type Resolver = (...arguments)=>Promise|any
41
+ * type ResolverOrValue = Resolver|Promise|any
41
42
  *
42
- * all(Promise|Array<Promise|any>) -> Promise|Array
43
- * all(...arguments, Array<ResolverOrValue>) -> Promise|Array
44
- * all(Array<ResolverOrValue>)(...arguments) -> Promise|Array
43
+ * all(values Promise|Array<Promise|any>) -> result Promise|Array
44
+ * all(...arguments, valuesOrFuncs Array<ResolverOrValue>) -> result Promise|Array
45
+ * all(valuesOrFuncs Array<ResolverOrValue>)(...arguments) -> result Promise|Array
45
46
  *
46
- * all(Promise|Object<Promise|any>) -> Promise|Object
47
- * all(...arguments, Object<ResolverOrValue>) -> Promise|Object
48
- * all(Object<ResolverOrValue>)(...arguments) -> Promise|Object
47
+ * all(values Promise|Object<Promise|any>) -> result Promise|Object
48
+ * all(...arguments, valuesOrFuncs Object<ResolverOrValue>) -> result Promise|Object
49
+ * all(valuesOrFuncs Object<ResolverOrValue>)(...arguments) -> result Promise|Object
49
50
  * ```
50
51
  *
51
52
  * @description
@@ -162,9 +163,9 @@ const all = function (...args) {
162
163
  *
163
164
  * @synopsis
164
165
  * ```coffeescript [specscript]
165
- * all.series(...arguments, Array<function>) -> Promise|Array
166
+ * all.series(...arguments, funcs Array<function>) -> result Promise|Array
166
167
  *
167
- * all.series(Array<function>)(...arguments) -> Promise|Array
168
+ * all.series(funcs Array<function>)(...arguments) -> result Promise|Array
168
169
  * ```
169
170
  *
170
171
  * @description
@@ -186,14 +187,33 @@ const all = function (...args) {
186
187
  */
187
188
 
188
189
  all.series = function allSeries(...args) {
189
- const funcs = args.pop()
190
- if (args.length == 0) {
191
- return curryArgs2(functionArrayAllSeries, funcs, __)
190
+ if (args.length == 1) {
191
+ const resolversOrValues = args[0]
192
+ if (isPromise(resolversOrValues)) {
193
+ return resolversOrValues.then(_allValues)
194
+ }
195
+ if (areAllValuesNonfunctions(resolversOrValues)) {
196
+ return _allValues(resolversOrValues)
197
+ }
198
+ return isArray(resolversOrValues)
199
+ ? curryArgs2(functionArrayAllSeries, resolversOrValues, __)
200
+ : curryArgs2(functionObjectAllSeries, resolversOrValues, __)
192
201
  }
193
- if (areAnyValuesPromises(args)) {
194
- return promiseAll(args).then(curry2(functionArrayAllSeries, funcs, __))
202
+
203
+ const resolversOrValues = args[args.length - 1]
204
+ const argValues = args.slice(0, -1)
205
+
206
+ if (areAnyValuesPromises(argValues)) {
207
+ return isArray(resolversOrValues)
208
+ ? promiseAll(argValues)
209
+ .then(curry2(functionArrayAllSeries, resolversOrValues, __))
210
+ : promiseAll(argValues)
211
+ .then(curry2(functionObjectAllSeries, resolversOrValues, __))
195
212
  }
196
- return functionArrayAllSeries(funcs, args)
213
+
214
+ return isArray(resolversOrValues)
215
+ ? functionArrayAllSeries(resolversOrValues, argValues)
216
+ : functionObjectAllSeries(resolversOrValues, argValues)
197
217
  }
198
218
 
199
219
  module.exports = all
package/always.js CHANGED
@@ -9,14 +9,14 @@ const always = require('./_internal/always')
9
9
  * ```
10
10
  *
11
11
  * @description
12
- * Creates a function from a value that always returns the provided value.
12
+ * Creates a function that always returns a value.
13
13
  *
14
14
  * ```javascript [playground]
15
15
  * const always5 = always(5)
16
16
  *
17
- * console.log(always5()) // 5
18
- * console.log(always5()) // 5
19
- * console.log(always5()) // 5
17
+ * console.log(always5())
18
+ * console.log(always5())
19
+ * console.log(always5())
20
20
  * ```
21
21
  *
22
22
  * See also: