1--- 2-- lodash for lua 3-- @module lodash 4-- @author Ted Moghimi 5-- @license MIT 6 7-- 20200120; added _.isEqual ( http://lua-users.org/lists/lua-l/2014-09/msg00463.html ) 8 9local _ = { 10 _VERSION = '0.03' 11} 12 13--- Array 14-- @section Array 15 16--- 17-- Creates an array of elements split into groups the length of size. 18-- If collection can’t be split evenly, the final chunk will be the 19-- remaining elements. 20-- @usage local t = _.chunk({'x', 'y', 'z', 1, 2, 3, 4, true , false}, 4) 21-- _.print(t) 22-- --> {{"x", "y", "z", 1}, {2, 3, 4, true}, {false}} 23-- 24-- @param array The array to process. 25-- @param[opt=1] size The length of each chunk. 26-- @return the new array containing chunks. 27_.chunk = function (array, size) 28 local t = {} 29 local size = size == 0 and 1 or size or 1 30 local c, i = 1, 1 31 while true do 32 t[i] = {} 33 for j = 1, size do 34 _.push(t[i], array[c]) 35 c = c + 1 36 end 37 if _.gt(c, #array) then 38 break 39 end 40 i = i + 1 41 end 42 return t 43end 44 45--- 46-- Creates an array with all falsey values removed. The values false, 47-- nil are falsey. 48-- @usage local t = _.compact({'x', 'y', nil, 1, 2, 3, false, true , false}) 49-- _.print(t) 50-- --> {"x", "y", 1, 2, 3, true} 51-- 52-- @param array The array to compact 53-- @return Returns the new array of filtered values 54_.compact = function (array) 55 local t = {} 56 for k, v in pairs(array) do 57 if v then 58 _.push(t, v) 59 end 60 end 61 return t 62end 63 64 65--- 66-- Creates an array of unique array values not included in the other 67-- provided arrays. 68-- @usage _.print(_.difference({3, 1, 2, 9, 5, 9}, {4, 5}, {9, 1})) 69-- --> {3, 2} 70-- 71-- @param array The array to inspect. 72-- @param ... The arrays of values to exclude. 73-- @return Returns the new array of filtered values. 74_.difference = function (array, ...) 75 local t = {} 76 local c = 1 77 local tmp = _.table(...) 78 for k, v in ipairs(array) do 79 while not _.isNil(tmp[c]) do 80 for j, v2 in ipairs(tmp[c]) do 81 if v == v2 then goto doubleBreak end 82 end 83 c = c + 1 84 end 85 _.push(t, v) 86 ::doubleBreak:: 87 c = 1 88 end 89 return t 90end 91 92--- 93-- Creates a slice of array with n elements dropped from the beginning. 94-- @usage _.print(_.drop({1, 2, 3, 4, 5, 6}, 2)) 95-- --> {3, 4, 5, 6} 96-- 97-- @param array The array to query. 98-- @param[opt=1] n The number of elements to drop. 99-- @return Returns the slice of array. 100_.drop = function (array, n) 101 local n = n or 1 102 return _.slice(array, n + 1) 103end 104 105 106local callIteratee = function (predicate, selfArg, ...) 107 local result 108 local predicate = predicate or _.identity 109 if selfArg then 110 result = predicate(selfArg, ...) 111 else 112 result = predicate(...) 113 end 114 return result 115end 116 117--- 118-- Creates a slice of array with n elements dropped from the end. 119-- @usage _.print(_.dropRight({1, 2, 3, 4, 5, 6}, 2)) 120-- --> {1, 2, 3, 4} 121-- 122-- @param array The array to query. 123-- @param[opt=1] n The number of elements to drop. 124-- @return Returns the slice of array. 125_.dropRight = function (array, n) 126 local n = n or 1 127 return _.slice(array, nil, #array - n) 128end 129 130 131local dropWhile = function(array, predicate, selfArg, start, step, right) 132 local t = {} 133 local c = start 134 while not _.isNil(array[c]) do 135 ::cont:: 136 if #t == 0 and 137 callIteratee(predicate, selfArg, array[c], c, array) then 138 c = c + step 139 goto cont 140 end 141 if right then 142 _.enqueue(t, array[c]) 143 else 144 _.push(t, array[c]) 145 end 146 c = c + step 147 end 148 return t 149end 150 151--- 152-- Creates a slice of array excluding elements dropped from the end. 153-- Elements are dropped until predicate returns falsey. 154-- @usage _.print(_.dropRightWhile({1, 5, 2, 3, 4, 5, 4, 4}, function(n) 155-- return n > 3 156-- end)) 157-- --> {1, 5, 2, 3} 158-- 159-- @param array The array to query. 160-- @param[opt=_.identity] predicate The function to invoked per iteratin. 161-- @param[opt] selfArg The self binding of predicate. 162-- @return Return the slice of array. 163_.dropRightWhile = function(array, predicate, selfArg) 164 return dropWhile(array, predicate, selfArg, #array, -1, true) 165end 166 167--- 168-- Creates a slice of array excluding elements dropped from the beginning. 169-- Elements are dropped until predicate returns falsey. 170-- @usage _.print(_.dropWhile({1, 2, 2, 3, 4, 5, 4, 4, 2}, function(n) 171-- return n < 3 172-- end)) 173-- --> {3, 4, 5, 4, 4, 2} 174-- 175-- @param array The array to query. 176-- @param[opt=_.idenitity] predicate The function invoked per iteration. 177-- @param[opt] selfArg The self binding of predicate. 178-- @return Return the slice of array. 179_.dropWhile = function(array, predicate, selfArg) 180 return dropWhile(array, predicate, selfArg, 1, 1) 181end 182 183 184--- 185-- Push value to first element of array 186--- 187--@Usage local array = {1, 2, 3, 4} 188-- _.enqueue(array, 5) 189-- _print(array) 190-- --> {5, 1, 2, 3, 4} 191-- 192-- @param array; Array to modify 193-- @param: value; Value to fill first element of Array with 194-- @return array 195_.enqueue = function (array, value) 196 return table.insert(array, 1, value) 197end 198 199--- 200-- Fills elements of array with value from start up to, including, end. 201-- @usage local array = {1, 2, 3, 4} 202-- _.fill(array, 'x', 2, 3) 203-- _.print(array) 204-- --> {1, "x", "x", 4} 205-- 206-- @param array The array to fill. 207-- @param value The value to fill array with. 208-- @param[opt=1] start The start position. 209-- @param[opt=#array] stop The end position. 210-- @return Returns array. 211_.fill = function (array, value, start, stop) 212 local start = start or 1 213 local stop = stop or #array 214 for i=start, stop, start > stop and -1 or 1 do 215 array[i] = value 216 end 217 return array 218end 219 220 221local findIndex = function(array, predicate, selfArg, start, step) 222 local c = start 223 while not _.isNil(array[c]) do 224 if callIteratee(predicate, selfArg, array[c], c, array) then 225 return c 226 end 227 c = c + step 228 end 229 return -1 230end 231 232--- 233-- This method is like [_.find](#_.find) except that it returns the index of the 234-- first element predicate returns truthy for instead of the element itself. 235-- @usage _.print(_.findIndex({{a = 1}, {a = 2}, {a = 3}, {a = 2}, {a = 3}}, function(v) 236-- return v.a == 3 237-- end)) 238-- --> 3 239-- 240-- @param array The array to search. 241-- @param[opt=_.idenitity] predicate The function invoked per iteration. 242-- @param[opt] selfArg The self binding of predicate. 243-- @return Returns the index of the found element, else -1. 244_.findIndex = function (array, predicate, selfArg) 245 return findIndex(array, predicate, selfArg, 1, 1) 246end 247 248--- 249-- This method is like [_.findIndex](#_.findIndex) except that it iterates over 250-- elements of collection from right to left. 251-- @usage _.print(_.findLastIndex({{a = 1}, {a = 2}, {a = 3}, {a = 2}, {a = 3}}, function(v) 252-- return v.a == 3 253-- end)) 254-- --> 5 255-- 256-- @param array The array to search. 257-- @param[opt=_.idenitity] predicate The function invoked per iteration. 258-- @param[opt] selfArg The self binding of predicate. 259-- @return Returns the index of the found element, else -1. 260_.findLastIndex = function (array, predicate, selfArg) 261 return findIndex(array, predicate, selfArg, #array, -1) 262end 263 264 265--- 266-- Gets the first element of array. 267-- @usage _.print(_.first({'w', 'x', 'y', 'z'})) 268-- --> w 269-- 270-- @param array The array to query. 271-- @return Returns the first element of array. 272_.first = function (array) 273 return array[1] 274end 275 276--- 277-- Flattens a nested array. 278-- If isDeep is true the array is recursively flattened, otherwise 279-- it’s only flattened a single level. 280-- @usage _.print(_.flatten({1, 2, {3, 4, {5, 6}}})) 281-- --> {1, 2, 3, 4, {5, 6}} 282-- _.print(_.flatten({1, 2, {3, 4, {5, 6}}}, true)) 283-- --> {1, 2, 3, 4, 5, 6} 284-- 285-- @param array The array to flatten. 286-- @param isDeep Specify a deep flatten 287-- @return Returns the new flattened array. 288_.flatten = function(array, isDeep) 289 local t = {} 290 for k, v in ipairs(array) do 291 if _.isTable(v) then 292 local childeren 293 if isDeep then 294 childeren = _.flatten(v) 295 else 296 childeren = v 297 end 298 for k2, v2 in ipairs(childeren) do 299 _.push(t, v2) 300 end 301 else 302 _.push(t, v) 303 end 304 end 305 return t 306end 307 308--- 309-- Recursively flattens a nested array. 310-- @usage _.print(_.flattenDeep({1, 2, {3, 4, {5, 6}}})) 311-- --> {1, 2, 3, 4, 5, 6} 312-- 313-- @param array The array to flatten. 314-- @return Returns the new flattened array. 315_.flattenDeep = function (array) 316 return _.flatten(array, true) 317end 318 319--- 320-- Gets the index at which the first occurrence of value is found in array. 321-- @usage _.print(_.indexOf({2, 3, 'x', 4}, 'x')) 322-- --> 3 323-- 324-- @param array The array to search. 325-- @param value The value to search for. 326-- @param[opt=1] fromIndex The index to search from. 327-- @return Returns the index of the matched value, else -1. 328_.indexOf = function (array, value, fromIndex) 329 return _.findIndex(array, function(n) 330 return n == value 331 end) 332end 333-- 334 335--- 336-- Gets all but the last element of array. 337-- @usage _.print(_.initial({1, 2, 3, 'a'})) 338-- --> {1, 2, 3} 339-- 340-- @param array The array to query. 341-- @return Returns the slice of array. 342_.initial = function (array) 343 return _.slice(array, nil, #array - 1) 344end 345-- 346 347--- 348-- Creates an array of unique values that are included in all of the 349-- provided arrays. 350-- @usage _.print(_.intersection({1, 2}, {4, 2}, {2, 1})) 351-- --> {2} 352-- 353-- @param The arrays to inspect. 354-- @return Returns the new array of shared values. 355_.intersection = function (...) 356 local tmp = _.table(...) 357 local first = table.remove(tmp, 1) 358 local t = {} 359 for i, v in ipairs(first) do 360 local notFound = false 361 for i2, v2 in ipairs(tmp) do 362 if _.indexOf(v2, v) == -1 then 363 notFound = true 364 break 365 end 366 end 367 if not notFound then 368 _.push(t, v) 369 end 370 end 371 return t 372 -- body 373end 374 375 376--- 377-- Gets the last element of array. 378-- @usage _.print(_.last({'w', 'x', 'y', 'z'})) 379-- --> z 380-- 381-- @param array The array to query. 382-- @return Returns the last element of array. 383_.last = function(array) 384 return array[#array] 385end 386 387--- 388-- This method is like [_.indexOf](#_.indexOf) except that it iterates 389-- over elements of array from right to left. 390-- @usage _.print(_.lastIndexOf({2, 3, 'x', 4, 'x', 5}, 'x')) 391-- --> 5 392-- 393-- @param array The array to search. 394-- @param value The value to search for. 395-- @param[opt=#array] fromIndex The index to search from. 396-- @return Returns the index of the matched value, else -1. 397_.lastIndexOf = function (array, value, fromIndex) 398 return _.findLastIndex(array, function(n) 399 return n == value 400 end) 401end 402 403 404--- 405-- Removes all provided values from array. 406-- @usage local array = {1, 2, 3, 4, 5, 4, 1, 2, 3} 407-- _.pull(array, 2, 3) 408-- _.print(array) 409-- --> {1, 4, 5, 4, 1} 410-- @param array The array to modify. 411-- @param ... The values to remove. 412-- @return Returns array 413_.pull = function(array, ...) 414 local i = 1 415 while not _.isNil(array[i]) do 416 for k, v in ipairs(_.table(...)) do 417 if array[i] == v then 418 table.remove(array, i) 419 goto cont 420 end 421 end 422 i = i + 1 423 ::cont:: 424 end 425 return array 426end 427 428_.push = function (array, value) 429 return table.insert(array, value) 430end 431 432--- 433-- Removes elements from array corresponding to the given indexes and 434-- returns an array of the removed elements. Indexes may be specified 435-- as an array of indexes or as individual arguments. 436-- @usage local array = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'} 437-- local t = _.pullAt(array, 4, 9, 8) 438-- _.print(array) 439-- --> {"a", "b", "c", "e", "f", "g", "j"} 440-- _.print(t) 441-- --> {"d", "h", "i"} 442-- 443-- @param array The array to modify. 444-- @param ... The indexes of elements to remove 445-- @return Returns the new array of removed elements. 446_.pullAt = function (array, ...) 447 local t = {} 448 local tmp = _.table(...) 449 table.sort(tmp, function(a, b) 450 return _.gt(a, b) 451 end) 452 for i, index in ipairs(tmp) do 453 _.enqueue(t, table.remove(array, index)) 454 end 455 return t 456end 457 458--- 459-- Removes all elements from array that predicate returns truthy for 460-- and returns an array of the removed elements. 461-- @usage local array = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 1, 2, 3, 5, 4} 462-- local t = _.remove(array, function(value) 463-- return value > 4 464-- end) 465-- _.print(array) 466-- --> {1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4} 467-- _.print(t) 468-- --> {5, 6, 7, 5, 6, 5} 469-- 470-- @param array The array to modify. 471-- @param predicate The function invoked per iteration. 472-- @return Returns the new array of removed elements 473_.remove = function(array, predicate) 474 local t = {} 475 local c = 1 476 local predicate = predicate or _.identity 477 while not _.isNil(array[c]) do 478 if predicate(array[c], c, array) then 479 _.push(t, table.remove(array, c)) 480 goto cont 481 end 482 c = c + 1 483 ::cont:: 484 end 485 return t 486end 487 488 489--- 490-- Gets all but the first element of array. 491-- @usage _.print(_.rest({1, 2, 3, 'a'})) 492-- --> {2, 3, 'a'} 493-- @param array The array to query. 494-- @return Returns the slice ofa array. 495_.rest = function (array) 496 return _.slice(array, 2, #array) 497end 498 499 500--- 501-- Reverses the array so the first element becomes the last, the second 502-- element becomes the second to last, and so on. 503-- @usage _.print(_.reverse({1, 2, 3, 'a', 'b'})) 504-- --> {'b', 'a', 3, 2, 1} 505-- 506-- @param array The array to mutate. 507-- @return Returns the new reversed array. 508_.reverse = function (array) 509 local t = {} 510 for i, v in ipairs(array) do 511 _.enqueue(t, v) 512 end 513 return t 514end 515 516 517--- 518-- Creates a slice of array from start up to, including, end. 519-- @usage _.print(_.slice({1, 2, 3, 4, 5, 6}, 2, 3)) 520-- --> {2, 3} 521-- 522-- @param array The array to slice. 523-- @param[opt=1] start The start position. 524-- @param[opt=#array] stop The end position 525-- @return Returns the slice of array. 526_.slice = function (array, start, stop) 527 local start = start or 1 528 local stop = stop or #array 529 local t = {} 530 for i=start, stop do 531 t[i - start + 1] = array[i] 532 end 533 return t 534end 535 536--- 537-- Creates a slice of array with n elements taken from the beginning. 538-- @usage _.print(_.take({1, 2, 3, 4, 5}, 3)) 539-- --> {1, 2, 3} 540-- 541-- @param array The array to query. 542-- @param[opt=1] n The number of elements to take. 543-- @return Returns the slice of array. 544_.take = function(array, n) 545 local n = n or 1 546 return _.slice(array, 1, n) 547end 548 549 550--- 551-- Creates a slice of array with n elements taken from the end. 552-- @usage _.print(_.takeRight({1, 2, 3, 4, 5}, 3)) 553-- --> {3, 4, 5} 554-- 555-- @param array The array to query. 556-- @param[opt=1] n The number of elements to take. 557-- @return Returns the slice of array. 558_.takeRight = function (array, n) 559 local n = n or 1 560 return _.slice(array, #array - n +1) 561end 562 563local takeWhile = function(array, predicate, selfArg, start, step, right) 564 local t = {} 565 local c = start 566 while not _.isNil(array[c]) do 567 if callIteratee(predicate, selfArg, array[c], c, array) then 568 if right then 569 _.enqueue(t, array[c]) 570 else 571 _.push(t, array[c]) 572 end 573 else 574 break 575 end 576 c = c + step 577 end 578 return t 579end 580 581--- 582-- Creates a slice of array with elements taken from the end. Elements 583-- are taken until predicate returns falsey. The predicate is bound to 584-- selfArg and invoked with three arguments: (value, index, array). 585-- @usage _.print(_.takeRightWhile({1, 2, 3, 4, 5, 6, 7, 8}, function(n) 586-- return n > 4 587-- end)) 588-- --> {5, 6, 7, 8} 589-- 590-- @param array The array to query. 591-- @param predicate The function invoked per iteration. 592-- @param selfArg The self binding of predicate. 593_.takeRightWhile = function (array, predicate, selfArg) 594 return takeWhile(array, predicate, selfArg, #array, -1, true) 595end 596 597--- 598-- Creates an array of unique values, from all of the 599-- provided arrays. 600-- @usage _.print(_.union({1, 2}, {4, 2}, {2, 1})) 601-- --> {1, 2, 4} 602-- 603-- @param ... The arrays to inspect 604_.union = function (...) 605 local tmp = _.table(...) 606 local t = {} 607 for i, array in ipairs(tmp) do 608 for i2, v in ipairs(array) do 609 if _.indexOf(t, v) == -1 then 610 _.push(t, v) 611 end 612 end 613 end 614 return t 615end 616 617 618 619--- 620-- Creates a slice of array with elements taken from the beginning. Elements 621-- are taken until predicate returns falsey. The predicate is bound to 622-- selfArg and invoked with three arguments: (value, index, array). 623-- @usage _.print(_.takeWhile({1, 2, 3, 4, 5, 6, 7, 8}, function(n) 624-- return n < 5 625-- end)) 626-- --> {1, 2, 3, 4} 627-- 628-- @param array The array to query. 629-- @param predicate The function invoked per iteration. 630-- @param selfArg The self binding of predicate. 631_.takeWhile = function (array, predicate, selfArg) 632 return takeWhile(array, predicate, selfArg, 1, 1) 633end 634 635--- 636-- Creates a duplicate-free version of an array in which only the first 637-- occurence of each element is kept. If an iteratee function is provided 638-- it’s invoked for each element in the array to generate the criterion 639-- by which uniqueness is computed. The iteratee is bound to thisArg and 640-- invoked with three arguments: (value, index, array). 641-- @usage _.print(_.uniq({1, 3, 2, 2})) 642-- --> {1, 3, 2} 643--_.print(_.uniq({{x=1}, {x=2}, {x=2}, {x=3}, {x=1}}, function(n) 644-- return n.x 645-- end)) 646-- --> {{["x"]=1}, {["x"]=2}, {["x"]=3}} 647-- 648-- @param array The array to inspect. 649-- @param iteratee The function invoked per iteration. 650-- @param selfArg The self binding of predicate. 651-- @return Returns the new duplicate-value-free array. 652_.uniq = function(array, iteratee, selfArg) 653 local t = {} 654 local results = {} 655 for k, v in ipairs(array) do 656 local r = callIteratee(iteratee, selfArg, v, k, array) 657 if _.indexOf(results, r) == -1 then 658 _.push(t, v) 659 end 660 _.push(results, r) 661 end 662 return t 663end 664 665--- 666-- The inverse of _.pairs; this method returns an object composed from 667-- arrays of property names and values. Provide either a single two dimensional 668-- array, e.g. [[key1, value1], [key2, value2]] or two arrays, one of 669-- property names and one of corresponding values. 670-- @usage _.print(_.zipObject({{'fred', 30}, {'alex', 20}})) 671-- --> {["alex"]=20, ["fred"]=30} 672-- _.print(_.zipObject({'fred', 'alex'}, {30, 20})) 673-- --> {["alex"]=20, ["fred"]=30} 674-- 675-- @param ... The properties/values 676-- @return Returns the new object. 677_.zipObject = function (...) 678 local tmp = _.table(...) 679 local t = {} 680 if #tmp == 1 then 681 for i, pair in ipairs(tmp[1]) do 682 t[pair[1]] = pair[2] 683 end 684 else 685 for i = 1, #tmp[1] do 686 t[tmp[1][i]] = tmp[2][i] 687 end 688 end 689 return t 690end 691 692 693--- 694-- This method is like [_.zip](#_.zip) except that it accepts an array of grouped 695-- elements and creates an array regrouping the elements to their pre-zip 696-- configuration. 697-- @usage local t = _.zip({'a', 'b', 'c'}, {1, 2, 3}, {10, 20, 30}) 698-- _.print(t) 699-- --> {{"a", 1, 10}, {"b", 2, 20}, {"c", 3, 30}} 700-- _.print(_.unzip(t)) 701-- --> {{"a", "b", "c"}, {1, 2, 3}, {10, 20, 30}} 702-- 703-- @param array The array of grouped elements to process. 704-- @return Returns the new array of regrouped elements. 705_.unzip = function (array) 706 return _.zip(_.args(array)) 707end 708 709--- 710-- Creates an array excluding all provided values 711-- @usage _.print(_.without({1,1, 2, 3, 2, 3, 5, 5, 1, 2}, 5, 1)) 712-- --> {2, 3, 2, 3, 2} 713-- 714-- @param array The array to filter. 715-- @param ... The values to exclude. 716-- @return Returns the new array of filtered values. 717_.without = function (array, ...) 718 local t = {} 719 for i, v in ipairs(array) do 720 local args = _.table(...) 721 if _.indexOf(args, v) == -1 then 722 _.push(t, v) 723 end 724 end 725 return t 726end 727 728--- 729-- Creates an array of grouped elements, the first of which contains 730-- the first elements of the given arrays, the second of which contains 731-- the second elements of the given arrays, and so on. 732-- @usage local t = _.zip({'a', 'b', 'c'}, {1, 2, 3}, {10, 20, 30}) 733-- _.print(t) 734-- --> {{"a", 1, 10}, {"b", 2, 20}, {"c", 3, 30}} 735-- 736-- @param ... The arrays to process 737-- @return Returns the new array of grouped elements. 738_.zip = function (...) 739 local t = {} 740 for i, array in ipairs(_.table(...)) do 741 for j, v in ipairs(array) do 742 t[j] = t[j] or {} 743 t[j][i] = v 744 end 745 end 746 return t 747end 748 749--- Collection 750-- @section Collection 751 752--- 753-- Creates an array of elements corresponding to the given keys, 754-- or indexes, of collection. Keys may be specified as individual 755-- arguments or as arrays of keys. 756-- @usage _.print(_.at({'1', '2', '3', '4', a='a', b='b'}, {1, 2}, 'b')) 757-- --> {"1", "2", "b"} 758-- 759-- @param collection The collection to iterate over. 760-- @param ... The property names or indexes of elements to pick, 761-- specified individually or in arrays. 762-- @return Return the new array of picked elements. 763_.at = function (collection, ...) 764 local t = {} 765 for k, key in ipairs(_.table(...)) do 766 if _.isTable(key) then 767 for k, key in ipairs(key) do 768 _.push(t, collection[key]) 769 end 770 else 771 _.push(t, collection[key]) 772 end 773 end 774 return t 775end 776 777--- 778-- Creates an object composed of keys generated from the results of 779-- running each element of collection through iteratee. The corresponding 780-- value of each key is the number of times the key was returned by 781-- iteratee. The iteratee is bound to selfArg and invoked with three arguments: 782-- (value, index|key, collection). 783-- 784-- @usage _.print(_.countBy({4.3, 6.1, 6.4}, function(n) 785-- return math.floor(n) 786-- end)) 787-- --> {[4]=1, [6]=2} 788-- 789-- @param collection The collection to iterate over. (table|string) 790-- @param[opt=_.identity] iteratee The function invoked per iteration. 791-- @param[opt] selfArg The self binding of predicate. 792-- @return Returns the composed aggregate object. 793_.countBy = function (collection, iteratee, selfArg) 794 local t = {} 795 for k, v in _.iter(collection) do 796 local r = _.str( 797 callIteratee(iteratee, selfArg, v, k, collection) 798 ) 799 if _.isNil(t[r]) then 800 t[r] = 1 801 else 802 t[r] = t[r] + 1 803 end 804 end 805 return t 806end 807 808--- 809-- Creates an object composed of keys generated from the results of 810-- running each element of collection through iteratee. The corresponding 811-- value of each key is an array of the elements responsible for generating 812-- the key. The iteratee is bound to selfArg and invoked with three arguments: 813-- (value, index|key, collection). 814-- @usage _.print(_.groupBy({4.3, 6.1, 6.4}, function(n) 815-- return math.floor(n) 816-- end)) 817-- --> {[4]={4.3}, [6]={6.1, 6.4}} 818-- 819-- @param collection The collection to iterate over. (table|string) 820-- @param[opt=_.identity] iteratee The function invoked per iteration. 821-- @param[opt] selfArg The self binding of predicate. 822-- @return Returns the composed aggregate object. 823_.groupBy = function (collection, iteratee, selfArg) 824 local t = {} 825 for k, v in _.iter(collection) do 826 local r = _.str( 827 callIteratee(iteratee, selfArg, v, k, collection) 828 ) 829 if _.isNil(t[r]) then 830 t[r] = {v} 831 else 832 _.push(t[r], v) 833 end 834 end 835 return t 836end 837 838--- 839-- Creates an object composed of keys generated from the results of 840-- running each element of collection through iteratee. The corresponding 841-- value of each key is the last element responsible for generating the key. 842-- The iteratee function is bound to selfArg and invoked with three arguments: 843-- (value, index|key, collection). 844-- @usage local keyData = { 845-- {dir='l', a=1}, 846-- {dir='r', a=2} 847-- } 848-- _.print('40.indexBy :', _.indexBy(keyData, function(n) 849-- return n.dir 850-- end)) 851-- --> {["l"]={[a]=1, [dir]="l"}, ["r"]={[a]=2, [dir]="r"}} 852-- 853-- @param collection The collection to iterate over. (table|string) 854-- @param[opt=_.identity] iteratee The function invoked per iteration. 855-- @param[opt] selfArg The self binding of predicate. 856-- @return Returns the composed aggregate object. 857_.indexBy = function (collection, iteratee, selfArg) 858 local t = {} 859 for k, v in _.iter(collection) do 860 local r = _.str( 861 callIteratee(iteratee, selfArg, v, k, collection) 862 ) 863 t[r] = v 864 end 865 return t 866end 867 868--- 869-- Checks if predicate returns truthy for all elements of collection. 870-- The predicate is bound to selfArg and invoked with three arguments: 871-- (value, index|key, collection). 872-- @usage _.print(_.every({1, 2, 3, 4, '5', 6}, _.isNumber)) 873-- --> false 874-- _.print(_.every({1, 2, 3, 4, 5, 6}, _.isNumber)) 875-- --> true 876-- 877-- @param collection The collection to iterate over. (table|string) 878-- @param[opt=_.identity] predicate The function invoked per iteration 879-- @param[opt] selfArg The self binding of predicate. 880_.every = function (collection, predicate, selfArg) 881 for k, v in _.iter(collection) do 882 if not callIteratee(predicate, selfArg, v, k, collection) then 883 return false 884 end 885 end 886 return true 887end 888 889local filter = function(collection, predicate, selfArg, reject) 890 local t = {} 891 for k, v in _.iter(collection) do 892 local check = callIteratee(predicate, selfArg, v, k, collection) 893 if reject then 894 if not check then 895 _.push(t, v) 896 end 897 else 898 if check then 899 _.push(t, v) 900 end 901 end 902 end 903 return t 904end 905 906--- 907-- Iterates over elements of collection, returning an array of all 908-- elements predicate returns truthy for. The predicate is bound to 909-- selfArg and invoked with three arguments: (value, index|key, collection). 910-- @usage _.print(_.filter({1, 2, 3, 4, '5', 6, '7'}, _.isNumber)) 911-- --> {1, 2, 3, 4, 6} 912-- 913-- @param collection The collection to iterate over. (table|string) 914-- @param[opt=_.identity] predicate The function invoked per iteration 915-- @param[opt] selfArg The self binding of predicate. 916_.filter = function (collection, predicate, selfArg) 917 return filter(collection, predicate, selfArg) 918end 919 920--- 921-- Iterates over elements of collection invoking iteratee for each element. 922-- The iteratee is bound to selfArg and invoked with three arguments: 923-- (value, index|key, collection). Iteratee functions may exit iteration 924-- early by explicitly returning false. 925-- 926-- @param collection The collection to iterate over. (table|string) 927-- @param[opt=_.identity] predicate The function invoked per iteration 928-- @param[opt] selfArg The self binding of predicate. 929-- @return Returns collection. 930_.forEach = function (collection, predicate, selfArg) 931 for k, v in _.iter(collection) do 932 callIteratee(predicate, selfArg, v, k, collection) 933 end 934 return collection 935end 936 937--- 938-- This method is like [_.forEach](#_.forEach) except that it iterates 939-- over elements of collection from right to left. 940-- 941-- @param collection The collection to iterate over. (table|string) 942-- @param[opt=_.identity] predicate The function invoked per iteration 943-- @param[opt] selfArg The self binding of predicate. 944-- @return Returns collection. 945_.forEachRight = function (collection, predicate, selfArg) 946 for k, v in _.iterRight(collection) do 947 callIteratee(predicate, selfArg, v, k, collection) 948 end 949 return collection 950end 951 952--- 953-- Checks if target is in collection. 954-- @usage print(_.includes({1, 2, 'x', 3, ['5']=4, x=3, 5}, 'x')) 955-- --> true 956-- print(_.includes({1, 2, 'x', 3, ['5']=4, x=3, 5}, 'z')) 957-- --> false 958-- @param collection The collection to search 959-- @param target The value to search for. 960_.includes = function (collection, target) 961 local result = _.find(collection, function (n) 962 return n == target 963 end) 964 return result ~= nil 965end 966 967--- 968-- Invokes method of each element in collection, returning an array of the 969-- results of each invoked method. Any additional arguments are provided 970-- to each invoked method. func bound to, each element in collection. 971-- @usage _.print(_.invoke({'1.first', '2.second', '3.third'}, string.sub, 1, 1)) 972-- --> {"1", "2", "3"} 973-- 974-- @param collection The collection to iterate over. 975-- @param method The method to invoke per iteration. 976-- @param ... The arguments to invoke the method with. 977-- @return Returns the array of results. 978_.invoke = function (collection, method, ...) 979 local t = {} 980 for k, v in _.iter(collection) do 981 _.push(t, callIteratee(method, v, ...)) 982 end 983 return t 984end 985 986--- 987-- Creates an array of values by running each element in collection through 988-- iteratee. The iteratee is bound to selfArg and invoked with three 989-- arguments: (value, index|key, collection). 990-- @usage _.print(_.map({1, 2, 3, 4, 5, 6, 7, 8, 9}, function(n) 991-- return n * n 992-- end)) 993-- --> {1, 4, 9, 16, 25, 36, 49, 64, 81} 994-- 995-- @param collection The collection to iterate over. (table|string) 996-- @param[opt=_.identity] iteratee The function invoked per iteration 997-- @param[opt] selfArg The self binding of predicate. 998_.map = function (collection, iteratee, selfArg) 999 local t = {} 1000 for k, v in _.iter(collection) do 1001 t[k] = callIteratee(iteratee, selfArg, v, k, collection) 1002 end 1003 return t 1004end 1005 1006--- 1007-- Creates an array of elements split into two groups, the first of 1008-- which contains elements predicate returns truthy for, while the second 1009-- of which contains elements predicate returns falsey for. The predicate 1010-- is bound to selfArg and invoked with three arguments: 1011-- (value, index|key, collection). 1012-- @usage _.print(_.partition({1, 2, 3, 4, 5, 6, 7}, function (n) 1013-- return n > 3 1014-- end)) 1015-- --> {{4, 5, 6, 7}, {1, 2, 3}} 1016-- 1017-- @param collection The collection to iterate over. (table|string) 1018-- @param[opt=_.identity] predicate The function invoked per iteration 1019-- @param[opt] selfArg The self binding of predicate. 1020-- @return Returns the array of grouped elements. 1021_.partition = function (collection, predicate, selfArg) 1022 local t = {{}, {}} 1023 for k, v in _.iter(collection) do 1024 if callIteratee(predicate, selfArg, v, k, collection) then 1025 _.push(t[1], v) 1026 else 1027 _.push(t[2], v) 1028 end 1029 end 1030 return t 1031end 1032 1033--- 1034-- Gets the property value of path from all elements in collection. 1035-- @usage local users = { 1036-- { user = 'barney', age = 36, child = {age = 5}}, 1037-- { user = 'fred', age = 40, child = {age = 6} } 1038-- } 1039-- _.print(_.pluck(users, {'user'})) 1040-- --> {"barney", "fred"} 1041-- _.print(_.pluck(users, {'child', 'age'})) 1042-- --> {5, 6} 1043-- 1044-- @param collection The collection to iterate over. 1045-- @param path The path of the property to pluck. 1046_.pluck = function (collection, path) 1047 local t = {} 1048 for k, value in _.iter(collection) do 1049 _.push(t, _.get(value, path)) 1050 end 1051 return t 1052end 1053 1054 1055--- 1056-- Reduces collection to a value which is the accumulated result of 1057-- running each element in collection through iteratee, where each 1058-- successive invocation is supplied the return value of the previous. 1059-- If accumulator is not provided the first element of collection is used 1060-- as the initial value. The iteratee is bound to selfArg and invoked 1061-- with four arguments: (accumulator, value, index|key, collection). 1062-- @usage _.print(_.reduce({1, 2, 3}, function(total, n) 1063-- return n + total; 1064-- end)) 1065-- --> 6 1066-- _.print(_.reduce({a = 1, b = 2}, function(result, n, key) 1067-- result[key] = n * 3 1068-- return result; 1069-- end, {})) 1070-- --> {["a"]=3, ["b"]=6} 1071-- 1072-- @param collection The collection to iterate over. 1073-- @param[opt=_.identity] iteratee The function invoked per iteration. 1074-- @param[opt=<first element>] accumulator The initial value. 1075-- @param[opt] selfArg The self binding of predicate. 1076-- @return Returns the accumulated value. 1077_.reduce = function (collection, iteratee, accumulator, selfArg) 1078 local accumulator = accumulator 1079 for k, v in _.iter(collection) do 1080 if _.isNil(accumulator) then 1081 accumulator = v 1082 else 1083 accumulator = callIteratee(iteratee, selfArg, accumulator, v, k, collection) 1084 end 1085 end 1086 return accumulator 1087end 1088 1089--- 1090-- This method is like _.reduce except that it iterates over elements 1091-- of collection from right to left. 1092-- @usage local array = {0, 1, 2, 3, 4, 5}; 1093-- _.print(_.reduceRight(array, function(str, other) 1094-- return str .. other 1095-- end, '')) 1096-- --> 543210 1097-- 1098-- @param collection The collection to iterate over. 1099-- @param[opt=_.identity] iteratee The function invoked per iteration. 1100-- @param[opt=<first element>] accumulator The initial value. 1101-- @param[opt] selfArg The self binding of predicate. 1102-- @return Returns the accumulated value. 1103_.reduceRight = function (collection, iteratee, accumulator, selfArg) 1104 local accumulator = accumulator 1105 for k, v in _.iterRight(collection) do 1106 if _.isNil(accumulator) then 1107 accumulator = v 1108 else 1109 accumulator = callIteratee(iteratee, selfArg, accumulator, v, k, collection) 1110 end 1111 end 1112 return accumulator 1113end 1114 1115--- 1116-- The opposite of [_.filter](#_.filter); this method returns the elements of 1117-- collection that predicate does not return truthy for. 1118-- @usage _.print(_.reject({1, 2, 3, 4, '5', 6, '7'}, _.isNumber)) 1119-- --> {"5", "7"} 1120-- 1121-- @param collection The collection to iterate over. (table|string) 1122-- @param[opt=_.identity] predicate The function invoked per iteration 1123-- @param[opt] selfArg The self binding of predicate. 1124_.reject = function (collection, predicate, selfArg) 1125 return filter(collection, predicate, selfArg, true) 1126end 1127 1128--- 1129-- Gets a random element or n random elements from a collection. 1130-- @usage _.print(_.sample({1, 2, 3, a=4, b='x', 5, 23, 24}, 4)) 1131-- --> {5, "x", 1, 23} 1132-- _.print(_.sample({1, 2, 3, a=4, b='x', 5, 23, 24})) 1133-- --> 4 1134-- 1135-- @param collection The collection to sample. 1136-- @param[opt=1] n The number of elements to sample. 1137-- @return Returns the random sample(s). 1138_.sample = function (collection, n) 1139 local n = n or 1 1140 local t = {} 1141 local keys = _.keys(collection) 1142 for i=1, n do 1143 local pick = keys[_.random(1, #keys)] 1144 _.push(t, _.get(collection, {pick})) 1145 end 1146 return #t == 1 and t[1] or t 1147end 1148 1149--- 1150-- Gets the size of collection by returning its length for array-like 1151-- values or the number of own enumerable properties for objects. 1152-- @usage _.print(_.size({'abc', 'def'})) 1153-- --> 2 1154-- _.print(_.size('abcdefg')) 1155-- --> 7 1156-- _.print(_.size({a=1, b=2,c=3})) 1157-- --> 3 1158-- 1159-- @param collection The collection to inspect. 1160-- @return Returns the size of collection. 1161_.size = function (collection) 1162 local c = 0 1163 for k, v in _.iter(collection) do 1164 c = c + 1 1165 end 1166 return c 1167end 1168 1169--- 1170-- Checks if predicate returns truthy for any element of collection. 1171-- The function returns as soon as it finds a passing value and does 1172-- not iterate over the entire collection. The predicate is bound to 1173-- selfArg and invoked with three arguments: (value, index|key, collection). 1174-- 1175-- @usage _.print(_.some({1, 2, 3, 4, 5, 6}, _.isString)) 1176-- --> false 1177-- _.print(_.some({1, 2, 3, 4, '5', 6}, _.isString)) 1178-- --> true 1179-- @param collection The collection to iterate over. (table|string) 1180-- @param[opt=_.identity] predicate The function invoked per iteration 1181-- @param[opt] selfArg The self binding of predicate. 1182-- @return Returns true if any element passes the predicate check, else false. 1183_.some = function (collection, predicate, selfArg) 1184 for k, v in _.iter(collection) do 1185 if callIteratee(predicate, selfArg, v, k, collection) then 1186 return true 1187 end 1188 end 1189 return false 1190end 1191 1192--- 1193-- Creates an array of elements, sorted in ascending order by the 1194-- results of running each element in a collection through iteratee. 1195-- The iteratee is bound to selfArg and 1196-- invoked with three arguments: (value, index|key, collection). 1197-- @usage local t = {1, 2, 3} 1198-- _.print(_.sortBy(t, function (a) 1199-- return math.sin(a) 1200-- end)) 1201-- --> {1, 3, 2} 1202-- local users = { 1203-- { user='fred' }, 1204-- { user='alex' }, 1205-- { user='zoee' }, 1206-- { user='john' }, 1207-- } 1208-- _.print(_.sortBy(users, function (a) 1209-- return a.user 1210-- end)) 1211-- --> {{["user"]="alex"}, {["user"]="fred"}, {["user"]="john"}, {["user"]="zoee"}} 1212-- 1213-- @param collection The collection to iterate over. 1214-- @param[opt=_.identity] predicate The function invoked per iteration 1215-- @param[opt] selfArg The self binding of predicate. 1216-- @return Returns the new sorted array. 1217_.sortBy = function (collection, predicate, selfArg) 1218 local t ={} 1219 local empty = true 1220 local previous 1221 for k, v in _.iter(collection) do 1222 if empty then 1223 _.push(t, v) 1224 previous = callIteratee(predicate, selfArg, v, k, collection) 1225 empty = false 1226 else 1227 local r = callIteratee(predicate, selfArg, v, k, collection) 1228 if _.lt(previous, r) then 1229 table.insert(t, v) 1230 previous = r 1231 else 1232 table.insert(t, #t, v) 1233 end 1234 end 1235 end 1236 return t 1237end 1238 1239--- 1240-- Iterates over elements of collection, returning the first element 1241-- predicate returns truthy for. The predicate is bound to selfArg and 1242-- invoked with three arguments: (value, index|key, collection). 1243-- @usage _.print(_.find({{a = 1}, {a = 2}, {a = 3}, {a = 2}, {a = 3}}, function(v) 1244-- return v.a == 3 1245-- end)) 1246-- --> {[a]=3} 1247-- 1248-- @param collection The collection to search. (table|string) 1249-- @param predicate The function invoked per iteration 1250-- @param selfArg The self binding of predicate. 1251_.find = function (collection, predicate, selfArg) 1252 for k, v in _.iter(collection) do 1253 if callIteratee(predicate, selfArg, v, k, collection) then 1254 return v 1255 end 1256 end 1257end 1258 1259--- 1260-- This method is like _.find except that it iterates over elements of 1261-- collection from right to left. 1262-- @usage _.findLast({{a = 1}, {a = 2}, {a = 3, x = 1}, {a = 2}, {a = 3, x = 2}}, 1263-- function(v) 1264-- return v.a == 3 1265-- end)) 1266-- --> {[a]=3, [x]=2} 1267-- 1268-- @param collection The collection to search. (table|string) 1269-- @param predicate The function invoked per iteration 1270-- @param selfArg The self binding of predicate. 1271_.findLast = function (collection, predicate, selfArg) 1272 for k, v in _.iterRight(collection) do 1273 if callIteratee(predicate, selfArg, v, k, collection) then 1274 return v 1275 end 1276 end 1277end 1278 1279--- Function 1280-- @section Function 1281 1282--- 1283-- This method creates a function that invokes func once it’s called n 1284-- or more times. 1285-- @usage local printAfter3 = _.after(3, print) 1286-- for i = 1, 5 do 1287-- printAfter3('done', i) 1288-- end 1289-- --> done 4 1290-- --> done 5 1291-- 1292-- @param n The number of calls before func invoked. 1293-- @param func The function to restrict. 1294-- @return Returns the new restricted function. 1295_.after = function(n, func) 1296 local i = 1 1297 return function(...) 1298 if _.gt(i, n) then 1299 return func(...) 1300 end 1301 i = i + 1 1302 end 1303end 1304 1305--- 1306-- Creates a function that accepts up to n arguments ignoring any 1307-- additional arguments. 1308-- @usage local printOnly3 =_.ary(print, 3) 1309-- printOnly3(1, 2, 3, 'x', 'y', 6) 1310-- --> 1 2 3 1311-- 1312-- @param func The function to cap arguments for. 1313-- @param n the arity cap. 1314-- @return Returns the new function 1315_.ary = function(func, n) 1316 return function(...) 1317 if n == 1 then 1318 return func((...)) 1319 else 1320 local t = _.table(...) 1321 local first = _.take(t, n) 1322 return func(_.args(first)) 1323 end 1324 end 1325end 1326 1327--- 1328-- Creates a function that invokes func while it’s called less than n times. 1329-- Subsequent calls to the created function return the result of the 1330-- last func invocation. 1331-- @usage local printBefore3 = _.before(3, print) 1332-- for i = 1, 10 do 1333-- printBefore3(i, 'ok') 1334-- end 1335-- --> 1 ok 1336-- --> 2 ok 1337-- --> 3 ok 1338-- 1339-- @param n The number of calls at which func is no longer invoked. 1340-- @param func The function to restrict. 1341-- @return Returns the new restriced function. 1342_.before = function (n, func) 1343 local i = 1 1344 local result 1345 return function (...) 1346 if _.lte(i, n) then 1347 result = func(...) 1348 end 1349 i = i + 1 1350 return result 1351 end 1352end 1353 1354--- 1355-- Creates a function that runs each argument through a corresponding 1356-- transform function. 1357-- @usage local increment = function(...) 1358-- return _.args(_.map(_.table(...), function(n) 1359-- return n + 1 1360-- end)) 1361-- end 1362-- local pow = function(...) 1363-- return _.args(_.map(_.table(...), function(n) 1364-- return n * n 1365-- end)) 1366-- end 1367-- local modded = _.modArgs(function(...) 1368-- print(...) 1369-- end, {increment, increment}, pow) 1370-- modded(0, 1, 2) 1371-- --> 4 9 16 1372-- 1373-- @param func The function to wrap 1374-- @param ... The functions to transform arguments, specified as 1375-- individual functions or arrays of functions. 1376-- @return Returns the new function. 1377_.modArgs = function (func, ...) 1378 local transforms = {} 1379 for i, v in ipairs( _.table(...)) do 1380 if _.isFunction(v) then 1381 _.push(transforms, v) 1382 elseif _.isTable(v) then 1383 for k2, v2 in _.iter(v) do 1384 if _.isFunction(v2) then _.push(transforms, v2) end 1385 end 1386 end 1387 end 1388 return function(...) 1389 local args 1390 for i, transform in ipairs(transforms) do 1391 if _.isNil(args) then 1392 args = _.table(transform(...)) 1393 else 1394 args = _.table(transform(_.args(args))) 1395 end 1396 end 1397 if _.isNil(args) then 1398 return func(...) 1399 else 1400 return func(_.args(args)) 1401 end 1402 end 1403end 1404 1405--- 1406-- Creates a function that negates the result of the predicate func. 1407-- The func predicate is invoked with arguments of the created function. 1408-- @usage local isEven = function (n) 1409-- return n % 2 == 0 1410-- end 1411-- local isOdd = _.negate(isEven) 1412-- _.print(_.filter({1, 2, 3, 4, 5, 6}, isEven)) 1413-- --> {2, 4, 6} 1414-- _.print(_.filter({1, 2, 3, 4, 5, 6}, isOdd)) 1415-- --> {1, 3, 5} 1416-- 1417-- @param func The preadicate to negate. 1418-- @return Returns the new function 1419_.negate = function (func) 1420 return function(...) 1421 return not func(...) 1422 end 1423end 1424 1425--- 1426-- Creates a function that is restricted to invoking func once. Repeat 1427-- calls to the function return the value of the first call. The func 1428-- is invoked with arguments of the created function. 1429-- @usage local createApp = function(version) 1430-- print('App created with version '..version) 1431-- return version 1432-- end 1433-- local initialize = _.once(createApp) 1434-- initialize(1.1) 1435-- initialize(1.1) 1436-- initialize(1.1) 1437-- --> App created with version 1.1 1438-- --> 1.1 1439-- --> 1.1 1440-- --> 1.1 1441-- 1442-- @param func The function to restrict. 1443-- @return Returns the new function. 1444_.once = function (func) 1445 local called = false; 1446 local result 1447 return function(...) 1448 if not called then 1449 result = func(...) 1450 called = true 1451 end 1452 return result 1453 end 1454end 1455 1456 1457--- 1458-- Creates a function that invokes func with arguments arranged according 1459-- to the specified indexes where the argument value at the first index 1460-- is provided as the first argument, the argument value at the second 1461-- index is provided as the second argument, and so on. 1462-- @usage local rearged = _.rearg(function(a, b, c) 1463-- return {a, b, c}; 1464-- end, 2, 1, 3) 1465-- _.print(rearged('a', 'b', 'c')) 1466-- --> {"b", "a", "c"} 1467-- _.print(rearged('b', 'a', 'c')) 1468-- --> {"a", "b", "c"} 1469-- 1470-- @param func The function to rearrange arguments for. 1471-- @param ... The arranged argument indexes, specified as individual 1472-- indexes or arrays of indexes. 1473-- @return Returns the new function. 1474_.rearg = function (func, ...) 1475 local indexes = {} 1476 for i, v in ipairs(_.table(...)) do 1477 if _.isNumber(v) then 1478 _.push(indexes, v) 1479 elseif _.isTable(v) then 1480 for k2, v2 in _.iter(v) do 1481 if _.isNumber(v2) then _.push(indexes, v2) end 1482 end 1483 end 1484 end 1485 return function(...) 1486 local args = _.table(...) 1487 local newArgs = {} 1488 for i, index in ipairs(indexes) do 1489 _.push(newArgs, args[index]) 1490 end 1491 if #indexes == 0 then 1492 return func(...) 1493 else 1494 return func(_.args(newArgs)) 1495 end 1496 end 1497end 1498 1499 1500 1501--- Lang 1502-- @section Lang 1503--- 1504 1505--- 1506-- Cast value to arguments 1507-- @usage print(_.args({1, 2, 3})) 1508-- --> 1 2 3 1509-- 1510-- @param value value to cast 1511-- @return Returns arguments 1512_.args = function (value) 1513 if _.isTable(value) then return table.unpack(value) 1514 else return table.unpack({value}) 1515 end 1516end 1517 1518--- 1519-- Checks if value is greater than other. 1520-- @usage _.print(_.gt(1, 3)) 1521-- --> false 1522-- _.print(_.gt(4, 3)) 1523-- --> true 1524-- 1525-- @param value The value to compare. 1526-- @param other The other value to compare. 1527_.gt = function (value, other, ...) 1528 local value, other = _.cast(value, other) 1529 if _.isString(value) or _.isNumber(value) then 1530 return value > other 1531 elseif _.isFunction(value) then 1532 return value(...) > other(...) 1533 end 1534 return false 1535end 1536 1537--- 1538-- Checks if value is greater than other. 1539-- @usage _.print(_.gte(1, 3)) 1540-- --> false 1541-- _.print(_.gte(3, 3)) 1542-- --> true 1543-- 1544-- @param value The value to compare. 1545-- @param other The other value to compare. 1546_.gte = function (value, other, ...) 1547 if _.isNil(value) or _.isBoolean(value) then 1548 return value == other 1549 end 1550 local value, other = _.cast(value, other) 1551 if _.isString(value) or _.isNumber(value) then 1552 return value >= other 1553 elseif _.isFunction(value) then 1554 return value(...) >= other(...) 1555 elseif _.isTable(value) then 1556 return false 1557 end 1558 return false 1559end 1560 1561--- 1562-- Checks if value is classified as a boolean primitive. 1563-- @usage _.print(_.isBoolean(false)) 1564-- --> true 1565-- _.print(_.isBoolean('x')) 1566-- --> false 1567-- 1568-- @param value the value to check 1569-- @return Returns true if value is correctly classified, else false. 1570_.isBoolean = function(value) 1571 return type(value) == 'boolean' 1572end 1573 1574--- 1575-- Checks if value is empty. A value is considered empty unless it’s an 1576-- arguments table, array, string with a length greater than 0 or an 1577--object with own enumerable properties. 1578--@usage _.print(_.isEmpty(true)) 1579-- --> true 1580-- _.print(_.isEmpty(1)) 1581-- --> true 1582-- _.print(_.isEmpty({1, 2, 3})) 1583-- --> false 1584-- _.print(_.isEmpty({a= 1})) 1585-- --> false 1586-- 1587-- @param value The value to inspect. 1588-- @return Returns true if value is empty, else false. 1589_.isEmpty = function (value) 1590 if _.isString(value) then 1591 return #value == 0 1592 elseif _.isTable(value) then 1593 local i = 0 1594 for k, v in _.iter(value) do 1595 i = i + 1 1596 end 1597 return i == 0 1598 else 1599 return true 1600 end 1601end 1602 1603--- 1604-- Checks if parm1 and parm2 are equal. Parm can be a boolean, string, number, function or table 1605--- 1606--@usage _.print(_.isEqual(true)) 1607-- --> true 1608-- _.print(_.isEmpty(1)) 1609-- --> true 1610-- _.print(_.isEmpty({1, 2, 3})) 1611-- --> false 1612-- _.print(_.isEmpty({a= 1})) 1613-- --> false 1614-- 1615-- @param parm1, parm2 The values to compare 1616-- @return Returns true if values are equal, else false. 1617 1618_.isEqual = function (parm1, parm2) 1619 local avoid_loops = {} 1620 local function recurse(t1, t2) 1621 if type(t1) ~= type(t2) then return false end 1622 if type(t1) ~= "table" then return t1 == t2 end 1623 if avoid_loops[t1] then return avoid_loops[t1] == t2 end 1624 avoid_loops[t1] = t2 1625 local t2keys = {} 1626 local t2tablekeys = {} 1627 for k, _ in pairs(t2) do 1628 if type(k) == "table" then table.insert(t2tablekeys, k) end 1629 t2keys[k] = true 1630 end 1631 for k1, v1 in pairs(t1) do 1632 local v2 = t2[k1] 1633 if type(k1) == "table" then 1634 local ok = false 1635 for i, tk in ipairs(t2tablekeys) do 1636 if _.isEqual(k1, tk) and recurse(v1, t2[tk]) then 1637 table.remove(t2tablekeys, i) 1638 t2keys[tk] = nil 1639 ok = true 1640 break 1641 end 1642 end 1643 if not ok then return false end 1644 else 1645 if v2 == nil then return false end 1646 t2keys[k1] = nil 1647 if not recurse(v1, v2) then return false end 1648 end 1649 end 1650 if next(t2keys) then return false end 1651 return true 1652 end 1653 return recurse(parm1, parm2) 1654end 1655 1656 1657--- 1658-- Checks if value is classified as a function primitive. 1659-- @usage _.print(_.isFunction(function() end)) 1660-- --> true 1661-- _.print(_.isFunction(1)) 1662-- --> false 1663-- 1664-- @param value the value to check 1665-- @return Returns true if value is correctly classified, else false. 1666_.isFunction = function(value) 1667 return type(value) == 'function' 1668end 1669 1670--- 1671-- Checks if value is classified as a nil primitive. 1672-- @usage _.print(_.isNil(variable) 1673-- --> true 1674-- variable = 1 1675-- _.print(_.isNil(variable)) 1676-- --> false 1677-- 1678-- @param value the value to check 1679-- @return Returns true if value is correctly classified, else false. 1680_.isNil = function(value) 1681 return type(value) == 'nil' 1682end 1683 1684--- 1685-- Checks if value is classified as a number primitive. 1686-- @usage _.print(_.isNumber(1)) 1687-- --> true 1688-- _.print(_.isNumber('1')) 1689-- --> false 1690-- 1691-- @param value the value to check 1692-- @return Returns true if value is correctly classified, else false. 1693_.isNumber = function(value) 1694 return type(value) == 'number' 1695end 1696 1697--- 1698-- Checks if value is classified as a string primitive. 1699-- @usage _.print(_.isString('1')) 1700-- --> true 1701-- _.print(_.isString(1)) 1702-- --> false 1703-- 1704-- @param value the value to check 1705-- @return Returns true if value is correctly classified, else false. 1706_.isString = function(value) 1707 return type(value) == 'string' 1708end 1709 1710--- 1711-- Checks if value is classified as a table primitive. 1712-- @usage _.print(_.isTable({'1'})) 1713-- --> true 1714-- _.print(_.isString(1)) 1715-- --> false 1716-- 1717-- @param value the value to check 1718-- @return Returns true if value is correctly classified, else false. 1719_.isTable = function(value) 1720 return type(value) == 'table' 1721end 1722 1723-- local implicitCast function (...) 1724-- if 1725-- end 1726 1727--- 1728-- Checks if value is less than other. 1729-- @usage _.print(_.lt(1, 3)) 1730-- --> true 1731-- _.print(_.lt(3, 3)) 1732-- --> false 1733-- 1734-- @param value The value to compare. 1735-- @param other The other value to compare. 1736_.lt = function (value, other, ...) 1737 local value, other = _.cast(value, other) 1738 if _.isString(value) or _.isNumber(value) then 1739 return value < other 1740 elseif _.isFunction(value) then 1741 return value(...) < other(...) 1742 end 1743 return false 1744end 1745 1746--- 1747-- Checks if value is less than or euqal to other. 1748-- @usage _.print(_.lt(4, 3)) 1749-- --> false 1750-- _.print(_.lt(3, 3)) 1751-- --> true 1752-- @param value The value to compare. 1753-- @param other The other value to compare. 1754_.lte = function (value, other, ...) 1755 if _.isNil(value) or _.isBoolean(value) then 1756 return value == other 1757 end 1758 local value, other = _.cast(value, other) 1759 if _.isString(value) or _.isNumber(value) then 1760 return value <= other 1761 elseif _.isFunction(value) then 1762 return value(...) <= other(...) 1763 elseif _.isTable(value) then 1764 return false 1765 end 1766 return false 1767end 1768 1769_.cast = function (a, b) 1770 if type(a) == type(b) then return a, b end 1771 local cast 1772 if _.isString(a) then cast = _.str 1773 elseif _.isBoolean(a) then cast = _.bool 1774 elseif _.isNumber(a) then cast = _.num 1775 elseif _.isFunction(a) then cast = _.func 1776 elseif _.isTable(a) then cast = _.table 1777 end 1778 return a, cast(b) 1779end 1780 1781--- 1782-- Cast parameters to a function that return passed parameters. 1783-- @usage local f = _.func(1, 2, 3) 1784-- _.print(f()) 1785-- --> 1 2 3 1786-- 1787-- @param value value to cast 1788-- @param ... The parameters to pass to any detected function 1789-- @return casted value 1790_.func = function (...) 1791 local t = _.table(...) 1792 return function () 1793 return _.args(t) 1794 end 1795end 1796 1797--- 1798-- Cast parameters to table using table.pack 1799-- @usage print(_.table(1, 2, 3)) 1800-- --> {1, 2, 3} 1801-- print(_.table("123")) 1802-- --> {"123"} 1803-- print(_.table(0)) 1804-- --> {0} 1805-- 1806-- @param value value to cast 1807-- @param ... The parameters to pass to any detected function 1808-- @return casted value 1809_.table = function (...) 1810 return table.pack(...) 1811end 1812 1813--- 1814-- Cast anything to boolean. If any function detected, call and cast its 1815-- result. Return false for 0, nil, table and empty string. 1816-- @usage print(_.bool({1, 2, 3})) 1817-- --> false 1818-- print(_.bool("123")) 1819-- --> true 1820-- print(_.bool(0)) 1821-- --> false 1822-- print(_.bool(function(a) return a end, "555")) 1823-- --> true 1824-- 1825-- @param value value to cast 1826-- @param ... The parameters to pass to any detected function 1827-- @return casted value 1828_.bool = function (value, ...) 1829 local bool = false 1830 if _.isString(value) then 1831 bool = #value > 0 1832 elseif _.isBoolean(value) then 1833 bool = value 1834 elseif _.isNumber(value) then 1835 bool = value ~= 0 1836 elseif _.isFunction(value) then 1837 bool = _.bool(value(...)) 1838 end 1839 return bool 1840end 1841 1842--- 1843-- Cast anything to number. If any function detected, call and cast its 1844-- result. Return 0 for nil and table. 1845-- @usage print(_.num({1, 2, 3})) 1846-- --> 0 1847-- print(_.num("123")) 1848-- --> 123 1849-- print(_.num(true)) 1850-- --> 1 1851-- print(_.num(function(a) return a end, "555")) 1852-- --> 555 1853-- 1854-- @param value value to cast 1855-- @param ... The parameters to pass to any detected function 1856-- @return casted value 1857_.num = function (value, ...) 1858 local num = 0 1859 if _.isString(value) then 1860 ok = pcall(function() 1861 num = value + 0 1862 end) 1863 if not ok then 1864 num = math.huge 1865 end 1866 elseif _.isBoolean(value) then 1867 num = value and 1 or 0 1868 elseif _.isNumber(value) then 1869 num = value 1870 elseif _.isFunction(value) then 1871 num = _.num(value(...)) 1872 end 1873 return num 1874end 1875 1876 1877local dblQuote = function (v) 1878 return '"'..v..'"' 1879end 1880 1881--- 1882-- Cast anything to string. If any function detected, call and cast its 1883-- result. 1884-- @usage print(_.str({1, 2, 3, 4, {k=2, {'x', 'y'}}})) 1885-- --> {1, 2, 3, 4, {{"x", "y"}, ["k"]=2}} 1886-- print(_.str({1, 2, 3, 4, function(a) return a end}, 5)) 1887-- --> {1, 2, 3, 4, 5} 1888-- 1889-- @param value value to cast 1890-- @param ... The parameters to pass to any detected function 1891-- @return casted value 1892_.str = function (value, ...) 1893 local str = ''; 1894 -- local v; 1895 if _.isString(value) then 1896 str = value 1897 elseif _.isBoolean(value) then 1898 str = value and 'true' or 'false' 1899 elseif _.isNil(value) then 1900 str = 'nil' 1901 elseif _.isNumber(value) then 1902 str = value .. '' 1903 elseif _.isFunction(value) then 1904 str = _.str(value(...)) 1905 elseif _.isTable(value) then 1906 str = '{' 1907 for k, v in pairs(value) do 1908 v = _.isString(v) and dblQuote(v) or _.str(v, ...) 1909 if _.isNumber(k) then 1910 str = str .. v .. ', ' 1911 else 1912 str = str .. '[' .. dblQuote(k) .. ']=' .. v .. ', ' 1913 end 1914 end 1915 str = str:sub(0, #str - 2) .. '}' 1916 end 1917 return str 1918end 1919 1920 1921--- Number 1922-- @section Number 1923 1924--- 1925-- Checks if n is between start and up to but not including, end. 1926-- If end is not specified it’s set to start with start then set to 0. 1927-- @usage print(_.inRange(-3, -4, 8)) 1928-- --> true 1929-- 1930-- @param n The number to check. 1931-- @param start The start of the range. 1932-- @param stop The end of the range. 1933-- @return Returns true if n is in the range, else false. 1934_.inRange = function (n, start, stop) 1935 local _start = _.isNil(stop) and 0 or start or 0 1936 local _stop = _.isNil(stop) and start or stop or 1 1937 return n >= _start and n < _stop 1938end 1939 1940--- 1941-- Produces a random number between min and max (inclusive). 1942-- If only one argument is provided a number between 0 and the given 1943-- number is returned. If floating is true, a floating-point number is 1944-- returned instead of an integer. 1945-- @usage _.print(_.random()) 1946-- --> 1 1947-- _.print(_.random(5)) 1948-- --> 3 1949-- _.print(_.random(5, 10, true)) 1950-- --> 8.8120200577248 1951-- 1952-- @param[opt=0] min the minimum possible value. 1953-- @param[opt=1] max the maximum possible value. 1954-- @param[opt=false] floating Specify returning a floating-point number. 1955-- @return Returns the random number. 1956_.random = function (min, max, floating) 1957 local minim = _.isNil(max) and 0 or min or 0 1958 local maxim = _.isNil(max) and min or max or 1 1959 math.randomseed(os.clock() * math.random(os.time())) 1960 local r = math.random(minim, maxim) 1961 if floating then 1962 r = r + math.random() 1963 end 1964 return r 1965end 1966 1967--- 1968-- Rounds a float number to the required number of decimals 1969-- If only one argument is provided it's round to an integer 1970-- @usage _print(_.round(math.pi) 1971-- --> 3 1972-- _.print(_.round(math.pi, 2) 1973-- --> 3.14 1974-- 1975-- @param the float to convert 1976-- @param[opt=1] the number of deceimals to round to 1977-- @return Returns the round number. 1978_.round = function (x, n) 1979 x = tonumber(x) 1980 if not(_.isNumber(x)) then return x end 1981 n = 10^(n or 0) 1982 x = x * n 1983 if x >= 0 then 1984 x = math.floor(x + 0.5) 1985 else 1986 x = math.ceil(x - 0.5) 1987 end 1988 return x / n 1989end 1990 1991 1992--- Object 1993-- @section Object 1994 1995--- 1996-- Gets the property value at path of object. If the resolved value 1997-- is nil the defaultValue is used in its place. 1998-- @usage local object = {a={b={c={d=5}}}} 1999-- _.print(_.get(object, {'a', 'b', 'c', 'd'})) 2000-- --> 5 2001-- 2002-- @param object The object to query. 2003-- @param path The path of the property to get. 2004-- @param[opt=nil] defaultValue The value returned if the resolved value is nil. 2005-- @return Returns the resolved value. 2006_.get = function (object, path, defaultValue) 2007 if _.isTable(object) then 2008 local value = object 2009 local c = 1 2010 while not _.isNil(path[c]) do 2011 if not _.isTable(value) then return defaultValue end 2012 value = value[path[c]] 2013 c = c + 1 2014 end 2015 return value or defaultValue 2016 elseif _.isString(object) then 2017 local index = path[1] 2018 return object:sub(index, index) 2019 end 2020end 2021 2022--- 2023-- Checks if path is a direct property. 2024-- @usage local object = {a={b={c={d}}}} 2025-- print(_.has(object, {'a', 'b', 'c'})) 2026-- --> true 2027-- 2028-- @param object The object to query 2029-- @param path The path to check (Array) 2030_.has = function (object, path) 2031 local obj = object 2032 local c = 1 2033 local exist = true 2034 while not _.isNil(path[c]) do 2035 obj = obj[path[c]] 2036 if _.isNil(obj) then 2037 exist = false 2038 break 2039 end 2040 c = c + 1 2041 end 2042 return exist 2043end 2044 2045--- 2046-- This method is like _.find except that it returns the key of the 2047-- first element predicate returns truthy for instead of the element itself. 2048-- @usage _.print(_.findKey({a={a = 1}, b={a = 2}, c={a = 3, x = 1}}, 2049-- function(v) 2050-- return v.a == 3 2051-- end)) 2052-- --> c 2053-- 2054-- @param object The collection to search. (table|string) 2055-- @param predicate The function invoked per iteration 2056-- @param selfArg The self binding of predicate. 2057-- @return Returns the key of the matched element, else nil 2058_.findKey = function (object, predicate, selfArg) 2059 for k, v in _.iter(object) do 2060 if callIteratee(predicate, selfArg, v, k, object) then 2061 return k 2062 end 2063 end 2064end 2065 2066--- 2067-- This method is like _.find except that it returns the key of the 2068-- first element predicate returns truthy for instead of the element itself. 2069-- @usage _.print(_.findLastKey({a={a=3}, b={a = 2}, c={a=3, x = 1}}, 2070-- function(v) 2071-- return v.a == 3 2072-- end)) 2073-- --> c 2074-- 2075-- @param object The object to search. (table|string) 2076-- @param predicate The function invoked per iteration 2077-- @param selfArg The self binding of predicate. 2078-- @return Returns the key of the matched element, else nil 2079_.findLastKey = function (object, predicate, selfArg) 2080 for k, v in _.iterRight(object) do 2081 if callIteratee(predicate, selfArg, v, k, object) then 2082 return k 2083 end 2084 end 2085end 2086 2087--- 2088-- Creates an array of function property names from all enumerable 2089-- properties, own and inherited, of object. 2090-- @usage _.print(_.functions(table)) 2091-- --> {"concat", "insert", "maxn", "pack", "remove", "sort", "unpack"} 2092-- 2093-- @param object The object to inspect. 2094-- @return Returns the new array of property names. 2095_.functions = function(object) 2096 local t = {} 2097 for k, v in _.iter(object) do 2098 if _.isFunction(v) then 2099 _.push(t, k) 2100 end 2101 end 2102 return t 2103end 2104 2105--- 2106-- Creates an object composed of the inverted keys and values of object. 2107-- If object contains duplicate values, subsequent values overwrite 2108-- property assignments of previous values unless multiValue is true. 2109-- @usage _.print(_.invert({a='1', b='2', c='3', d='3'})) 2110-- --> {[2]="b", [3]="d", [1]="a"} 2111-- _.print(_.invert({a='1', b='2', c='3', d='3'}, true)) 2112-- --> {[2]="b", [3]={"c", "d"}, [1]="a"} 2113-- 2114-- @param object The object to invert. 2115-- @param multiValue Allow multiple values per key. 2116-- @return Returns the new inverted object. 2117_.invert = function (object, multiValue) 2118 local t = {} 2119 for k, v in _.iter(object) do 2120 if multiValue and not _.isNil(t[v]) then 2121 t[v] = { t[v] } 2122 _.push(t[v], k) 2123 else 2124 t[v] = k 2125 end 2126 end 2127 return t 2128 2129end 2130 2131local getSortedKeys = function(collection, desc) 2132 local sortedKeys = {} 2133 for k, v in pairs(collection) do 2134 table.insert(sortedKeys, k) 2135 end 2136 if desc then 2137 table.sort(sortedKeys, _.gt) 2138 else 2139 table.sort(sortedKeys, _.lt) 2140 end 2141 return sortedKeys 2142end 2143 2144--- 2145-- Creates an array of the own enumerable property names of object. 2146-- @usage _.print(_.keys("test")) 2147-- --> {1, 2, 3, 4} 2148-- _.print(_.keys({a=1, b=2, c=3})) 2149-- --> {"c", "b", "a"} 2150-- 2151-- @param object The object to query. (table|string) 2152-- @return Returns the array of property names. 2153_.keys = function (object) 2154 if _.isTable(object) then 2155 return getSortedKeys(object) 2156 elseif _.isString(object) then 2157 local keys = {} 2158 for i=1, #object do 2159 keys[i] = i 2160 end 2161 return keys 2162 end 2163end 2164 2165--- 2166-- Creates a two dimensional array of the key-value pairs for object. 2167-- @usage _.print(_.pairs({1, 2, 'x', a='b'})) 2168-- --> {{1, 1}, {2, 2}, {3, "x"}, {"a", "b"}} 2169-- 2170-- @param object The object to query 2171-- @return Returns the new array of key-value pairs. 2172_.pairs = function (object) 2173 local t = {} 2174 for k, v in _.iter(object) do 2175 _.push(t, {k, v}) 2176 end 2177 return t 2178end 2179 2180--- 2181-- This method is like _.get except that if the resolved value is a 2182-- function it’s invoked with additional parameters and its result is returned. 2183-- @usage local object = {a=5, b={c=function(a) print(a) end}} 2184-- _.result(object, {'b', 'c'}, nil, 5) 2185-- --> 5 2186-- 2187-- @param object The object to query. 2188-- @param path The path of the property to get. 2189-- @param[opt=nil] defaultValue The value returned if the resolved value is nil. 2190-- @param ... Additional parameters to pass to function 2191-- @return Returns the resolved value. 2192_.result = function (object, path, defaultValue, ...) 2193 local result = _.get(object, path, defaultValue) 2194 if _.isFunction(result) then 2195 return result(...) 2196 else 2197 return result 2198 end 2199end 2200 2201 2202--- 2203-- Creates an array of the own enumerable property values of object. 2204-- @usage _.print(_.values("test")) 2205-- --> {"t", "e", "s", "t"} 2206-- _.print(_.values({a=1, b=2, c=3})) 2207-- --> {1, 3, 2} 2208-- 2209-- @param object The object to query. (table|string) 2210-- @return Returns the array of property values. 2211_.values = function (object) 2212 local t = {} 2213 for k, v in _.iter(object) do 2214 _.push(t, v) 2215 end 2216 return t 2217end 2218 2219--- String 2220-- @section String 2221 2222 2223--- Utility 2224-- @section Utility 2225 2226--- 2227-- Creates a function that returns value. 2228-- @usage local object = {x=5} 2229-- local getter = _.constant(object) 2230-- _.print(getter() == object); 2231-- --> true 2232-- 2233-- @param value Any value. 2234-- @return Returns the new function. 2235_.constant = function(value) 2236 return _.func(value) 2237end 2238 2239--- 2240-- This method returns the first argument provided to it. 2241-- @usage local object = {x=5} 2242-- _.print(_.identity(object) == object); 2243-- --> true 2244-- 2245-- @param value Any value. 2246-- @return Returns value. 2247_.identity = function(...) return ... end 2248 2249local iterCollection = function(table, desc) 2250 local sortedKeys = getSortedKeys(table, desc) 2251 local i = 0 2252 return function () 2253 if _.lt(i, #sortedKeys) then 2254 i = i + 1 2255 local key = sortedKeys[i] 2256 return key, table[key] 2257 end 2258 end 2259end 2260 2261_.iter = function(value) 2262 if _.isString(value) then 2263 local i = 0 2264 return function() 2265 if _.lt(i, #value) then 2266 i = i + 1 2267 local c = value:sub(i, i) 2268 return i, c 2269 end 2270 end 2271 elseif _.isTable(value) then 2272 return iterCollection(value) 2273 else 2274 return function() end 2275 end 2276end 2277 2278_.iterRight = function(value) 2279 if _.isString(value) then 2280 local i = #value + 1 2281 return function() 2282 if _.gt(i, 1) then 2283 i = i - 1 2284 local c = value:sub(i, i) 2285 return i, c 2286 end 2287 end 2288 elseif _.isTable(value) then 2289 return iterCollection(value, true) 2290 else 2291 return function() end 2292 end 2293end 2294 2295--- 2296-- A no-operation function that returns nil regardless of the arguments 2297-- it receives. 2298-- @usage local object = {x=5} 2299-- _.print(_.noop(object) == nil); 2300-- --> true 2301-- 2302-- @param ... Any arguments 2303-- @return Returns nil 2304_.noop = function(...) return nil end 2305 2306 2307--- 2308-- Print more readable representation of arguments using _.str 2309-- @usage _.print({1, 2, 3, 4, {k=2, {'x', 'y'}}}) 2310-- --> {1, 2, 3, 4, {{"x", "y"}, [k]=2}} 2311-- 2312-- @param ... values to print 2313-- @return Return human readable string of the value 2314_.print = function(...) 2315 local t = _.table(...) 2316 for i, v in ipairs(t) do 2317 t[i] = _.str(t[i]) 2318 end 2319 return print(_.args(t)) 2320end 2321 2322--- 2323-- Creates an array of numbers (positive and/or negative) progressing 2324-- from start up to, including, end. 2325-- If end is not specified it’s set to start with start then set to 1. 2326-- @usage _.print(_.range(5, 20, 3)) 2327-- --> {5, 8, 11, 14, 17, 20} 2328-- 2329-- @param[opt=1] start The start of the range. 2330-- @param stop Then end of the range. 2331-- @param[opt=1] step The value to increment or decrement by 2332-- @return Returns the new array of numbers 2333_.range = function(start, ...) 2334 local start = start 2335 local args = _.table(...) 2336 local a, b, c 2337 if #args == 0 then 2338 a = 1 -- according to lua 2339 b = start 2340 c = 1 2341 else 2342 a = start 2343 b = args[1] 2344 c = args[2] or 1 2345 end 2346 local t = {} 2347 for i = a, b, c do 2348 _.push(t, i) 2349 end 2350 return t 2351end 2352 2353return _ 2354 2355