1before: 2 this_module = "std.list" 3 global_table = "_G" 4 5 exported_apis = { "append", "compare", "concat", "cons", "depair", 6 "elems", "enpair", "filter", "flatten", "foldl", 7 "foldr", "index_key", "index_value", "map", 8 "map_with", "project", "relems", "rep", "reverse", 9 "shape", "sub", "tail", "transpose", "zip_with" } 10 11 M = require (this_module) 12 13 List = M {} 14 l = List {"foo", "bar", "baz"} 15 16 17 18specify std.list: 19- context when required: 20 - context by name: 21 - it does not touch the global table: 22 expect (show_apis {added_to="_G", by="std.list"}). 23 to_equal {} 24 - it exports the documented apis: 25 t = {} 26 for k in pairs (M) do t[#t + 1] = k end 27 expect (t).to_contain.a_permutation_of (exported_apis) 28 29 - context via the std module: 30 - it does not touch the global table: 31 expect (show_apis {added_to=global_table, by="std"}). 32 to_equal {} 33 34- describe construction: 35 - context from List clone method: 36 - it constructs a new list: 37 l = List:clone {} 38 expect (l).not_to_be (List) 39 expect (prototype (l)).to_be "List" 40 - it reuses the List metatable: 41 l, m = List:clone {"l"}, List:clone {"m"} 42 expect (getmetatable (l)).to_be (getmetatable (m)) 43 - it initialises List with constructor parameters: 44 m = List:clone {"foo", "bar", "baz"} 45 expect (m).to_equal (l) 46 - it serves as a prototype for new instances: 47 m = l:clone {} 48 expect (prototype (m)).to_be "List" 49 expect (m).to_equal (l) 50 expect (getmetatable (m)).to_be (getmetatable (l)) 51 52 # List {args} is just syntactic sugar for List:clone {args} 53 - context from List object prototype: 54 - it constructs a new List: 55 l = List {} 56 expect (l).not_to_be (List) 57 expect (prototype (l)).to_be "List" 58 - it reuses the List metatable: 59 l, m = List {"l"}, List {"m"} 60 expect (getmetatable (l)).to_be (getmetatable (m)) 61 - it initialises List with constructor parameters: 62 m = List {"foo", "bar", "baz"} 63 expect (m).to_equal (l) 64 - it serves as a prototype for new instances: 65 m = l {} 66 expect (prototype (m)).to_be "List" 67 expect (m).to_equal (l) 68 expect (getmetatable (m)).to_be (getmetatable (l)) 69 70 71- describe metatable propagation: 72 - it reuses the metatable for List constructed objects: 73 m = List {"foo", "bar"} 74 expect (getmetatable (m)).to_be (getmetatable (l)) 75 76 77- describe append: 78 - before: 79 f = M.append 80 81 - context with bad arguments: 82 badargs.diagnose (f, "std.list.append (List, any)") 83 84 - context as a module function: 85 - it returns a List object: 86 expect (prototype (f (l, "quux"))).to_be "List" 87 - it works for an empty List: 88 expect (f (List {}, "quux")).to_equal (List {"quux"}) 89 - it appends an item to a List: 90 expect (f (l, "quux")). 91 to_equal (List {"foo", "bar", "baz", "quux"}) 92 93 - context as an object method: 94 - before: 95 f = l.append 96 97 - it returns a List object: 98 expect (prototype (f (l, "quux"))).to_be "List" 99 - it works for an empty List: 100 expect (f (List {}, "quux")).to_equal (List {"quux"}) 101 - it appends an item to a List: 102 expect (f (l, "quux")). 103 to_equal (List {"foo", "bar", "baz", "quux"}) 104 105 - context as a List metamethod: 106 - it returns a List object: 107 expect (prototype (l + "quux")).to_be "List" 108 - it works for an empty list: 109 expect (List {} + "quux").to_equal (List {"quux"}) 110 - it appends an item to a list: 111 expect (l + "quux"). 112 to_equal (List {"foo", "bar", "baz", "quux"}) 113 114 115- describe compare: 116 - before: 117 a, b = List {"foo", "bar"}, List {"foo", "baz"} 118 119 f = M.compare 120 121 - context with bad arguments: 122 badargs.diagnose (f, "std.list.compare (List, List|table)") 123 124 - context as a module function: 125 - it returns -1 when the first list is less than the second: 126 expect (f (a, {"foo", "baz"})).to_be (-1) 127 expect (f (a, List {"foo", "baz"})).to_be (-1) 128 - it returns -1 when the second list has additional elements: 129 expect (f (List {"foo"}, {"foo", "bar"})).to_be (-1) 130 expect (f (List {"foo"}, List {"foo", "bar"})).to_be (-1) 131 - it returns 0 when two lists are the same: 132 expect (f (a, {"foo", "bar"})).to_be (0) 133 expect (f (a, List {"foo", "bar"})).to_be (0) 134 - it returns +1 when the first list is greater than the second: 135 expect (f (a, {"baz", "quux"})).to_be (1) 136 expect (f (a, List {"baz", "quux"})).to_be (1) 137 - it returns +1 when the first list has additional elements: 138 expect (f (a, {"foo"})).to_be (1) 139 expect (f (a, List {"foo"})).to_be (1) 140 - it compares numerically when both arguments can be coerced: 141 a, b = List {"1", "2", "3"}, List {"1", "2", "10"} 142 expect (f (a, b)).to_be (-1) 143 144 - context as an object method: 145 - before: 146 f = a.compare 147 148 - it returns -1 when the first list is less than the second: 149 expect (f (a, {"foo", "baz"})).to_be (-1) 150 expect (f (a, List {"foo", "baz"})).to_be (-1) 151 - it returns -1 when the second list has additional elements: | 152 b = List {"foo"} 153 expect (f (b, {"foo", "bar"})).to_be (-1) 154 expect (List {"foo"}:compare (List {"foo", "bar"})).to_be (-1) 155 - it returns 0 when two lists are the same: 156 expect (f (a, {"foo", "bar"})).to_be (0) 157 expect (f (a, List {"foo", "bar"})).to_be (0) 158 - it returns +1 when the first list is greater than the second: 159 expect (f (a, {"baz", "quux"})).to_be (1) 160 expect (f (a, List {"baz", "quux"})).to_be (1) 161 - it returns +1 when the first list has additional elements: 162 expect (f (a, {"foo"})).to_be (1) 163 expect (f (a, List {"foo"})).to_be (1) 164 - it compares numerically when both arguments can be coerced: 165 a, b = List {"1", "2", "3"}, List {"1", "2", "10"} 166 expect (f (a, b)).to_be (-1) 167 168 - context as a '<' List metamethod: 169 - it succeeds when the first list is less than the second: 170 expect (a < b).to_be (true) 171 - it fails when the first list is not less than the second: 172 expect (a < a).to_be (false) 173 expect (b < a).to_be (false) 174 - it compares numerically when both arguments can be coerced: 175 a, b = List {"1", "2", "3"}, List {"1", "2", "10"} 176 expect (a < b).to_be (true) 177 178 - context as a '>' List metamethod: 179 - it succeeds when the first list is greater than the second: 180 expect (b > a).to_be (true) 181 - it fails when the first list is not greater than the second: 182 expect (b > b).to_be (false) 183 expect (a > b).to_be (false) 184 - it compares numerically when both arguments can be coerced: 185 a, b = List {"1", "2", "3"}, List {"1", "2", "10"} 186 expect (a > b).to_be (false) 187 188 - context as a '<=' List metamethod: 189 - it succeeds when the first list is less than or equal to the second: 190 expect (a <= b).to_be (true) 191 expect (a <= a).to_be (true) 192 - it fails when the first list is not less than or equal to the second: 193 expect (b <= a).to_be (false) 194 - it compares numerically when both arguments can be coerced: 195 a, b = List {"1", "2", "3"}, List {"1", "2", "10"} 196 expect (a <= b).to_be (true) 197 198 - context as a '>=' List metamethod: 199 - it succeeds when the first list is greater than or equal to the second: 200 expect (b >= a).to_be (true) 201 expect (b >= b).to_be (true) 202 - it fails when the first list is not greater than or equal to the second: 203 expect (a >= b).to_be (false) 204 - it compares numerically when both arguments can be coerced: 205 a, b = List {"1", "2", "3"}, List {"1", "2", "10"} 206 expect (a >= b).to_be (false) 207 208 209- describe concat: 210 - before: 211 l = List {"foo", "bar"} 212 213 f = M.concat 214 215 - context with bad arguments: 216 badargs.diagnose (f, "std.list.concat (List, List|table*)") 217 218 - context as a module function: 219 - it returns a List object: 220 expect (prototype (f (l, l))).to_be "List" 221 - it works for an empty List: 222 expect (f (List {}, {"baz"})).to_equal (List {"baz"}) 223 expect (f (List {}, List {"baz"})).to_equal (List {"baz"}) 224 - it concatenates Lists: 225 expect (f (l, {"baz", "quux"})). 226 to_equal (List {"foo", "bar", "baz", "quux"}) 227 expect (f (l, List {"baz", "quux"})). 228 to_equal (List {"foo", "bar", "baz", "quux"}) 229 expect (f (l, {"baz"}, {"quux"})). 230 to_equal (List {"foo", "bar", "baz", "quux"}) 231 expect (f (l, List {"baz"}, List {"quux"})). 232 to_equal (List {"foo", "bar", "baz", "quux"}) 233 234 - context as an object method: 235 - before: 236 f = l.concat 237 238 - it returns a List object: 239 expect (prototype (f (l, l))).to_be "List" 240 - it works for an empty List: 241 expect (f (List {}, {"baz"})).to_equal (List {"baz"}) 242 expect (f (List {}, List {"baz"})).to_equal (List {"baz"}) 243 - it concatenates Lists: 244 expect (f (l, {"baz", "quux"})). 245 to_equal (List {"foo", "bar", "baz", "quux"}) 246 expect (f (l, List {"baz", "quux"})). 247 to_equal (List {"foo", "bar", "baz", "quux"}) 248 expect (f (l, {"baz"}, {"quux"})). 249 to_equal (List {"foo", "bar", "baz", "quux"}) 250 expect (f (l, List {"baz"}, List {"quux"})). 251 to_equal (List {"foo", "bar", "baz", "quux"}) 252 253 # Beware that .. operations are right associative 254 - context as a List metamethod: 255 - it returns a List object: 256 expect (prototype (l .. List {"baz"})).to_be "List" 257 - it works for an empty List: 258 expect (List {} .. {"baz"}).to_equal (List {"baz"}) 259 expect (List {} .. List {"baz"}).to_equal (List {"baz"}) 260 - it concatenates Lists: 261 expect (l .. {"baz", "quux"}). 262 to_equal (List {"foo", "bar", "baz", "quux"}) 263 expect (l .. List {"baz", "quux"}). 264 to_equal (List {"foo", "bar", "baz", "quux"}) 265 expect ({"baz"} .. {"quux"} .. l). 266 to_equal (List {"baz", "quux", "foo", "bar"}) 267 expect (l .. List {"baz"} .. List {"quux"}). 268 to_equal (List {"foo", "bar", "baz", "quux"}) 269 270 271- describe cons: 272 - before: 273 f = M.cons 274 275 - context with bad arguments: 276 badargs.diagnose (f, "std.list.cons (List, any)") 277 278 - context as a module function: 279 - it returns a List object: 280 expect (prototype (f (l, "x"))).to_be "List" 281 - it prepends an item to a List: 282 expect (f (l, "x")).to_equal (List {"x", "foo", "bar", "baz"}) 283 - it works for empty Lists: 284 expect (f (List {}, "x")).to_equal (List {"x"}) 285 286 - context as an object method: 287 - before: 288 f = l.cons 289 290 - it returns a List object: 291 expect (prototype (f (l, "x"))).to_be "List" 292 - it prepends an item to a List: 293 expect (f (l, "x")).to_equal (List {"x", "foo", "bar", "baz"}) 294 - it works for empty Lists: 295 expect (f (List {}, "x")).to_equal (List {"x"}) 296 297 298- describe depair: 299 - before: 300 l = List {List {1, "first"}, List {2, "second"}, List {"third", 4}} 301 t = {"first", "second", third = 4} 302 303 - context as a module function: 304 - before: 305 f = M.depair 306 307 - it writes a deprecation warning: 308 setdebug { deprecate = "nil" } 309 expect (capture (f, {l})).to_contain_error "was deprecated" 310 setdebug { deprecate = false } 311 expect (capture (f, {l})).not_to_contain_error "was deprecated" 312 313 - it returns a primitive table: 314 expect (prototype (f (l))).to_be "table" 315 - it works with an empty List: 316 l = List {} 317 expect (f (l)).to_equal {} 318 - it is the inverse of enpair: 319 expect (f (l)).to_equal (t) 320 321 - context as an object method: 322 - before: 323 f = l.depair 324 325 - it writes a deprecation warning: 326 setdebug { deprecate = "nil" } 327 expect (capture (f, {l})).to_contain_error "was deprecated" 328 setdebug { deprecate = false } 329 expect (capture (f, {l})).not_to_contain_error "was deprecated" 330 331 - it returns a primitive table: 332 expect (prototype (f (l))).to_be "table" 333 - it works with an empty List: 334 expect (f (List {})).to_equal {} 335 - it is the inverse of enpair: 336 expect (f (l)).to_equal (t) 337 338 339- describe elems: 340 - context as a module function: 341 - before: 342 f = M.elems 343 344 - it writes a deprecation warning: 345 setdebug { deprecate = "nil" } 346 expect (capture (f, {{}})).to_contain_error "was deprecated" 347 setdebug { deprecate = false } 348 expect (capture (f, {{}})).not_to_contain_error "was deprecated" 349 350 - it is an iterator over List members: 351 t = {} 352 for e in f (l) do table.insert (t, e) end 353 expect (t).to_equal {"foo", "bar", "baz"} 354 - it works for an empty List: 355 t = {} 356 for e in f (List {}) do table.insert (t, e) end 357 expect (t).to_equal {} 358 359 - context as an object method: 360 - before: 361 f = l.elems 362 363 - it writes a deprecation warning: 364 setdebug { deprecate = "nil" } 365 expect (capture (f, {l})).to_contain_error "was deprecated" 366 setdebug { deprecate = false } 367 expect (capture (f, {l})).not_to_contain_error "was deprecated" 368 369 - it is an iterator over List members: 370 t = {} 371 for e in l:elems () do table.insert (t, e) end 372 expect (t).to_equal {"foo", "bar", "baz"} 373 - it works for an empty List: 374 t, l = {}, List {} 375 for e in l:elems () do table.insert (t, e) end 376 expect (t).to_equal {} 377 378 379- describe enpair: 380 - before: 381 t = {"first", "second", third = 4} 382 f = M.enpair 383 384 - it writes a deprecation warning: 385 setdebug { deprecate = "nil" } 386 expect (capture (f, {t})).to_contain_error "was deprecated" 387 setdebug { deprecate = false } 388 expect (capture (f, {t})).not_to_contain_error "was deprecated" 389 390 - context as a module function: 391 - it returns a List object: 392 expect (prototype (f (t))).to_be "List" 393 - it works for an empty table: 394 expect (f {}).to_equal (List {}) 395 - it turns a table into a List of pairs: 396 expect (f (t)). 397 to_equal (List {List {1, "first"}, List {2, "second"}, List {"third", 4}}) 398 399 400- describe filter: 401 - before: 402 l = List {"foo", "bar", "baz", "quux"} 403 p = function (e) return (e:match "a" ~= nil) end 404 405 - context as a module function: 406 - before: 407 f = M.filter 408 409 - it writes a deprecation warning: 410 setdebug { deprecate = "nil" } 411 expect (capture (f, {p, l})).to_contain_error "was deprecated" 412 setdebug { deprecate = false } 413 expect (capture (f, {p, l})).not_to_contain_error "was deprecated" 414 415 - it returns a List object: 416 expect (prototype (f (p, l))).to_be "List" 417 - it works for an empty List: 418 expect (f (p, List {})).to_equal (List {}) 419 - it filters a List according to a predicate: 420 expect (f (p, l)).to_equal (List {"bar", "baz"}) 421 422 - context as an object method: 423 - before: 424 f = l.filter 425 426 - it writes a deprecation warning: 427 setdebug { deprecate = "nil" } 428 expect (capture (f, {l, p})).to_contain_error "was deprecated" 429 setdebug { deprecate = false } 430 expect (capture (f, {l, p})).not_to_contain_error "was deprecated" 431 432 - it returns a List object: 433 expect (prototype (f (l, p))).to_be "List" 434 - it works for an empty List: 435 expect (f (List {}, p)).to_equal (List {}) 436 - it filters a List according to a predicate: 437 expect (f (l, p)).to_equal (List {"bar", "baz"}) 438 439 440- describe flatten: 441 - before: 442 l = List {List {List {"one"}}, "two", List {List {"three"}, "four"}} 443 444 - context as a module function: 445 - before: 446 f = M.flatten 447 448 - it writes a deprecation warning: 449 setdebug { deprecate = "nil" } 450 expect (capture (f, {l})).to_contain_error "was deprecated" 451 setdebug { deprecate = false } 452 expect (capture (f, {l})).not_to_contain_error "was deprecated" 453 454 - it returns a List object: 455 expect (prototype (f (l))).to_be "List" 456 - it works for an empty List: 457 l = List {} 458 expect (f (l)).to_equal (List {}) 459 - it flattens a List: 460 expect (f (l)). 461 to_equal (List {"one", "two", "three", "four"}) 462 463 - context as an object method: 464 - before: 465 f = l.flatten 466 467 - it writes a deprecation warning: 468 setdebug { deprecate = "nil" } 469 expect (capture (f, {l})).to_contain_error "was deprecated" 470 setdebug { deprecate = false } 471 expect (capture (f, {l})).not_to_contain_error "was deprecated" 472 473 - it returns a List object: 474 expect (prototype (f (l))).to_be "List" 475 - it works for an empty List: 476 l = List {} 477 expect (f (l)).to_equal (List {}) 478 - it flattens a List: 479 expect (f (l)). 480 to_equal (List {"one", "two", "three", "four"}) 481 482 483- describe foldl: 484 - before: 485 op = require "std.operator" 486 l = List {3, 4} 487 488 - context as a module function: 489 - before: 490 f = M.foldl 491 492 - it writes a deprecation warning: 493 setdebug { deprecate = "nil" } 494 expect (capture (f, {op.sum, 1, l})). 495 to_contain_error "was deprecated" 496 setdebug { deprecate = false } 497 expect (capture (f, {op.sum, 1, l})). 498 not_to_contain_error "was deprecated" 499 500 - context with a table: 501 - it works with an empty table: 502 expect (f (op.sum, 10000, {})).to_be (10000) 503 - it folds a binary function through a table: 504 expect (f (op.sum, 10000, {1, 10, 100})).to_be (10111) 505 - it folds from left to right: 506 expect (f (op.pow, 2, {3, 4})).to_be ((2 ^ 3) ^ 4) 507 508 - context with a List: 509 - it works with an empty List: 510 expect (f (op.sum, 10000, List {})).to_be (10000) 511 - it folds a binary function through a List: 512 expect (f (op.sum, 10000, List {1, 10, 100})). 513 to_be (10111) 514 - it folds from left to right: 515 expect (f (op.pow, 2, List {3, 4})).to_be ((2 ^ 3) ^ 4) 516 517 - context as an object method: 518 - before: 519 f = l.foldl 520 521 - it writes a deprecation warning: 522 setdebug { deprecate = "nil" } 523 expect (capture (f, {l, op.sum, 1})). 524 to_contain_error "was deprecated" 525 setdebug { deprecate = false } 526 expect (capture (f, {l, op.sum, 1})). 527 not_to_contain_error "was deprecated" 528 529 - it works with an empty List: 530 l = List {} 531 expect (f (l, op.sum, 2)).to_be (2) 532 - it folds a binary function through a List: 533 expect (f (l, op.sum, 2)).to_be (9) 534 - it folds from left to right: 535 expect (f (l, op.pow, 2)).to_be ((2 ^ 3) ^ 4) 536 537 538- describe foldr: 539 - before: 540 op = require "std.operator" 541 l = List {10000, 100} 542 543 - context as a module function: 544 - before: 545 f = M.foldr 546 547 - it writes a deprecation warning: 548 setdebug { deprecate = "nil" } 549 expect (capture (f, {op.sum, 1, {10}})). 550 to_contain_error "was deprecated" 551 setdebug { deprecate = false } 552 expect (capture (f, {op.sum, 1, {10}})). 553 not_to_contain_error "was deprecated" 554 555 - context with a table: 556 - it works with an empty table: 557 expect (f (op.sum, 10000, {})).to_be (10000) 558 - it folds a binary function through a table: 559 expect (f (op.sum, 10000, {1, 10, 100})).to_be (10111) 560 - it folds from right to left: 561 expect (f (op.quot, 10, {10000, 100})).to_be (10000 / (100 / 10)) 562 563 - context with a List: 564 - it works with an empty List: 565 expect (f (op.sum, 10000, List {})).to_be (10000) 566 - it folds a binary function through a List: 567 expect (f (op.sum, 10000, List {1, 10, 100})). 568 to_be (10111) 569 - it folds from right to left: 570 expect (f (op.quot, 10, List {10000, 100})). 571 to_be (10000 / (100 / 10)) 572 573 - context as an object method: 574 - before: 575 f = l.foldr 576 577 - it writes a deprecation warning: 578 setdebug { deprecate = "nil" } 579 expect (capture (f, {l, op.sum, 1})). 580 to_contain_error "was deprecated" 581 setdebug { deprecate = false } 582 expect (capture (f, {l, op.sum, 1})). 583 not_to_contain_error "was deprecated" 584 585 - it works with an empty List: 586 l = List {} 587 expect (f (l, op.sum, 10)).to_be (10) 588 - it folds a binary function through a List: 589 expect (f (l, op.sum, 10)).to_be (10110) 590 - it folds from right to left: 591 expect (f (l, op.quot, 10)).to_be (10000 / (100 / 10)) 592 593 594- describe index_key: 595 - context as a module function: 596 - before: 597 f = M.index_key 598 599 - it writes a deprecation warning: 600 setdebug { deprecate = "nil" } 601 expect (capture (f, {1, List {{1}}})). 602 to_contain_error "was deprecated" 603 setdebug { deprecate = false } 604 expect (capture (f, {1, List {{1}}})). 605 not_to_contain_error "was deprecated" 606 607 - it makes a map of matched table field values to table List offsets: 608 l = List {{a = "b", c = "d"}, {e = "x", f = "g"}, {a = "x"}} 609 t = f ("a", l) 610 expect (t).to_equal {b = 1, x = 3} 611 for k, v in pairs (t) do 612 expect (k).to_equal (l[v]["a"]) 613 end 614 - it captures only the last matching List offset: 615 l = List {{a = "b"}, {a = "x"}, {a = "b"}} 616 t = f ("a", l) 617 expect (t.b).not_to_be (1) 618 expect (t.x).to_be (2) 619 expect (t.b).to_be (3) 620 - it produces incomplete indices when faced with repeated matching table values: 621 l = List {{1, 2, 3}, {2}, {2, 1, 3, 2, 1}} 622 expect (f (1, l)).to_equal {1, 3} 623 expect (f (2, l)).to_equal {3, 1} 624 expect (f (3, l)).to_equal {nil, nil, 3} 625 626 - context as an object method: 627 - before: 628 f = l.index_key 629 630 - it writes a deprecation warning: 631 setdebug { deprecate = "nil" } 632 expect (capture (f, {l, 1})).to_contain_error "was deprecated" 633 setdebug { deprecate = false } 634 expect (capture (f, {l, 1})).not_to_contain_error "was deprecated" 635 636 - it makes a map of matched table field values to table List offsets: 637 l = List {{a = "b", c = "d"}, {e = "x", f = "g"}, {a = "x"}} 638 t = l:index_key "a" 639 expect (t).to_equal {b = 1, x = 3} 640 for k, v in pairs (t) do 641 expect (k).to_equal (l[v]["a"]) 642 end 643 - it captures only the last matching List offset: 644 l = List {{a = "b"}, {a = "x"}, {a = "b"}} 645 t = l:index_key "a" 646 expect (t.b).not_to_be (1) 647 expect (t.x).to_be (2) 648 expect (t.b).to_be (3) 649 - it produces incomplete indices when faced with repeated matching table values: 650 l = List {{1, 2, 3}, {2}, {2, 1, 3, 2, 1}} 651 expect (l:index_key (1)).to_equal {1, 3} 652 expect (l:index_key (2)).to_equal {3, 1} 653 expect (l:index_key (3)).to_equal {nil, nil, 3} 654 655 656- describe index_value: 657 - context as a module function: 658 - before: 659 f = M.index_value 660 661 - it writes a deprecation warning: 662 setdebug { deprecate = "nil" } 663 expect (capture (f, {1, List {{1}}})). 664 to_contain_error "was deprecated" 665 setdebug { deprecate = false } 666 expect (capture (f, {1, List {{1}}})). 667 not_to_contain_error "was deprecated" 668 669 - it makes a table of matched table field values to table List references: 670 l = List {{a = "b", c = "d"}, {e = "x", f = "g"}, {a = "x"}} 671 t = f ("a", l) 672 expect (t).to_equal {b = l[1], x = l[3]} 673 for k, v in pairs (t) do 674 expect (k).to_equal (v["a"]) 675 end 676 - it captures only the last matching List offset: 677 l = List {{a = "b"}, {a = "x"}, {a = "b"}} 678 t = f ("a", l) 679 expect (t.b).not_to_be (l[1]) 680 expect (t.x).to_be (l[2]) 681 expect (t.b).to_be (l[3]) 682 - it produces incomplete indices when faced with repeated matching table values: 683 l = List {{1, 2, 3}, {2}, {2, 1, 3, 2, 1}} 684 expect (f (1, l)).to_equal {l[1], l[3]} 685 expect (f (2, l)).to_equal {l[3], l[1]} 686 expect (f (3, l)).to_equal {nil, nil, l[3]} 687 688 - context as an object method: 689 - before: 690 l = List {{1}} 691 692 f = l.index_value 693 694 - it writes a deprecation warning: 695 setdebug { deprecate = "nil" } 696 expect (capture (f, {l, 1})).to_contain_error "was deprecated" 697 setdebug { deprecate = false } 698 expect (capture (f, {l, 1})).not_to_contain_error "was deprecated" 699 700 - it makes a table of matched table field values to table List references: 701 l = List {{a = "b", c = "d"}, {e = "x", f = "g"}, {a = "x"}} 702 t = l:index_value "a" 703 expect (t).to_equal {b = l[1], x = l[3]} 704 for k, v in pairs (t) do 705 expect (k).to_equal (v["a"]) 706 end 707 - it captures only the last matching List offset: 708 l = List {{a = "b"}, {a = "x"}, {a = "b"}} 709 t = l:index_value "a" 710 expect (t.b).not_to_be (l[1]) 711 expect (t.x).to_be (l[2]) 712 expect (t.b).to_be (l[3]) 713 - it produces incomplete indices when faced with repeated matching table values: 714 l = List {{1, 2, 3}, {2}, {2, 1, 3, 2, 1}} 715 expect (l:index_value (1)).to_equal {l[1], l[3]} 716 expect (l:index_value (2)).to_equal {l[3], l[1]} 717 expect (l:index_value (3)).to_equal {nil, nil, l[3]} 718 719 720- describe map: 721 - before: 722 l = List {1, 2, 3, 4, 5} 723 sq = function (n) return n * n end 724 725 - context as a module function: 726 - before: 727 f, badarg = init (M, this_module, "map") 728 729 - it writes a deprecation warning: 730 setdebug { deprecate = "nil" } 731 expect (capture (f, {sq, l})).to_contain_error "was deprecated" 732 setdebug { deprecate = false } 733 expect (capture (f, {sq, l})).not_to_contain_error "was deprecated" 734 735 - it returns a List object: 736 expect (prototype (f (sq, l))).to_be "List" 737 - it works for an empty List: 738 expect (f (sq, List {})).to_equal (List {}) 739 - it creates a new List: 740 o = l 741 m = f (sq, l) 742 expect (l).to_equal (o) 743 expect (m).not_to_equal (o) 744 expect (l).to_equal (List {1, 2, 3, 4, 5}) 745 - it maps a function over a List: 746 expect (f (sq, l)).to_equal (List {1, 4, 9, 16, 25}) 747 748 - context as an object method: 749 - before: 750 f = l.map 751 752 - it writes a deprecation warning: 753 setdebug { deprecate = "nil" } 754 expect (capture (f, {l, sq})).to_contain_error "was deprecated" 755 setdebug { deprecate = false } 756 expect (capture (f, {l, sq})).not_to_contain_error "was deprecated" 757 758 - it returns a List object: 759 m = f (l, sq) 760 expect (prototype (m)).to_be "List" 761 - it works for an empty List: 762 expect (f (List {}, sq)).to_equal (List {}) 763 - it creates a new List: 764 o = l 765 m = f (l, sq) 766 expect (l).to_equal (o) 767 expect (m).not_to_equal (o) 768 expect (l).to_equal (List {1, 2, 3, 4, 5}) 769 - it maps a function over a List: 770 expect (f (l, sq)).to_equal (List {1, 4, 9, 16, 25}) 771 772 773- describe map_with: 774 - before: 775 l = List {List {1, 2, 3}, List {4, 5}} 776 fn = function (...) return select ("#", ...) end 777 778 - context as a module function: 779 - before: 780 f = M.map_with 781 782 - it writes a deprecation warning: 783 setdebug { deprecate = "nil" } 784 expect (capture (f, {fn, l})).to_contain_error "was deprecated" 785 setdebug { deprecate = false } 786 expect (capture (f, {fn, l})).not_to_contain_error "was deprecated" 787 788 - it returns a List object: 789 m = f (fn, l) 790 expect (prototype (m)).to_be "List" 791 - it creates a new List: 792 o = l 793 m = f (fn, l) 794 expect (l).to_equal (o) 795 expect (m).not_to_equal (o) 796 expect (l).to_equal (List {List {1, 2, 3}, List {4, 5}}) 797 - it maps a function over a List: 798 expect (f (fn, l)).to_equal (List {3, 2}) 799 - it works for an empty List: 800 l = List {} 801 expect (f (fn, l)).to_equal (List {}) 802 803 - context as an object method: 804 - before: 805 f = l.map_with 806 807 - it writes a deprecation warning: 808 setdebug { deprecate = "nil" } 809 expect (capture (f, {l, fn})).to_contain_error "was deprecated" 810 setdebug { deprecate = false } 811 expect (capture (f, {l, fn})).not_to_contain_error "was deprecated" 812 813 - it returns a List object: 814 m = f (l, fn) 815 expect (prototype (m)).to_be "List" 816 - it creates a new List: 817 o = l 818 m = f (l, fn) 819 expect (l).to_equal (o) 820 expect (m).not_to_equal (o) 821 expect (l).to_equal (List {List {1, 2, 3}, List {4, 5}}) 822 - it maps a function over a List: 823 expect (f (l, fn)).to_equal (List {3, 2}) 824 - it works for an empty List: 825 l = List {} 826 expect (f (l, fn)).to_equal (List {}) 827 828 829- describe project: 830 - before: 831 l = List { 832 {first = false, second = true, third = true}, 833 {first = 1, second = 2, third = 3}, 834 {first = "1st", second = "2nd", third = "3rd"}, 835 } 836 837 - context as a module function: 838 - before: 839 f = M.project 840 841 - it writes a deprecation warning: 842 setdebug { deprecate = "nil" } 843 expect (capture (f, {"third", l})).to_contain_error "was deprecated" 844 setdebug { deprecate = false } 845 expect (capture (f, {"third", l})).not_to_contain_error "was deprecated" 846 847 - it returns a List object: 848 expect (prototype (f ("third", l))).to_be "List" 849 - it works with an empty List: 850 expect (f ("third", List {})).to_equal (List {}) 851 - it projects a List of fields from a List of tables: 852 expect (f ("third", l)).to_equal (List {true, 3, "3rd"}) 853 - it projects fields with a falsey value correctly: 854 expect (f ("first", l)).to_equal (List {false, 1, "1st"}) 855 856 - context as an object method: 857 - before: 858 f = l.project 859 860 - it writes a deprecation warning: 861 setdebug { deprecate = "nil" } 862 expect (capture (f, {l, "third"})).to_contain_error "was deprecated" 863 setdebug { deprecate = false } 864 expect (capture (f, {l, "third"})).not_to_contain_error "was deprecated" 865 866 - it returns a List object: 867 expect (prototype (f (l, "third"))).to_be "List" 868 - it works with an empty List: 869 expect (f (List {}, "third")).to_equal (List {}) 870 - it projects a List of fields from a List of tables: 871 expect (f (l, "third")).to_equal (List {true, 3, "3rd"}) 872 - it projects fields with a falsey value correctly: 873 expect (f (l, "first")).to_equal (List {false, 1, "1st"}) 874 875 876- describe relems: 877 - context as a module function: 878 - before: 879 f = M.relems 880 881 - it writes a deprecation warning: 882 setdebug { deprecate = "nil" } 883 expect (capture (f, {l})).to_contain_error "was deprecated" 884 setdebug { deprecate = false } 885 expect (capture (f, {l})).not_to_contain_error "was deprecated" 886 887 - it is a reverse iterator over List members: 888 t = {} 889 for e in f (l) do table.insert (t, e) end 890 expect (t).to_equal {"baz", "bar", "foo"} 891 - it works for an empty List: 892 t = {} 893 for e in f (List {}) do table.insert (t, e) end 894 expect (t).to_equal {} 895 896 - context as an object method: 897 - before: 898 f = l.relems 899 900 - it writes a deprecation warning: 901 setdebug { deprecate = "nil" } 902 expect (capture (f, {l})).to_contain_error "was deprecated" 903 setdebug { deprecate = false } 904 expect (capture (f, {l})).not_to_contain_error "was deprecated" 905 906 - it is a reverse iterator over List members: 907 t = {} 908 for e in l:relems () do table.insert (t, e) end 909 expect (t).to_equal {"baz", "bar", "foo"} 910 - it works for an empty List: 911 t, l = {}, List {} 912 for e in l:relems () do table.insert (t, e) end 913 expect (t).to_equal {} 914 915 916- describe rep: 917 - before: 918 l = List {"foo", "bar"} 919 920 f = M.rep 921 922 - context with bad arguments: 923 badargs.diagnose (f, "std.list.rep (List, int)") 924 925 - context as a module function: 926 - it returns a List object: 927 expect (prototype (f (l, 3))).to_be "List" 928 - it works for an empty List: 929 expect (f (List {}, 99)).to_equal (List {}) 930 - it repeats the contents of a List: 931 expect (f (l, 3)). 932 to_equal (List {"foo", "bar", "foo", "bar", "foo", "bar"}) 933 934 - context as an object method: 935 - before: 936 f = l.rep 937 938 - it returns a List object: 939 expect (prototype (f (l, 3))).to_be "List" 940 - it works for an empty List: 941 expect (f (List {}, 99)).to_equal (List {}) 942 - it repeats the contents of a List: 943 expect (f (l, 3)). 944 to_equal (List {"foo", "bar", "foo", "bar", "foo", "bar"}) 945 946 947- describe reverse: 948 - before: 949 l = List {"foo", "bar", "baz", "quux"} 950 951 - context as a module function: 952 - before: 953 f = M.reverse 954 955 - it writes a deprecation warning: 956 setdebug { deprecate = "nil" } 957 expect (capture (f, {{}})).to_contain_error "was deprecated" 958 setdebug { deprecate = false } 959 expect (capture (f, {{}})).not_to_contain_error "was deprecated" 960 961 - it returns a List object: 962 expect (prototype (f (l))).to_be "List" 963 - it works for an empty List: 964 l = List {} 965 expect (f (l)).to_equal (List {}) 966 - it makes a new reversed List: 967 m = l 968 expect (f (l)). 969 to_equal (List {"quux", "baz", "bar", "foo"}) 970 expect (l).to_equal (List {"foo", "bar", "baz", "quux"}) 971 expect (l).to_be (m) 972 973 - context as an object method: 974 - before: 975 f = l.reverse 976 977 - it writes a deprecation warning: 978 setdebug { deprecate = "nil" } 979 expect (capture (f, {l})).to_contain_error "was deprecated" 980 setdebug { deprecate = false } 981 expect (capture (f, {l})).not_to_contain_error "was deprecated" 982 983 - it returns a List object: 984 expect (prototype (f (l))).to_be "List" 985 - it works for an empty List: 986 expect (f (List {})).to_equal (List {}) 987 - it makes a new reversed List: 988 m = l 989 expect (f (l)). 990 to_equal (List {"quux", "baz", "bar", "foo"}) 991 expect (l).to_equal (List {"foo", "bar", "baz", "quux"}) 992 expect (l).to_be (m) 993 994 995- describe shape: 996 - before: 997 l = List {1, 2, 3, 4, 5, 6} 998 999 - context as a module function: 1000 - before: 1001 f = M.shape 1002 1003 - it writes a deprecation warning: 1004 setdebug { deprecate = "nil" } 1005 expect (capture (f, {{0}, l})).to_contain_error "was deprecated" 1006 setdebug { deprecate = false } 1007 expect (capture (f, {{0}, l})).not_to_contain_error "was deprecated" 1008 1009 - it returns a List object: 1010 expect (prototype (f ({2, 3}, l))).to_be "List" 1011 - it works for an empty List: 1012 expect (f ({0}, List {})).to_equal (List {}) 1013 - it returns the result in a new List object: 1014 expect (f ({2, 3}, l)).not_to_be (l) 1015 - it does not perturb the argument List: 1016 f ({2, 3}, l) 1017 expect (l).to_equal (List {1, 2, 3, 4, 5, 6}) 1018 - it reshapes a List according to given dimensions: 1019 expect (f ({2, 3}, l)). 1020 to_equal (List {List {1, 2, 3}, List {4, 5, 6}}) 1021 expect (f ({3, 2}, l)). 1022 to_equal (List {List {1, 2}, List {3, 4}, List {5, 6}}) 1023 - it treats 0-valued dimensions as an indefinite number: 1024 expect (f ({2, 0}, l)). 1025 to_equal (List {List {1, 2, 3}, List {4, 5, 6}}) 1026 expect (f ({0, 2}, l)). 1027 to_equal (List {List {1, 2}, List {3, 4}, List {5, 6}}) 1028 1029 - context as an object method: 1030 - before: 1031 f = l.shape 1032 1033 - it writes a deprecation warning: 1034 setdebug { deprecate = "nil" } 1035 expect (capture (f, {l, {0}})).to_contain_error "was deprecated" 1036 setdebug { deprecate = false } 1037 expect (capture (f, {l, {0}})).not_to_contain_error "was deprecated" 1038 1039 - it returns a List object: 1040 expect (prototype (f (l, {2, 3}))).to_be "List" 1041 - it works for an empty List: 1042 expect (f (List {}, {0})).to_equal (List {}) 1043 - it returns the result in a new List object: 1044 expect (f (l, {2, 3})):not_to_be (l) 1045 - it does not perturb the argument List: 1046 f (l, {2, 3}) 1047 expect (l).to_equal (List {1, 2, 3, 4, 5, 6}) 1048 - it reshapes a List according to given dimensions: 1049 expect (f (l, {2, 3})). 1050 to_equal (List {List {1, 2, 3}, List {4, 5, 6}}) 1051 expect (f (l, {3, 2})). 1052 to_equal (List {List {1, 2}, List {3, 4}, List {5, 6}}) 1053 - it treats 0-valued dimensions as an indefinite number: 1054 expect (f (l, {2, 0})). 1055 to_equal (List {List {1, 2, 3}, List {4, 5, 6}}) 1056 expect (f (l, {0, 2})). 1057 to_equal (List {List {1, 2}, List {3, 4}, List {5, 6}}) 1058 1059 1060- describe sub: 1061 - before: 1062 l = List {1, 2, 3, 4, 5, 6, 7} 1063 1064 f = M.sub 1065 1066 - context with bad arguments: 1067 badargs.diagnose (f, "std.list.sub (List, ?int, ?int)") 1068 1069 - context as a module function: 1070 - it returns a List object: 1071 expect (prototype (f (l, 1, 1))).to_be "List" 1072 - it makes a List from a subrange of another List: 1073 expect (f (l, 2, 5)).to_equal (List {2, 3, 4, 5}) 1074 - it truncates the result if 'to' argument is too large: 1075 expect (f (l, 5, 10)).to_equal (List {5, 6, 7}) 1076 - it defaults 'to' to the end of the List: 1077 expect (f (l, 5)).to_equal (List {5, 6, 7}) 1078 - it defaults 'from' to the beginning of the List: 1079 expect (f (l)).to_equal (l) 1080 - it returns an empty List when 'from' is greater than 'to': 1081 expect (f (l, 2, 1)).to_equal (List {}) 1082 - it counts from the end of the List for a negative 'from' argument: 1083 expect (f (l, -3)).to_equal (List {5, 6, 7}) 1084 - it counts from the end of the List for a negative 'to' argument: 1085 expect (f (l, -5, -2)).to_equal (List {3, 4, 5, 6}) 1086 1087 - context as an object method: 1088 - before: 1089 f = l.sub 1090 1091 - it returns a List object: 1092 expect (prototype (f (l, 1, 1))).to_be "List" 1093 - it makes a List from a subrange of another List: 1094 expect (f (l, 2, 5)).to_equal (List {2, 3, 4, 5}) 1095 - it truncates the result if 'to' argument is too large: 1096 expect (f (l, 5, 10)).to_equal (List {5, 6, 7}) 1097 - it defaults 'to' to the end of the List: 1098 expect (f (l, 5)).to_equal (List {5, 6, 7}) 1099 - it defaults 'from' to the beginning of the List: 1100 expect (f (l)).to_equal (l) 1101 - it returns an empty List when 'from' is greater than 'to': 1102 expect (f (l, 2, 1)).to_equal (List {}) 1103 - it counts from the end of the List for a negative 'from' argument: 1104 expect (f (l, -3)).to_equal (List {5, 6, 7}) 1105 - it counts from the end of the List for a negative 'to' argument: 1106 expect (f (l, -5, -2)).to_equal (List {3, 4, 5, 6}) 1107 1108 1109- describe tail: 1110 - before: 1111 l = List {1, 2, 3, 4, 5, 6, 7} 1112 1113 f = M.tail 1114 1115 - context with bad arguments: 1116 badargs.diagnose (f, "std.list.tail (List)") 1117 1118 - context as a module function: 1119 - it returns a List object: 1120 expect (prototype (f (l))).to_be "List" 1121 - it makes a new List with the first element removed: 1122 expect (f (l)).to_equal (List {2, 3, 4, 5, 6, 7}) 1123 - it works for an empty List: 1124 expect (f (List {})).to_equal (List {}) 1125 - it returns an empty List when passed a List with one element: 1126 expect (f (List {1})).to_equal (List {}) 1127 1128 - context as an object method: 1129 - before: 1130 f = l.tail 1131 1132 - it returns a List object: 1133 expect (prototype (f (l))).to_be "List" 1134 - it makes a new List with the first element removed: 1135 expect (f (l)).to_equal (List {2, 3, 4, 5, 6, 7}) 1136 - it works for an empty List: 1137 expect (f (List {})).to_equal (List {}) 1138 - it returns an empty List when passed a List with one element: 1139 expect (f (List {1})).to_equal (List {}) 1140 1141 1142- describe transpose: 1143 - before: 1144 l = List {List {1, 2}, List {3, 4}, List {5, 6}} 1145 1146 - context as a module function: 1147 - before: 1148 f = M.transpose 1149 1150 - it writes a deprecation warning: 1151 setdebug { deprecate = "nil" } 1152 expect (capture (f, {l})).to_contain_error "was deprecated" 1153 setdebug { deprecate = false } 1154 expect (capture (f, {l})).not_to_contain_error "was deprecated" 1155 1156 - it returns a List object: 1157 expect (prototype (f (l))).to_be "List" 1158 - it works for an empty List: 1159 expect (f (List {})).to_equal (List {}) 1160 - it returns the result in a new List object: 1161 expect (f (l)).not_to_be (l) 1162 - it does not perturb the argument List: 1163 m = f (l) 1164 expect (l).to_equal (List {List {1, 2}, List {3, 4}, List {5, 6}}) 1165 - it transposes rows and columns: 1166 expect (f (l)).to_equal (List {List {1, 3, 5}, List {2, 4, 6}}) 1167 1168 - context as an object method: 1169 - before: 1170 f = l.transpose 1171 1172 - it writes a deprecation warning: 1173 setdebug { deprecate = "nil" } 1174 expect (capture (f, {l})).to_contain_error "was deprecated" 1175 setdebug { deprecate = false } 1176 expect (capture (f, {l})).not_to_contain_error "was deprecated" 1177 1178 - it returns a List object: 1179 expect (prototype (f (l))).to_be "List" 1180 - it works for an empty List: 1181 expect (f (List {})).to_equal (List {}) 1182 - it returns the result in a new List object: 1183 expect (f (l)).not_to_be (l) 1184 - it does not perturb the argument List: 1185 m = f (l) 1186 expect (l).to_equal (List {List {1, 2}, List {3, 4}, List {5, 6}}) 1187 - it transposes rows and columns: 1188 expect (f (l)). 1189 to_equal (List {List {1, 3, 5}, List {2, 4, 6}}) 1190 1191 1192- describe zip_with: 1193 - before: 1194 l = List {List {1, 2}, List {3, 4}, List {5}} 1195 fn = function (...) return tonumber (table.concat {...}) end 1196 1197 - context as a module function: 1198 - before: 1199 f = M.zip_with 1200 1201 - it writes a deprecation warning: 1202 setdebug { deprecate = "nil" } 1203 expect (capture (f, {l, fn})).to_contain_error "was deprecated" 1204 setdebug { deprecate = false } 1205 expect (capture (f, {l, fn})).not_to_contain_error "was deprecated" 1206 1207 - it returns a List object: 1208 expect (prototype (f (l, fn))).to_be "List" 1209 - it works for an empty List: 1210 expect (f (List {}, fn)).to_equal (List {}) 1211 - it returns the result in a new List object: 1212 expect (f (l, fn)):not_to_be (l) 1213 - it does not perturb the argument List: 1214 m = f (l, fn) 1215 expect (l).to_equal (List {List {1, 2}, List {3, 4}, List {5}}) 1216 - it combines column entries with a function: 1217 expect (f (l, fn)).to_equal (List {135, 24}) 1218 1219 - context as an object method: 1220 - before: 1221 f = l.zip_with 1222 1223 - it writes a deprecation warning: 1224 setdebug { deprecate = "nil" } 1225 expect (capture (f, {l, fn})).to_contain_error "was deprecated" 1226 setdebug { deprecate = false } 1227 expect (capture (f, {l, fn})).not_to_contain_error "was deprecated" 1228 1229 - it returns a List object: 1230 expect (prototype (f (l, fn))).to_be "List" 1231 - it works for an empty List: 1232 expect (f (List {}, fn)).to_equal (List {}) 1233 - it returns the result in a new List object: 1234 expect (f (l, fn)):not_to_be (l) 1235 - it does not perturb the argument List: 1236 m = f (l, fn) 1237 expect (l).to_equal (List {List {1, 2}, List {3, 4}, List {5}}) 1238 - it combines column entries with a function: 1239 expect (f (l, fn)).to_equal (List {135, 24}) 1240