1 // Written in the D programming language. 2 3 /** 4 Functions that manipulate other functions. 5 6 This module provides functions for compile time function composition. These 7 functions are helpful when constructing predicates for the algorithms in 8 $(MREF std, algorithm) or $(MREF std, range). 9 10 $(SCRIPT inhibitQuickIndex = 1;) 11 $(DIVC quickindex, 12 $(BOOKTABLE , 13 $(TR $(TH Function Name) $(TH Description) 14 ) 15 $(TR $(TD $(LREF adjoin)) 16 $(TD Joins a couple of functions into one that executes the original 17 functions independently and returns a tuple with all the results. 18 )) 19 $(TR $(TD $(LREF compose), $(LREF pipe)) 20 $(TD Join a couple of functions into one that executes the original 21 functions one after the other, using one function's result for the next 22 function's argument. 23 )) 24 $(TR $(TD $(LREF lessThan), $(LREF greaterThan), $(LREF equalTo)) 25 $(TD Ready-made predicate functions to compare two values. 26 )) 27 $(TR $(TD $(LREF memoize)) 28 $(TD Creates a function that caches its result for fast re-evaluation. 29 )) 30 $(TR $(TD $(LREF not)) 31 $(TD Creates a function that negates another. 32 )) 33 $(TR $(TD $(LREF partial)) 34 $(TD Creates a function that binds the first argument of a given function 35 to a given value. 36 )) 37 $(TR $(TD $(LREF curry)) 38 $(TD Converts a multi-argument function into a series of single-argument 39 functions. f(x, y) == curry(f)(x)(y) 40 )) 41 $(TR $(TD $(LREF reverseArgs)) 42 $(TD Predicate that reverses the order of its arguments. 43 )) 44 $(TR $(TD $(LREF toDelegate)) 45 $(TD Converts a callable to a delegate. 46 )) 47 $(TR $(TD $(LREF unaryFun), $(LREF binaryFun)) 48 $(TD Create a unary or binary function from a string. Most often 49 used when defining algorithms on ranges. 50 )) 51 $(TR $(TD $(LREF bind)) 52 $(TD Passes the fields of a struct as arguments to a function. 53 )) 54 )) 55 56 Copyright: Copyright Andrei Alexandrescu 2008 - 2009. 57 License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0). 58 Authors: $(HTTP erdani.org, Andrei Alexandrescu) 59 Source: $(PHOBOSSRC std/functional.d) 60 */ 61 /* 62 Copyright Andrei Alexandrescu 2008 - 2009. 63 Distributed under the Boost Software License, Version 1.0. 64 (See accompanying file LICENSE_1_0.txt or copy at 65 http://www.boost.org/LICENSE_1_0.txt) 66 */ 67 module std.functional; 68 69 import std.meta : AliasSeq, Reverse; 70 import std.traits : isCallable, Parameters; 71 import std.conv : toCtString; 72 73 import std.internal.attributes : betterC; 74 75 public import core.lifetime : forward; 76 77 private template needOpCallAlias(alias fun) 78 { 79 /* Determine whether or not unaryFun and binaryFun need to alias to fun or 80 * fun.opCall. Basically, fun is a function object if fun(...) compiles. We 81 * want is(unaryFun!fun) (resp., is(binaryFun!fun)) to be true if fun is 82 * any function object. There are 4 possible cases: 83 * 84 * 1) fun is the type of a function object with static opCall; 85 * 2) fun is an instance of a function object with static opCall; 86 * 3) fun is the type of a function object with non-static opCall; 87 * 4) fun is an instance of a function object with non-static opCall. 88 * 89 * In case (1), is(unaryFun!fun) should compile, but does not if unaryFun 90 * aliases itself to fun, because typeof(fun) is an error when fun itself 91 * is a type. So it must be aliased to fun.opCall instead. All other cases 92 * should be aliased to fun directly. 93 */ 94 static if (is(typeof(fun.opCall) == function)) 95 { 96 enum needOpCallAlias = !is(typeof(fun)) && __traits(compiles, () { 97 return fun(Parameters!fun.init); 98 }); 99 } 100 else 101 enum needOpCallAlias = false; 102 } 103 104 /** 105 Transforms a `string` representing an expression into a unary 106 function. The `string` must either use symbol name `a` as 107 the parameter or provide the symbol via the `parmName` argument. 108 109 Params: 110 fun = a `string` or a callable 111 parmName = the name of the parameter if `fun` is a string. Defaults 112 to `"a"`. 113 Returns: 114 If `fun` is a `string`, a new single parameter function 115 116 If `fun` is not a `string`, an alias to `fun`. 117 */ 118 template unaryFun(alias fun, string parmName = "a") 119 { 120 static if (is(typeof(fun) : string)) 121 { 122 static if (!fun._ctfeMatchUnary(parmName)) 123 { 124 import std.algorithm, std.conv, std.exception, std.math, std.range, std.string; 125 import std.meta, std.traits, std.typecons; 126 } 127 auto unaryFun(ElementType)(auto ref ElementType __a) 128 { 129 mixin("alias " ~ parmName ~ " = __a ;"); 130 return mixin(fun); 131 } 132 } 133 else static if (needOpCallAlias!fun) 134 { 135 // https://issues.dlang.org/show_bug.cgi?id=9906 136 alias unaryFun = fun.opCall; 137 } 138 else 139 { 140 alias unaryFun = fun; 141 } 142 } 143 144 /// 145 @safe unittest 146 { 147 // Strings are compiled into functions: 148 alias isEven = unaryFun!("(a & 1) == 0"); 149 assert(isEven(2) && !isEven(1)); 150 } 151 152 @safe unittest 153 { 154 static int f1(int a) { return a + 1; } 155 static assert(is(typeof(unaryFun!(f1)(1)) == int)); 156 assert(unaryFun!(f1)(41) == 42); 157 int f2(int a) { return a + 1; } 158 static assert(is(typeof(unaryFun!(f2)(1)) == int)); 159 assert(unaryFun!(f2)(41) == 42); 160 assert(unaryFun!("a + 1")(41) == 42); 161 //assert(unaryFun!("return a + 1;")(41) == 42); 162 163 int num = 41; 164 assert(unaryFun!"a + 1"(num) == 42); 165 166 // https://issues.dlang.org/show_bug.cgi?id=9906 167 struct Seen 168 { 169 static bool opCall(int n) { return true; } 170 } 171 static assert(needOpCallAlias!Seen); 172 static assert(is(typeof(unaryFun!Seen(1)))); 173 assert(unaryFun!Seen(1)); 174 175 Seen s; 176 static assert(!needOpCallAlias!s); 177 static assert(is(typeof(unaryFun!s(1)))); 178 assert(unaryFun!s(1)); 179 180 struct FuncObj 181 { 182 bool opCall(int n) { return true; } 183 } 184 FuncObj fo; 185 static assert(!needOpCallAlias!fo); 186 static assert(is(typeof(unaryFun!fo))); 187 assert(unaryFun!fo(1)); 188 189 // Function object with non-static opCall can only be called with an 190 // instance, not with merely the type. 191 static assert(!is(typeof(unaryFun!FuncObj))); 192 } 193 194 /** 195 Transforms a `string` representing an expression into a binary function. The 196 `string` must either use symbol names `a` and `b` as the parameters or 197 provide the symbols via the `parm1Name` and `parm2Name` arguments. 198 199 Params: 200 fun = a `string` or a callable 201 parm1Name = the name of the first parameter if `fun` is a string. 202 Defaults to `"a"`. 203 parm2Name = the name of the second parameter if `fun` is a string. 204 Defaults to `"b"`. 205 Returns: 206 If `fun` is not a string, `binaryFun` aliases itself away to 207 `fun`. 208 */ 209 template binaryFun(alias fun, string parm1Name = "a", 210 string parm2Name = "b") 211 { 212 static if (is(typeof(fun) : string)) 213 { 214 static if (!fun._ctfeMatchBinary(parm1Name, parm2Name)) 215 { 216 import std.algorithm, std.conv, std.exception, std.math, std.range, std.string; 217 import std.meta, std.traits, std.typecons; 218 } 219 auto binaryFun(ElementType1, ElementType2) 220 (auto ref ElementType1 __a, auto ref ElementType2 __b) 221 { 222 mixin("alias "~parm1Name~" = __a ;"); 223 mixin("alias "~parm2Name~" = __b ;"); 224 return mixin(fun); 225 } 226 } 227 else static if (needOpCallAlias!fun) 228 { 229 // https://issues.dlang.org/show_bug.cgi?id=9906 230 alias binaryFun = fun.opCall; 231 } 232 else 233 { 234 alias binaryFun = fun; 235 } 236 } 237 238 /// 239 @safe unittest 240 { 241 alias less = binaryFun!("a < b"); 242 assert(less(1, 2) && !less(2, 1)); 243 alias greater = binaryFun!("a > b"); 244 assert(!greater("1", "2") && greater("2", "1")); 245 } 246 247 @safe unittest 248 { 249 static int f1(int a, string b) { return a + 1; } 250 static assert(is(typeof(binaryFun!(f1)(1, "2")) == int)); 251 assert(binaryFun!(f1)(41, "a") == 42); 252 string f2(int a, string b) { return b ~ "2"; } 253 static assert(is(typeof(binaryFun!(f2)(1, "1")) == string)); 254 assert(binaryFun!(f2)(1, "4") == "42"); 255 assert(binaryFun!("a + b")(41, 1) == 42); 256 //@@BUG 257 //assert(binaryFun!("return a + b;")(41, 1) == 42); 258 259 // https://issues.dlang.org/show_bug.cgi?id=9906 260 struct Seen 261 { 262 static bool opCall(int x, int y) { return true; } 263 } 264 static assert(is(typeof(binaryFun!Seen))); 265 assert(binaryFun!Seen(1,1)); 266 267 struct FuncObj 268 { 269 bool opCall(int x, int y) { return true; } 270 } 271 FuncObj fo; 272 static assert(!needOpCallAlias!fo); 273 static assert(is(typeof(binaryFun!fo))); 274 assert(unaryFun!fo(1,1)); 275 276 // Function object with non-static opCall can only be called with an 277 // instance, not with merely the type. 278 static assert(!is(typeof(binaryFun!FuncObj))); 279 } 280 281 // skip all ASCII chars except a .. z, A .. Z, 0 .. 9, '_' and '.'. 282 private uint _ctfeSkipOp(ref string op) 283 { 284 if (!__ctfe) assert(false); 285 import std.ascii : isASCII, isAlphaNum; 286 immutable oldLength = op.length; 287 while (op.length) 288 { 289 immutable front = op[0]; 290 if (front.isASCII() && !(front.isAlphaNum() || front == '_' || front == '.')) 291 op = op[1..$]; 292 else 293 break; 294 } 295 return oldLength != op.length; 296 } 297 298 // skip all digits 299 private uint _ctfeSkipInteger(ref string op) 300 { 301 if (!__ctfe) assert(false); 302 import std.ascii : isDigit; 303 immutable oldLength = op.length; 304 while (op.length) 305 { 306 immutable front = op[0]; 307 if (front.isDigit()) 308 op = op[1..$]; 309 else 310 break; 311 } 312 return oldLength != op.length; 313 } 314 315 // skip name 316 private uint _ctfeSkipName(ref string op, string name) 317 { 318 if (!__ctfe) assert(false); 319 if (op.length >= name.length && op[0 .. name.length] == name) 320 { 321 op = op[name.length..$]; 322 return 1; 323 } 324 return 0; 325 } 326 327 // returns 1 if `fun` is trivial unary function 328 private uint _ctfeMatchUnary(string fun, string name) 329 { 330 if (!__ctfe) assert(false); 331 fun._ctfeSkipOp(); 332 for (;;) 333 { 334 immutable h = fun._ctfeSkipName(name) + fun._ctfeSkipInteger(); 335 if (h == 0) 336 { 337 fun._ctfeSkipOp(); 338 break; 339 } 340 else if (h == 1) 341 { 342 if (!fun._ctfeSkipOp()) 343 break; 344 } 345 else 346 return 0; 347 } 348 return fun.length == 0; 349 } 350 351 @safe unittest 352 { 353 static assert(!_ctfeMatchUnary("sqrt(ё)", "ё")); 354 static assert(!_ctfeMatchUnary("ё.sqrt", "ё")); 355 static assert(!_ctfeMatchUnary(".ё+ё", "ё")); 356 static assert(!_ctfeMatchUnary("_ё+ё", "ё")); 357 static assert(!_ctfeMatchUnary("ёё", "ё")); 358 static assert(_ctfeMatchUnary("a+a", "a")); 359 static assert(_ctfeMatchUnary("a + 10", "a")); 360 static assert(_ctfeMatchUnary("4 == a", "a")); 361 static assert(_ctfeMatchUnary("2 == a", "a")); 362 static assert(_ctfeMatchUnary("1 != a", "a")); 363 static assert(_ctfeMatchUnary("a != 4", "a")); 364 static assert(_ctfeMatchUnary("a< 1", "a")); 365 static assert(_ctfeMatchUnary("434 < a", "a")); 366 static assert(_ctfeMatchUnary("132 > a", "a")); 367 static assert(_ctfeMatchUnary("123 >a", "a")); 368 static assert(_ctfeMatchUnary("a>82", "a")); 369 static assert(_ctfeMatchUnary("ё>82", "ё")); 370 static assert(_ctfeMatchUnary("ё[ё(ё)]", "ё")); 371 static assert(_ctfeMatchUnary("ё[21]", "ё")); 372 } 373 374 // returns 1 if `fun` is trivial binary function 375 private uint _ctfeMatchBinary(string fun, string name1, string name2) 376 { 377 if (!__ctfe) assert(false); 378 fun._ctfeSkipOp(); 379 for (;;) 380 { 381 immutable h = fun._ctfeSkipName(name1) + fun._ctfeSkipName(name2) + fun._ctfeSkipInteger(); 382 if (h == 0) 383 { 384 fun._ctfeSkipOp(); 385 break; 386 } 387 else if (h == 1) 388 { 389 if (!fun._ctfeSkipOp()) 390 break; 391 } 392 else 393 return 0; 394 } 395 return fun.length == 0; 396 } 397 398 @safe unittest 399 { 400 401 static assert(!_ctfeMatchBinary("sqrt(ё)", "ё", "b")); 402 static assert(!_ctfeMatchBinary("ё.sqrt", "ё", "b")); 403 static assert(!_ctfeMatchBinary(".ё+ё", "ё", "b")); 404 static assert(!_ctfeMatchBinary("_ё+ё", "ё", "b")); 405 static assert(!_ctfeMatchBinary("ёё", "ё", "b")); 406 static assert(_ctfeMatchBinary("a+a", "a", "b")); 407 static assert(_ctfeMatchBinary("a + 10", "a", "b")); 408 static assert(_ctfeMatchBinary("4 == a", "a", "b")); 409 static assert(_ctfeMatchBinary("2 == a", "a", "b")); 410 static assert(_ctfeMatchBinary("1 != a", "a", "b")); 411 static assert(_ctfeMatchBinary("a != 4", "a", "b")); 412 static assert(_ctfeMatchBinary("a< 1", "a", "b")); 413 static assert(_ctfeMatchBinary("434 < a", "a", "b")); 414 static assert(_ctfeMatchBinary("132 > a", "a", "b")); 415 static assert(_ctfeMatchBinary("123 >a", "a", "b")); 416 static assert(_ctfeMatchBinary("a>82", "a", "b")); 417 static assert(_ctfeMatchBinary("ё>82", "ё", "q")); 418 static assert(_ctfeMatchBinary("ё[ё(10)]", "ё", "q")); 419 static assert(_ctfeMatchBinary("ё[21]", "ё", "q")); 420 421 static assert(!_ctfeMatchBinary("sqrt(ё)+b", "b", "ё")); 422 static assert(!_ctfeMatchBinary("ё.sqrt-b", "b", "ё")); 423 static assert(!_ctfeMatchBinary(".ё+b", "b", "ё")); 424 static assert(!_ctfeMatchBinary("_b+ё", "b", "ё")); 425 static assert(!_ctfeMatchBinary("ba", "b", "a")); 426 static assert(_ctfeMatchBinary("a+b", "b", "a")); 427 static assert(_ctfeMatchBinary("a + b", "b", "a")); 428 static assert(_ctfeMatchBinary("b == a", "b", "a")); 429 static assert(_ctfeMatchBinary("b == a", "b", "a")); 430 static assert(_ctfeMatchBinary("b != a", "b", "a")); 431 static assert(_ctfeMatchBinary("a != b", "b", "a")); 432 static assert(_ctfeMatchBinary("a< b", "b", "a")); 433 static assert(_ctfeMatchBinary("b < a", "b", "a")); 434 static assert(_ctfeMatchBinary("b > a", "b", "a")); 435 static assert(_ctfeMatchBinary("b >a", "b", "a")); 436 static assert(_ctfeMatchBinary("a>b", "b", "a")); 437 static assert(_ctfeMatchBinary("ё>b", "b", "ё")); 438 static assert(_ctfeMatchBinary("b[ё(-1)]", "b", "ё")); 439 static assert(_ctfeMatchBinary("ё[-21]", "b", "ё")); 440 } 441 442 //undocumented 443 template safeOp(string S) 444 if (S=="<"||S==">"||S=="<="||S==">="||S=="=="||S=="!=") 445 { 446 import std.traits : isIntegral; 447 private bool unsafeOp(ElementType1, ElementType2)(ElementType1 a, ElementType2 b) pure 448 if (isIntegral!ElementType1 && isIntegral!ElementType2) 449 { 450 import std.traits : CommonType; 451 alias T = CommonType!(ElementType1, ElementType2); 452 return mixin("cast(T)a "~S~" cast(T) b"); 453 } 454 455 bool safeOp(T0, T1)(auto ref T0 a, auto ref T1 b) 456 { 457 import std.traits : mostNegative; 458 static if (isIntegral!T0 && isIntegral!T1 && 459 (mostNegative!T0 < 0) != (mostNegative!T1 < 0)) 460 { 461 static if (S == "<=" || S == "<") 462 { 463 static if (mostNegative!T0 < 0) 464 immutable result = a < 0 || unsafeOp(a, b); 465 else 466 immutable result = b >= 0 && unsafeOp(a, b); 467 } 468 else 469 { 470 static if (mostNegative!T0 < 0) 471 immutable result = a >= 0 && unsafeOp(a, b); 472 else 473 immutable result = b < 0 || unsafeOp(a, b); 474 } 475 } 476 else 477 { 478 static assert(is(typeof(mixin("a "~S~" b"))), 479 "Invalid arguments: Cannot compare types " ~ T0.stringof ~ " and " ~ T1.stringof ~ "."); 480 481 immutable result = mixin("a "~S~" b"); 482 } 483 return result; 484 } 485 } 486 487 @safe unittest //check user defined types 488 { 489 import std.algorithm.comparison : equal; 490 struct Foo 491 { 492 int a; 493 auto opEquals(Foo foo) 494 { 495 return a == foo.a; 496 } 497 } 498 assert(safeOp!"!="(Foo(1), Foo(2))); 499 } 500 501 /** 502 Predicate that returns $(D_PARAM a < b). 503 Correctly compares signed and unsigned integers, ie. -1 < 2U. 504 */ 505 alias lessThan = safeOp!"<"; 506 507 /// 508 pure @safe @nogc nothrow unittest 509 { 510 assert(lessThan(2, 3)); 511 assert(lessThan(2U, 3U)); 512 assert(lessThan(2, 3.0)); 513 assert(lessThan(-2, 3U)); 514 assert(lessThan(2, 3U)); 515 assert(!lessThan(3U, -2)); 516 assert(!lessThan(3U, 2)); 517 assert(!lessThan(0, 0)); 518 assert(!lessThan(0U, 0)); 519 assert(!lessThan(0, 0U)); 520 } 521 522 /** 523 Predicate that returns $(D_PARAM a > b). 524 Correctly compares signed and unsigned integers, ie. 2U > -1. 525 */ 526 alias greaterThan = safeOp!">"; 527 528 /// 529 @safe unittest 530 { 531 assert(!greaterThan(2, 3)); 532 assert(!greaterThan(2U, 3U)); 533 assert(!greaterThan(2, 3.0)); 534 assert(!greaterThan(-2, 3U)); 535 assert(!greaterThan(2, 3U)); 536 assert(greaterThan(3U, -2)); 537 assert(greaterThan(3U, 2)); 538 assert(!greaterThan(0, 0)); 539 assert(!greaterThan(0U, 0)); 540 assert(!greaterThan(0, 0U)); 541 } 542 543 /** 544 Predicate that returns $(D_PARAM a == b). 545 Correctly compares signed and unsigned integers, ie. !(-1 == ~0U). 546 */ 547 alias equalTo = safeOp!"=="; 548 549 /// 550 @safe unittest 551 { 552 assert(equalTo(0U, 0)); 553 assert(equalTo(0, 0U)); 554 assert(!equalTo(-1, ~0U)); 555 } 556 /** 557 N-ary predicate that reverses the order of arguments, e.g., given 558 $(D pred(a, b, c)), returns $(D pred(c, b, a)). 559 560 Params: 561 pred = A callable 562 Returns: 563 A function which calls `pred` after reversing the given parameters 564 */ 565 template reverseArgs(alias pred) 566 { 567 auto reverseArgs(Args...)(auto ref Args args) 568 if (is(typeof(pred(Reverse!args)))) 569 { 570 return pred(Reverse!args); 571 } 572 } 573 574 /// 575 @safe unittest 576 { 577 alias gt = reverseArgs!(binaryFun!("a < b")); 578 assert(gt(2, 1) && !gt(1, 1)); 579 } 580 581 /// 582 @safe unittest 583 { 584 int x = 42; 585 bool xyz(int a, int b) { return a * x < b / x; } 586 auto foo = &xyz; 587 foo(4, 5); 588 alias zyx = reverseArgs!(foo); 589 assert(zyx(5, 4) == foo(4, 5)); 590 } 591 592 /// 593 @safe unittest 594 { 595 alias gt = reverseArgs!(binaryFun!("a < b")); 596 assert(gt(2, 1) && !gt(1, 1)); 597 int x = 42; 598 bool xyz(int a, int b) { return a * x < b / x; } 599 auto foo = &xyz; 600 foo(4, 5); 601 alias zyx = reverseArgs!(foo); 602 assert(zyx(5, 4) == foo(4, 5)); 603 } 604 605 /// 606 @safe unittest 607 { 608 int abc(int a, int b, int c) { return a * b + c; } 609 alias cba = reverseArgs!abc; 610 assert(abc(91, 17, 32) == cba(32, 17, 91)); 611 } 612 613 /// 614 @safe unittest 615 { 616 int a(int a) { return a * 2; } 617 alias _a = reverseArgs!a; 618 assert(a(2) == _a(2)); 619 } 620 621 /// 622 @safe unittest 623 { 624 int b() { return 4; } 625 alias _b = reverseArgs!b; 626 assert(b() == _b()); 627 } 628 629 /** 630 Negates predicate `pred`. 631 632 Params: 633 pred = A string or a callable 634 Returns: 635 A function which calls `pred` and returns the logical negation of its 636 return value. 637 */ 638 template not(alias pred) 639 { 640 auto not(T...)(auto ref T args) 641 { 642 static if (is(typeof(!pred(args)))) 643 return !pred(args); 644 else static if (T.length == 1) 645 return !unaryFun!pred(args); 646 else static if (T.length == 2) 647 return !binaryFun!pred(args); 648 else 649 static assert(0); 650 } 651 } 652 653 /// 654 @safe unittest 655 { 656 import std.algorithm.searching : find; 657 import std.uni : isWhite; 658 string a = " Hello, world!"; 659 assert(find!(not!isWhite)(a) == "Hello, world!"); 660 } 661 662 @safe unittest 663 { 664 assert(not!"a != 5"(5)); 665 assert(not!"a != b"(5, 5)); 666 667 assert(not!(() => false)()); 668 assert(not!(a => a != 5)(5)); 669 assert(not!((a, b) => a != b)(5, 5)); 670 assert(not!((a, b, c) => a * b * c != 125 )(5, 5, 5)); 671 } 672 673 /** 674 $(LINK2 http://en.wikipedia.org/wiki/Partial_application, Partially 675 applies) $(D_PARAM fun) by tying its first argument to $(D_PARAM arg). 676 677 Params: 678 fun = A callable 679 arg = The first argument to apply to `fun` 680 Returns: 681 A new function which calls `fun` with `arg` plus the passed parameters. 682 */ 683 template partial(alias fun, alias arg) 684 { 685 import std.traits : isCallable; 686 // Check whether fun is a user defined type which implements opCall or a template. 687 // As opCall itself can be templated, std.traits.isCallable does not work here. 688 enum isSomeFunctor = (is(typeof(fun) == struct) || is(typeof(fun) == class)) && __traits(hasMember, fun, "opCall"); 689 static if (isSomeFunctor || __traits(isTemplate, fun)) 690 { 691 auto partial(Ts...)(Ts args2) 692 { 693 static if (is(typeof(fun(arg, args2)))) 694 { 695 return fun(arg, args2); 696 } 697 else 698 { 699 static string errormsg() 700 { 701 string msg = "Cannot call '" ~ fun.stringof ~ "' with arguments " ~ 702 "(" ~ arg.stringof; 703 foreach (T; Ts) 704 msg ~= ", " ~ T.stringof; 705 msg ~= ")."; 706 return msg; 707 } 708 static assert(0, errormsg()); 709 } 710 } 711 } 712 else static if (!isCallable!fun) 713 { 714 static assert(false, "Cannot apply partial to a non-callable '" ~ fun.stringof ~ "'."); 715 } 716 else 717 { 718 import std.meta : Filter; 719 720 static if (__traits(compiles, __traits(getOverloads, 721 __traits(parent, fun), __traits(identifier, fun)))) 722 alias overloads = __traits(getOverloads, __traits(parent, fun), 723 __traits(identifier, fun)); 724 else 725 alias overloads = AliasSeq!(fun); 726 727 enum isCallableWithArg(alias fun) = Parameters!fun.length > 0 && 728 is(typeof(arg) : Parameters!fun[0]); 729 alias candidates = Filter!(isCallableWithArg, overloads); 730 731 static if (overloads.length == 1 && Parameters!fun.length == 0) 732 { 733 static assert(0, "Cannot partially apply '" ~ fun.stringof ~ "'." ~ 734 "'" ~ fun.stringof ~ "' has 0 arguments."); 735 } 736 else static if (candidates.length == 0) 737 { 738 import std.meta : NoDuplicates, staticMap; 739 740 enum hasParameters(alias fun) = Parameters!fun.length > 0; 741 alias firstParameter(alias fun) = Parameters!fun[0]; 742 alias firstParameters = NoDuplicates!( 743 staticMap!(firstParameter, Filter!(hasParameters, overloads))); 744 745 string errorMsg() 746 { 747 string msg = "Argument mismatch for '" ~ fun.stringof ~ 748 "': expected " ~ firstParameters[0].stringof; 749 static foreach (firstParam; firstParameters[1 .. $]) 750 msg ~= " or " ~ firstParam.stringof; 751 msg ~= ", but got " ~ typeof(arg).stringof ~ "."; 752 753 return msg; 754 } 755 static assert(0, errorMsg()); 756 } 757 else 758 { 759 import std.traits : ReturnType; 760 static foreach (candidate; candidates) 761 ReturnType!candidate partial(Parameters!candidate[1..$] args2) 762 { 763 return candidate(arg, args2); 764 } 765 } 766 } 767 } 768 769 /// 770 @safe unittest 771 { 772 int fun(int a, int b) { return a + b; } 773 alias fun5 = partial!(fun, 5); 774 assert(fun5(6) == 11); 775 // Note that in most cases you'd use an alias instead of a value 776 // assignment. Using an alias allows you to partially evaluate template 777 // functions without committing to a particular type of the function. 778 } 779 780 // https://issues.dlang.org/show_bug.cgi?id=21457 781 /// 782 @safe unittest 783 { 784 // Overloads are resolved when the partially applied function is called 785 // with the remaining arguments. 786 struct S 787 { 788 static char fun(int i, string s) { return s[i]; } 789 static int fun(int a, int b) { return a * b; } 790 } 791 alias fun3 = partial!(S.fun, 3); 792 assert(fun3("hello") == 'l'); 793 assert(fun3(10) == 30); 794 } 795 796 // tests for partially evaluating callables 797 @safe unittest 798 { 799 static int f1(int a, int b) { return a + b; } 800 assert(partial!(f1, 5)(6) == 11); 801 802 int f2(int a, int b) { return a + b; } 803 int x = 5; 804 assert(partial!(f2, x)(6) == 11); 805 x = 7; 806 assert(partial!(f2, x)(6) == 13); 807 static assert(partial!(f2, 5)(6) == 11); 808 809 auto dg = &f2; 810 auto f3 = &partial!(dg, x); 811 assert(f3(6) == 13); 812 813 static int funOneArg(int a) { return a; } 814 assert(partial!(funOneArg, 1)() == 1); 815 816 static int funThreeArgs(int a, int b, int c) { return a + b + c; } 817 alias funThreeArgs1 = partial!(funThreeArgs, 1); 818 assert(funThreeArgs1(2, 3) == 6); 819 static assert(!is(typeof(funThreeArgs1(2)))); 820 821 enum xe = 5; 822 alias fe = partial!(f2, xe); 823 static assert(fe(6) == 11); 824 } 825 826 // tests for partially evaluating templated/overloaded callables 827 @safe unittest 828 { 829 static auto add(A, B)(A x, B y) 830 { 831 return x + y; 832 } 833 834 alias add5 = partial!(add, 5); 835 assert(add5(6) == 11); 836 static assert(!is(typeof(add5()))); 837 static assert(!is(typeof(add5(6, 7)))); 838 839 // taking address of templated partial evaluation needs explicit type 840 auto dg = &add5!(int); 841 assert(dg(6) == 11); 842 843 int x = 5; 844 alias addX = partial!(add, x); 845 assert(addX(6) == 11); 846 847 static struct Callable 848 { 849 static string opCall(string a, string b) { return a ~ b; } 850 int opCall(int a, int b) { return a * b; } 851 double opCall(double a, double b) { return a + b; } 852 } 853 Callable callable; 854 assert(partial!(Callable, "5")("6") == "56"); 855 assert(partial!(callable, 5)(6) == 30); 856 assert(partial!(callable, 7.0)(3.0) == 7.0 + 3.0); 857 858 static struct TCallable 859 { 860 auto opCall(A, B)(A a, B b) 861 { 862 return a + b; 863 } 864 } 865 TCallable tcallable; 866 assert(partial!(tcallable, 5)(6) == 11); 867 static assert(!is(typeof(partial!(tcallable, "5")(6)))); 868 869 static struct NonCallable{} 870 static assert(!__traits(compiles, partial!(NonCallable, 5)), "Partial should not work on non-callable structs."); 871 static assert(!__traits(compiles, partial!(NonCallable.init, 5)), 872 "Partial should not work on instances of non-callable structs."); 873 874 static A funOneArg(A)(A a) { return a; } 875 alias funOneArg1 = partial!(funOneArg, 1); 876 assert(funOneArg1() == 1); 877 878 static auto funThreeArgs(A, B, C)(A a, B b, C c) { return a + b + c; } 879 alias funThreeArgs1 = partial!(funThreeArgs, 1); 880 assert(funThreeArgs1(2, 3) == 6); 881 static assert(!is(typeof(funThreeArgs1(1)))); 882 883 auto dg2 = &funOneArg1!(); 884 assert(dg2() == 1); 885 } 886 887 // Fix https://issues.dlang.org/show_bug.cgi?id=15732 888 @safe unittest 889 { 890 // Test whether it works with functions. 891 auto partialFunction(){ 892 auto fullFunction = (float a, float b, float c) => a + b / c; 893 alias apply1 = partial!(fullFunction, 1); 894 return &apply1; 895 } 896 auto result = partialFunction()(2, 4); 897 assert(result == 1.5f); 898 899 // And with delegates. 900 auto partialDelegate(float c){ 901 auto fullDelegate = (float a, float b) => a + b / c; 902 alias apply1 = partial!(fullDelegate, 1); 903 return &apply1; 904 } 905 auto result2 = partialDelegate(4)(2); 906 assert(result2 == 1.5f); 907 } 908 909 /** 910 Takes a function of (potentially) many arguments, and returns a function taking 911 one argument and returns a callable taking the rest. f(x, y) == curry(f)(x)(y) 912 913 Params: 914 F = a function taking at least one argument 915 t = a callable object whose opCall takes at least 1 object 916 Returns: 917 A single parameter callable object 918 */ 919 template curry(alias F) 920 if (isCallable!F && Parameters!F.length) 921 { 922 //inspired from the implementation from Artur Skawina here: 923 //https://forum.dlang.org/post/mailman.1626.1340110492.24740.digitalmars-d@puremagic.com 924 //This implementation stores a copy of all filled in arguments with each curried result 925 //this way, the curried functions are independent and don't share any references 926 //eg: auto fc = curry!f; auto fc1 = fc(1); auto fc2 = fc(2); fc1(3) != fc2(3) 927 struct CurryImpl(size_t N) 928 { 929 alias FParams = Parameters!F; 930 FParams[0 .. N] storedArguments; 931 static if (N > 0) 932 { 933 this(U : FParams[N - 1])(ref CurryImpl!(N - 1) prev, ref U arg) 934 { 935 storedArguments[0 .. N - 1] = prev.storedArguments[]; 936 storedArguments[N-1] = arg; 937 } 938 } 939 940 auto opCall(U : FParams[N])(auto ref U arg) return scope 941 { 942 static if (N == FParams.length - 1) 943 { 944 return F(storedArguments, arg); 945 } 946 else 947 { 948 return CurryImpl!(N + 1)(this, arg); 949 } 950 } 951 } 952 953 auto curry() 954 { 955 CurryImpl!0 res; 956 return res; // return CurryImpl!0.init segfaults for delegates on Windows 957 } 958 } 959 960 /// 961 pure @safe @nogc nothrow unittest 962 { 963 int f(int x, int y, int z) 964 { 965 return x + y + z; 966 } 967 auto cf = curry!f; 968 auto cf1 = cf(1); 969 auto cf2 = cf(2); 970 971 assert(cf1(2)(3) == f(1, 2, 3)); 972 assert(cf2(2)(3) == f(2, 2, 3)); 973 } 974 975 ///ditto 976 auto curry(T)(T t) 977 if (isCallable!T && Parameters!T.length) 978 { 979 static auto fun(ref T inst, ref Parameters!T args) 980 { 981 return inst(args); 982 } 983 984 return curry!fun()(t); 985 } 986 987 /// 988 pure @safe @nogc nothrow unittest 989 { 990 //works with callable structs too 991 struct S 992 { 993 int w; 994 int opCall(int x, int y, int z) 995 { 996 return w + x + y + z; 997 } 998 } 999 1000 S s; 1001 s.w = 5; 1002 1003 auto cs = curry(s); 1004 auto cs1 = cs(1); 1005 auto cs2 = cs(2); 1006 1007 assert(cs1(2)(3) == s(1, 2, 3)); 1008 assert(cs1(2)(3) == (1 + 2 + 3 + 5)); 1009 assert(cs2(2)(3) ==s(2, 2, 3)); 1010 } 1011 1012 1013 @safe pure @nogc nothrow unittest 1014 { 1015 //currying a single argument function does nothing 1016 int pork(int a){ return a*2;} 1017 auto curryPork = curry!pork; 1018 assert(curryPork(0) == pork(0)); 1019 assert(curryPork(1) == pork(1)); 1020 assert(curryPork(-1) == pork(-1)); 1021 assert(curryPork(1000) == pork(1000)); 1022 1023 //test 2 argument function 1024 double mixedVeggies(double a, int b, bool) 1025 { 1026 return a + b; 1027 } 1028 1029 auto mixedCurry = curry!mixedVeggies; 1030 assert(mixedCurry(10)(20)(false) == mixedVeggies(10, 20, false)); 1031 assert(mixedCurry(100)(200)(true) == mixedVeggies(100, 200, true)); 1032 1033 // struct with opCall 1034 struct S 1035 { 1036 double opCall(int x, double y, short z) const pure nothrow @nogc 1037 { 1038 return x*y*z; 1039 } 1040 } 1041 1042 S s; 1043 auto curriedStruct = curry(s); 1044 assert(curriedStruct(1)(2)(short(3)) == s(1, 2, short(3))); 1045 assert(curriedStruct(300)(20)(short(10)) == s(300, 20, short(10))); 1046 } 1047 1048 pure @safe nothrow unittest 1049 { 1050 auto cfl = curry!((double a, int b) => a + b); 1051 assert(cfl(13)(2) == 15); 1052 1053 int c = 42; 1054 auto cdg = curry!((double a, int b) => a + b + c); 1055 assert(cdg(13)(2) == 57); 1056 1057 static class C 1058 { 1059 int opCall(int mult, int add) pure @safe nothrow @nogc scope 1060 { 1061 return mult * 42 + add; 1062 } 1063 } 1064 1065 scope C ci = new C(); 1066 scope cc = curry(ci); 1067 assert(cc(2)(4) == ci(2, 4)); 1068 } 1069 1070 // Disallows callables without parameters 1071 pure @safe @nogc nothrow unittest 1072 { 1073 static void noargs() {} 1074 static assert(!__traits(compiles, curry!noargs())); 1075 1076 static struct NoArgs 1077 { 1078 void opCall() {} 1079 } 1080 1081 static assert(!__traits(compiles, curry(NoArgs.init))); 1082 } 1083 1084 private template Iota(size_t n) 1085 { 1086 static if (n == 0) 1087 alias Iota = AliasSeq!(); 1088 else 1089 alias Iota = AliasSeq!(Iota!(n - 1), n - 1); 1090 } 1091 1092 /** 1093 Takes multiple functions and adjoins them together. 1094 1095 Params: 1096 F = the call-able(s) to adjoin 1097 Returns: 1098 A new function which returns a $(REF Tuple, std,typecons). Each of the 1099 elements of the tuple will be the return values of `F`. 1100 1101 Note: In the special case where only a single function is provided 1102 ($(D F.length == 1)), adjoin simply aliases to the single passed function 1103 (`F[0]`). 1104 */ 1105 template adjoin(F...) 1106 if (F.length >= 1) 1107 { 1108 static if (F.length == 1) 1109 alias adjoin = F[0]; 1110 else 1111 auto adjoin(V...)(auto ref V a) 1112 { 1113 import std.typecons : tuple; 1114 import std.meta : staticMap; 1115 1116 auto resultElement(size_t i)() 1117 { 1118 return F[i](a); 1119 } 1120 1121 return tuple(staticMap!(resultElement, Iota!(F.length))); 1122 } 1123 } 1124 1125 /// 1126 @safe unittest 1127 { 1128 import std.typecons : Tuple; 1129 static bool f1(int a) { return a != 0; } 1130 static int f2(int a) { return a / 2; } 1131 auto x = adjoin!(f1, f2)(5); 1132 assert(is(typeof(x) == Tuple!(bool, int))); 1133 assert(x[0] == true && x[1] == 2); 1134 } 1135 1136 @safe unittest 1137 { 1138 import std.typecons : Tuple; 1139 static bool F1(int a) { return a != 0; } 1140 auto x1 = adjoin!(F1)(5); 1141 static int F2(int a) { return a / 2; } 1142 auto x2 = adjoin!(F1, F2)(5); 1143 assert(is(typeof(x2) == Tuple!(bool, int))); 1144 assert(x2[0] && x2[1] == 2); 1145 auto x3 = adjoin!(F1, F2, F2)(5); 1146 assert(is(typeof(x3) == Tuple!(bool, int, int))); 1147 assert(x3[0] && x3[1] == 2 && x3[2] == 2); 1148 1149 bool F4(int a) { return a != x1; } 1150 alias eff4 = adjoin!(F4); 1151 static struct S 1152 { 1153 bool delegate(int) @safe store; 1154 int fun() { return 42 + store(5); } 1155 } 1156 S s; 1157 s.store = (int a) { return eff4(a); }; 1158 auto x4 = s.fun(); 1159 assert(x4 == 43); 1160 } 1161 1162 @safe unittest 1163 { 1164 import std.meta : staticMap; 1165 import std.typecons : Tuple, tuple; 1166 alias funs = staticMap!(unaryFun, "a", "a * 2", "a * 3", "a * a", "-a"); 1167 alias afun = adjoin!funs; 1168 assert(afun(5) == tuple(5, 10, 15, 25, -5)); 1169 1170 static class C{} 1171 alias IC = immutable(C); 1172 IC foo(){return typeof(return).init;} 1173 Tuple!(IC, IC, IC, IC) ret1 = adjoin!(foo, foo, foo, foo)(); 1174 1175 static struct S{int* p;} 1176 alias IS = immutable(S); 1177 IS bar(){return typeof(return).init;} 1178 enum Tuple!(IS, IS, IS, IS) ret2 = adjoin!(bar, bar, bar, bar)(); 1179 } 1180 1181 // https://issues.dlang.org/show_bug.cgi?id=21347 1182 @safe @betterC unittest 1183 { 1184 alias f = (int n) => n + 1; 1185 alias g = (int n) => n + 2; 1186 alias h = (int n) => n + 3; 1187 alias i = (int n) => n + 4; 1188 1189 auto result = adjoin!(f, g, h, i)(0); 1190 1191 assert(result[0] == 1); 1192 assert(result[1] == 2); 1193 assert(result[2] == 3); 1194 assert(result[3] == 4); 1195 } 1196 1197 /** 1198 Composes passed-in functions $(D fun[0], fun[1], ...). 1199 1200 Params: 1201 fun = the call-able(s) or `string`(s) to compose into one function 1202 Returns: 1203 A new function `f(x)` that in turn returns `fun[0](fun[1](...(x)))...`. 1204 1205 See_Also: $(LREF pipe) 1206 */ 1207 template compose(fun...) 1208 if (fun.length > 0) 1209 { 1210 static if (fun.length == 1) 1211 { 1212 alias compose = unaryFun!(fun[0]); 1213 } 1214 else 1215 { 1216 alias fun0 = unaryFun!(fun[0]); 1217 alias rest = compose!(fun[1 .. $]); 1218 1219 auto compose(Args...)(Args args) 1220 { 1221 return fun0(rest(args)); 1222 } 1223 } 1224 } 1225 1226 /// 1227 @safe unittest 1228 { 1229 import std.algorithm.comparison : equal; 1230 import std.algorithm.iteration : map; 1231 import std.array : split; 1232 import std.conv : to; 1233 1234 // First split a string in whitespace-separated tokens and then 1235 // convert each token into an integer 1236 assert(compose!(map!(to!(int)), split)("1 2 3").equal([1, 2, 3])); 1237 } 1238 1239 // https://issues.dlang.org/show_bug.cgi?id=6484 1240 @safe unittest 1241 { 1242 int f(int a) { return a; } 1243 int g(int a) { return a; } 1244 int h(int a,int b,int c) { return a * b * c; } 1245 1246 alias F = compose!(f,g,h); 1247 assert(F(1,2,3) == f(g(h(1,2,3)))); 1248 } 1249 1250 /** 1251 Pipes functions in sequence. Offers the same functionality as $(D 1252 compose), but with functions specified in reverse order. This may 1253 lead to more readable code in some situation because the order of 1254 execution is the same as lexical order. 1255 1256 Params: 1257 fun = the call-able(s) or `string`(s) to compose into one function 1258 Returns: 1259 A new function `f(x)` that in turn returns `fun[$-1](...fun[1](fun[0](x)))...`. 1260 1261 Example: 1262 1263 ---- 1264 // Read an entire text file, split the resulting string in 1265 // whitespace-separated tokens, and then convert each token into an 1266 // integer 1267 int[] a = pipe!(readText, split, map!(to!(int)))("file.txt"); 1268 ---- 1269 1270 See_Also: $(LREF compose) 1271 */ 1272 alias pipe(fun...) = compose!(Reverse!(fun)); 1273 1274 /// 1275 @safe unittest 1276 { 1277 import std.conv : to; 1278 string foo(int a) { return to!(string)(a); } 1279 int bar(string a) { return to!(int)(a) + 1; } 1280 double baz(int a) { return a + 0.5; } 1281 assert(compose!(baz, bar, foo)(1) == 2.5); 1282 assert(pipe!(foo, bar, baz)(1) == 2.5); 1283 1284 assert(compose!(baz, `to!(int)(a) + 1`, foo)(1) == 2.5); 1285 assert(compose!(baz, bar)("1"[]) == 2.5); 1286 1287 assert(compose!(baz, bar)("1") == 2.5); 1288 1289 assert(compose!(`a + 0.5`, `to!(int)(a) + 1`, foo)(1) == 2.5); 1290 } 1291 1292 private template getOverloads(alias fun) 1293 { 1294 import std.meta : AliasSeq; 1295 static if (__traits(compiles, __traits(getOverloads, __traits(parent, fun), __traits(identifier, fun), true))) 1296 alias getOverloads = __traits(getOverloads, __traits(parent, fun), __traits(identifier, fun), true); 1297 else 1298 alias getOverloads = AliasSeq!fun; 1299 } 1300 1301 /** 1302 * $(LINK2 https://en.wikipedia.org/wiki/Memoization, Memoizes) a function so as 1303 * to avoid repeated computation. The memoization structure is a hash table keyed by a 1304 * tuple of the function's arguments. There is a speed gain if the 1305 * function is repeatedly called with the same arguments and is more 1306 * expensive than a hash table lookup. For more information on memoization, refer to $(HTTP docs.google.com/viewer?url=http%3A%2F%2Fhop.perl.plover.com%2Fbook%2Fpdf%2F03CachingAndMemoization.pdf, this book chapter). 1307 1308 Example: 1309 ---- 1310 double transmogrify(int a, string b) 1311 { 1312 ... expensive computation ... 1313 } 1314 alias fastTransmogrify = memoize!transmogrify; 1315 unittest 1316 { 1317 auto slow = transmogrify(2, "hello"); 1318 auto fast = fastTransmogrify(2, "hello"); 1319 assert(slow == fast); 1320 } 1321 ---- 1322 1323 Params: 1324 fun = the call-able to memozie 1325 maxSize = The maximum size of the GC buffer to hold the return values 1326 Returns: 1327 A new function which calls `fun` and caches its return values. 1328 1329 Note: 1330 Technically the memoized function should be pure because `memoize` assumes it will 1331 always return the same result for a given tuple of arguments. However, `memoize` does not 1332 enforce that because sometimes it is useful to memoize an impure function, too. 1333 */ 1334 template memoize(alias fun) 1335 { 1336 import std.traits : Parameters; 1337 import std.meta : anySatisfy; 1338 1339 // Specific overloads: 1340 alias overloads = getOverloads!fun; 1341 static foreach (fn; overloads) 1342 static if (is(Parameters!fn)) 1343 alias memoize = impl!(Parameters!fn); 1344 1345 enum isTemplate(alias a) = __traits(isTemplate, a); 1346 static if (anySatisfy!(isTemplate, overloads)) 1347 { 1348 // Generic implementation 1349 alias memoize = impl; 1350 } 1351 1352 auto impl(Args...)(Args args) 1353 if (is(typeof(fun(args)))) 1354 { 1355 import std.typecons : Tuple, tuple; 1356 import std.traits : Unqual; 1357 1358 static if (args.length > 0) 1359 { 1360 static Unqual!(typeof(fun(args)))[Tuple!(typeof(args))] memo; 1361 1362 auto t = Tuple!Args(args); 1363 if (auto p = t in memo) 1364 return *p; 1365 auto r = fun(args); 1366 memo[t] = r; 1367 return r; 1368 } 1369 else 1370 { 1371 static typeof(fun(args)) result; 1372 result = fun(args); 1373 return result; 1374 } 1375 } 1376 } 1377 1378 /// ditto 1379 template memoize(alias fun, uint maxSize) 1380 { 1381 import std.traits : Parameters; 1382 import std.meta : anySatisfy; 1383 1384 // Specific overloads: 1385 alias overloads = getOverloads!fun; 1386 static foreach (fn; overloads) 1387 static if (is(Parameters!fn)) 1388 alias memoize = impl!(Parameters!fn); 1389 1390 enum isTemplate(alias a) = __traits(isTemplate, a); 1391 static if (anySatisfy!(isTemplate, overloads)) 1392 { 1393 // Generic implementation 1394 alias memoize = impl; 1395 } 1396 1397 auto impl(Args...)(Args args) 1398 if (is(typeof(fun(args)))) 1399 { 1400 static if (args.length > 0) 1401 { 1402 import std.meta : staticMap; 1403 import std.traits : hasIndirections, Unqual; 1404 import std.typecons : tuple; 1405 alias returnType = typeof(fun(args)); 1406 static struct Value { staticMap!(Unqual, Args) args; Unqual!returnType res; } 1407 static Value[] memo; 1408 static size_t[] initialized; 1409 1410 if (!memo.length) 1411 { 1412 import core.memory : GC; 1413 1414 // Ensure no allocation overflows 1415 static assert(maxSize < size_t.max / Value.sizeof); 1416 static assert(maxSize < size_t.max - (8 * size_t.sizeof - 1)); 1417 1418 enum attr = GC.BlkAttr.NO_INTERIOR | (hasIndirections!Value ? 0 : GC.BlkAttr.NO_SCAN); 1419 memo = (cast(Value*) GC.malloc(Value.sizeof * maxSize, attr))[0 .. maxSize]; 1420 enum nwords = (maxSize + 8 * size_t.sizeof - 1) / (8 * size_t.sizeof); 1421 initialized = (cast(size_t*) GC.calloc(nwords * size_t.sizeof, attr | GC.BlkAttr.NO_SCAN))[0 .. nwords]; 1422 } 1423 1424 import core.bitop : bt, bts; 1425 import core.lifetime : emplace; 1426 1427 size_t hash; 1428 foreach (ref arg; args) 1429 hash = hashOf(arg, hash); 1430 // cuckoo hashing 1431 immutable idx1 = hash % maxSize; 1432 if (!bt(initialized.ptr, idx1)) 1433 { 1434 emplace(&memo[idx1], args, fun(args)); 1435 // only set to initialized after setting args and value 1436 // https://issues.dlang.org/show_bug.cgi?id=14025 1437 bts(initialized.ptr, idx1); 1438 return memo[idx1].res; 1439 } 1440 else if (memo[idx1].args == args) 1441 return memo[idx1].res; 1442 // FNV prime 1443 immutable idx2 = (hash * 16_777_619) % maxSize; 1444 if (!bt(initialized.ptr, idx2)) 1445 { 1446 emplace(&memo[idx2], memo[idx1]); 1447 bts(initialized.ptr, idx2); 1448 } 1449 else if (memo[idx2].args == args) 1450 return memo[idx2].res; 1451 else if (idx1 != idx2) 1452 memo[idx2] = memo[idx1]; 1453 1454 memo[idx1] = Value(args, fun(args)); 1455 return memo[idx1].res; 1456 } 1457 else 1458 { 1459 static typeof(fun(args)) result; 1460 result = fun(args); 1461 return result; 1462 } 1463 } 1464 } 1465 1466 /** 1467 * To _memoize a recursive function, simply insert the memoized call in lieu of the plain recursive call. 1468 * For example, to transform the exponential-time Fibonacci implementation into a linear-time computation: 1469 */ 1470 @safe nothrow 1471 unittest 1472 { 1473 ulong fib(ulong n) @safe nothrow 1474 { 1475 return n < 2 ? n : memoize!fib(n - 2) + memoize!fib(n - 1); 1476 } 1477 assert(fib(10) == 55); 1478 } 1479 1480 /** 1481 * To improve the speed of the factorial function, 1482 */ 1483 @safe unittest 1484 { 1485 ulong fact(ulong n) @safe 1486 { 1487 return n < 2 ? 1 : n * memoize!fact(n - 1); 1488 } 1489 assert(fact(10) == 3628800); 1490 } 1491 1492 /** 1493 * This memoizes all values of `fact` up to the largest argument. To only cache the final 1494 * result, move `memoize` outside the function as shown below. 1495 */ 1496 @safe unittest 1497 { 1498 ulong factImpl(ulong n) @safe 1499 { 1500 return n < 2 ? 1 : n * factImpl(n - 1); 1501 } 1502 alias fact = memoize!factImpl; 1503 assert(fact(10) == 3628800); 1504 } 1505 1506 /** 1507 * When the `maxSize` parameter is specified, memoize will used 1508 * a fixed size hash table to limit the number of cached entries. 1509 */ 1510 @system unittest // not @safe due to memoize 1511 { 1512 ulong fact(ulong n) 1513 { 1514 // Memoize no more than 8 values 1515 return n < 2 ? 1 : n * memoize!(fact, 8)(n - 1); 1516 } 1517 assert(fact(8) == 40320); 1518 // using more entries than maxSize will overwrite existing entries 1519 assert(fact(10) == 3628800); 1520 } 1521 1522 // Issue 20099 1523 @system unittest // not @safe due to memoize 1524 { 1525 int i = 3; 1526 alias a = memoize!((n) => i + n); 1527 alias b = memoize!((n) => i + n, 3); 1528 1529 assert(a(3) == 6); 1530 assert(b(3) == 6); 1531 } 1532 1533 @system unittest // not @safe due to memoize 1534 { 1535 static Object objNum(int a) { return new Object(); } 1536 assert(memoize!objNum(0) is memoize!objNum(0U)); 1537 assert(memoize!(objNum, 3)(0) is memoize!(objNum, 3)(0U)); 1538 } 1539 1540 @system unittest // not @safe due to memoize 1541 { 1542 struct S 1543 { 1544 static int fun() { return 0; } 1545 static int fun(int i) { return 1; } 1546 } 1547 assert(memoize!(S.fun)() == 0); 1548 assert(memoize!(S.fun)(3) == 1); 1549 assert(memoize!(S.fun, 3)() == 0); 1550 assert(memoize!(S.fun, 3)(3) == 1); 1551 } 1552 1553 @system unittest // not @safe due to memoize 1554 { 1555 import core.math : sqrt; 1556 alias msqrt = memoize!(function double(double x) { return sqrt(x); }); 1557 auto y = msqrt(2.0); 1558 assert(y == msqrt(2.0)); 1559 y = msqrt(4.0); 1560 assert(y == sqrt(4.0)); 1561 1562 // alias mrgb2cmyk = memoize!rgb2cmyk; 1563 // auto z = mrgb2cmyk([43, 56, 76]); 1564 // assert(z == mrgb2cmyk([43, 56, 76])); 1565 1566 //alias mfib = memoize!fib; 1567 1568 static ulong fib(ulong n) @safe 1569 { 1570 alias mfib = memoize!fib; 1571 return n < 2 ? 1 : mfib(n - 2) + mfib(n - 1); 1572 } 1573 1574 auto z = fib(10); 1575 assert(z == 89); 1576 1577 static ulong fact(ulong n) @safe 1578 { 1579 alias mfact = memoize!fact; 1580 return n < 2 ? 1 : n * mfact(n - 1); 1581 } 1582 assert(fact(10) == 3628800); 1583 1584 // https://issues.dlang.org/show_bug.cgi?id=12568 1585 static uint len2(const string s) { // Error 1586 alias mLen2 = memoize!len2; 1587 if (s.length == 0) 1588 return 0; 1589 else 1590 return 1 + mLen2(s[1 .. $]); 1591 } 1592 1593 int _func(int x) @safe { return 1; } 1594 alias func = memoize!(_func, 10); 1595 assert(func(int.init) == 1); 1596 assert(func(int.init) == 1); 1597 } 1598 1599 // https://issues.dlang.org/show_bug.cgi?id=16079 1600 // memoize should work with arrays 1601 @system unittest // not @safe with -dip1000 due to memoize 1602 { 1603 int executed = 0; 1604 T median(T)(const T[] nums) { 1605 import std.algorithm.sorting : sort; 1606 executed++; 1607 auto arr = nums.dup; 1608 arr.sort(); 1609 if (arr.length % 2) 1610 return arr[$ / 2]; 1611 else 1612 return (arr[$ / 2 - 1] 1613 + arr[$ / 2]) / 2; 1614 } 1615 1616 alias fastMedian = memoize!(median!int); 1617 1618 assert(fastMedian([7, 5, 3]) == 5); 1619 assert(fastMedian([7, 5, 3]) == 5); 1620 1621 assert(executed == 1); 1622 } 1623 1624 // https://issues.dlang.org/show_bug.cgi?id=16079: memoize should work with structs 1625 @safe unittest 1626 { 1627 int executed = 0; 1628 T pickFirst(T)(T first) 1629 { 1630 executed++; 1631 return first; 1632 } 1633 1634 struct Foo { int k; } 1635 Foo A = Foo(3); 1636 1637 alias first = memoize!(pickFirst!Foo); 1638 assert(first(Foo(3)) == A); 1639 assert(first(Foo(3)) == A); 1640 assert(executed == 1); 1641 } 1642 1643 // https://issues.dlang.org/show_bug.cgi?id=20439 memoize should work with void opAssign 1644 @safe unittest 1645 { 1646 static struct S 1647 { 1648 void opAssign(S) {} 1649 } 1650 1651 assert(memoize!(() => S()) == S()); 1652 } 1653 1654 // https://issues.dlang.org/show_bug.cgi?id=16079: memoize should work with classes 1655 @system unittest // not @safe with -dip1000 due to memoize 1656 { 1657 int executed = 0; 1658 T pickFirst(T)(T first) 1659 { 1660 executed++; 1661 return first; 1662 } 1663 1664 class Bar 1665 { 1666 size_t k; 1667 this(size_t k) 1668 { 1669 this.k = k; 1670 } 1671 override size_t toHash() 1672 { 1673 return k; 1674 } 1675 override bool opEquals(Object o) 1676 { 1677 auto b = cast(Bar) o; 1678 return b && k == b.k; 1679 } 1680 } 1681 1682 alias firstClass = memoize!(pickFirst!Bar); 1683 assert(firstClass(new Bar(3)).k == 3); 1684 assert(firstClass(new Bar(3)).k == 3); 1685 assert(executed == 1); 1686 } 1687 1688 // https://issues.dlang.org/show_bug.cgi?id=20302 1689 @system unittest 1690 { 1691 version (none) // TODO change `none` to `all` and fix remaining limitations 1692 struct S { const int len; } 1693 else 1694 struct S { int len; } 1695 1696 static string fun000( string str, S s) { return str[0 .. s.len] ~ "123"; } 1697 static string fun001( string str, const S s) { return str[0 .. s.len] ~ "123"; } 1698 static string fun010(const string str, S s) { return str[0 .. s.len] ~ "123"; } 1699 static string fun011(const string str, const S s) { return str[0 .. s.len] ~ "123"; } 1700 static const(string) fun100( string str, S s) { return str[0 .. s.len] ~ "123"; } 1701 static const(string) fun101( string str, const S s) { return str[0 .. s.len] ~ "123"; } 1702 static const(string) fun110(const string str, S s) { return str[0 .. s.len] ~ "123"; } 1703 static const(string) fun111(const string str, const S s) { return str[0 .. s.len] ~ "123"; } 1704 1705 static foreach (fun; AliasSeq!(fun000, fun001, fun010, fun011, fun100, fun101, fun110, fun111)) 1706 {{ 1707 alias mfun = memoize!fun; 1708 assert(mfun("abcdefgh", S(3)) == "abc123"); 1709 1710 alias mfun2 = memoize!(fun, 42); 1711 assert(mfun2("asd", S(3)) == "asd123"); 1712 }} 1713 } 1714 1715 // memoize should continue to work with functions that cannot be evaluated at compile time 1716 @system unittest 1717 { 1718 __gshared string[string] glob; 1719 1720 static bool foo() 1721 { 1722 return (":-)" in glob) is null; 1723 } 1724 1725 assert(memoize!foo); 1726 } 1727 1728 private struct DelegateFaker(F) 1729 { 1730 import std.typecons : FuncInfo, MemberFunctionGenerator; 1731 1732 // for @safe 1733 static F castToF(THIS)(THIS x) @trusted 1734 { 1735 return cast(F) x; 1736 } 1737 1738 /* 1739 * What all the stuff below does is this: 1740 *-------------------- 1741 * struct DelegateFaker(F) { 1742 * extern(linkage) 1743 * [ref] ReturnType!F doIt(Parameters!F args) [@attributes] 1744 * { 1745 * auto fp = cast(F) &this; 1746 * return fp(args); 1747 * } 1748 * } 1749 *-------------------- 1750 */ 1751 1752 // We will use MemberFunctionGenerator in std.typecons. This is a policy 1753 // configuration for generating the doIt(). 1754 template GeneratingPolicy() 1755 { 1756 // Inform the genereator that we only have type information. 1757 enum WITHOUT_SYMBOL = true; 1758 1759 // Generate the function body of doIt(). 1760 template generateFunctionBody(unused...) 1761 { 1762 enum generateFunctionBody = 1763 // [ref] ReturnType doIt(Parameters args) @attributes 1764 q{ 1765 // When this function gets called, the this pointer isn't 1766 // really a this pointer (no instance even really exists), but 1767 // a function pointer that points to the function to be called. 1768 // Cast it to the correct type and call it. 1769 1770 auto fp = castToF(&this); 1771 return fp(args); 1772 }; 1773 } 1774 } 1775 // Type information used by the generated code. 1776 alias FuncInfo_doIt = FuncInfo!(F); 1777 1778 // Generate the member function doIt(). 1779 mixin( MemberFunctionGenerator!(GeneratingPolicy!()) 1780 .generateFunction!("FuncInfo_doIt", "doIt", F) ); 1781 } 1782 1783 /** 1784 * Convert a callable to a delegate with the same parameter list and 1785 * return type, avoiding heap allocations and use of auxiliary storage. 1786 * 1787 * Params: 1788 * fp = a function pointer or an aggregate type with `opCall` defined. 1789 * Returns: 1790 * A delegate with the context pointer pointing to nothing. 1791 * 1792 * Example: 1793 * ---- 1794 * void doStuff() { 1795 * writeln("Hello, world."); 1796 * } 1797 * 1798 * void runDelegate(void delegate() myDelegate) { 1799 * myDelegate(); 1800 * } 1801 * 1802 * auto delegateToPass = toDelegate(&doStuff); 1803 * runDelegate(delegateToPass); // Calls doStuff, prints "Hello, world." 1804 * ---- 1805 * 1806 * BUGS: 1807 * $(UL 1808 * $(LI Does not work with `@safe` functions.) 1809 * $(LI Ignores C-style / D-style variadic arguments.) 1810 * ) 1811 */ 1812 auto toDelegate(F)(auto ref F fp) 1813 if (isCallable!(F)) 1814 { 1815 static if (is(F == delegate)) 1816 { 1817 return fp; 1818 } 1819 else static if (is(F Func == Func*) && is(Func == function)) 1820 { 1821 return function(ref F fp) @trusted 1822 { 1823 return buildDelegate(fp); 1824 }(fp); 1825 } 1826 else static if (is(typeof(&F.opCall) == delegate) 1827 || (is(typeof(&F.opCall) V : V*) && is(V == function))) 1828 { 1829 return toDelegate(&fp.opCall); 1830 } 1831 else static if (is(typeof(&fp.opCall!()))) 1832 { 1833 return toDelegate(&fp.opCall!()); 1834 } 1835 else 1836 { 1837 static assert(false, "Unsupported type of callable, please open an issue."); 1838 } 1839 } 1840 1841 /// 1842 @safe unittest 1843 { 1844 static int inc(ref uint num) { 1845 num++; 1846 return 8675309; 1847 } 1848 1849 uint myNum = 0; 1850 auto incMyNumDel = toDelegate(&inc); 1851 auto returnVal = incMyNumDel(myNum); 1852 assert(myNum == 1); 1853 } 1854 1855 private template buildDelegate(F) 1856 { 1857 auto buildDelegate(auto ref F fp) { 1858 alias DelType = typeof(&(new DelegateFaker!(F)).doIt); 1859 1860 static struct DelegateFields { 1861 union { 1862 DelType del; 1863 //pragma(msg, typeof(del)); 1864 1865 struct { 1866 void* contextPtr; 1867 void* funcPtr; 1868 } 1869 } 1870 } 1871 1872 // fp is stored in the returned delegate's context pointer. 1873 // The returned delegate's function pointer points to 1874 // DelegateFaker.doIt. 1875 DelegateFields df; 1876 1877 df.contextPtr = cast(void*) fp; 1878 1879 DelegateFaker!(F) dummy; 1880 auto dummyDel = &dummy.doIt; 1881 df.funcPtr = dummyDel.funcptr; 1882 1883 return df.del; 1884 } 1885 } 1886 1887 @safe unittest 1888 { 1889 static int inc(ref uint num) { 1890 num++; 1891 return 8675309; 1892 } 1893 1894 uint myNum = 0x1337; 1895 struct S1 { int opCall() { inc(myNum); return myNum; } } 1896 static assert(!is(typeof(&s1.opCall) == delegate)); 1897 S1 s1; 1898 auto getvals1 = toDelegate(s1); 1899 assert(getvals1() == 0x1338); 1900 } 1901 1902 @system unittest 1903 { 1904 static int inc(ref uint num) { 1905 num++; 1906 return 8675309; 1907 } 1908 1909 uint myNum = 0; 1910 auto incMyNumDel = toDelegate(&inc); 1911 int delegate(ref uint) dg = incMyNumDel; 1912 auto returnVal = incMyNumDel(myNum); 1913 assert(myNum == 1); 1914 1915 interface I { int opCall(); } 1916 class C: I { int opCall() { inc(myNum); return myNum;} } 1917 auto c = new C; 1918 auto i = cast(I) c; 1919 1920 auto getvalc = toDelegate(c); 1921 assert(getvalc() == 2); 1922 1923 auto getvali = toDelegate(i); 1924 assert(getvali() == 3); 1925 1926 struct S1 { int opCall() { inc(myNum); return myNum; } } 1927 static assert(!is(typeof(&s1.opCall) == delegate)); 1928 S1 s1; 1929 auto getvals1 = toDelegate(s1); 1930 assert(getvals1() == 4); 1931 1932 struct S2 { static int opCall() { return 123456; } } 1933 static assert(!is(typeof(&S2.opCall) == delegate)); 1934 S2 s2; 1935 auto getvals2 =&S2.opCall; 1936 assert(getvals2() == 123456); 1937 1938 /* test for attributes */ 1939 { 1940 static int refvar = 0xDeadFace; 1941 1942 static ref int func_ref() { return refvar; } 1943 static int func_pure() pure { return 1; } 1944 static int func_nothrow() nothrow { return 2; } 1945 static int func_property() @property { return 3; } 1946 static int func_safe() @safe { return 4; } 1947 static int func_trusted() @trusted { return 5; } 1948 static int func_system() @system { return 6; } 1949 static int func_pure_nothrow() pure nothrow { return 7; } 1950 static int func_pure_nothrow_safe() pure nothrow @safe { return 8; } 1951 1952 auto dg_ref = toDelegate(&func_ref); 1953 int delegate() pure dg_pure = toDelegate(&func_pure); 1954 int delegate() nothrow dg_nothrow = toDelegate(&func_nothrow); 1955 int delegate() @property dg_property = toDelegate(&func_property); 1956 int delegate() @safe dg_safe = toDelegate(&func_safe); 1957 int delegate() @trusted dg_trusted = toDelegate(&func_trusted); 1958 int delegate() @system dg_system = toDelegate(&func_system); 1959 int delegate() pure nothrow dg_pure_nothrow = toDelegate(&func_pure_nothrow); 1960 int delegate() @safe pure nothrow dg_pure_nothrow_safe = toDelegate(&func_pure_nothrow_safe); 1961 1962 //static assert(is(typeof(dg_ref) == ref int delegate())); // [BUG@DMD] 1963 1964 assert(dg_ref() == refvar); 1965 assert(dg_pure() == 1); 1966 assert(dg_nothrow() == 2); 1967 assert(dg_property() == 3); 1968 assert(dg_safe() == 4); 1969 assert(dg_trusted() == 5); 1970 assert(dg_system() == 6); 1971 assert(dg_pure_nothrow() == 7); 1972 assert(dg_pure_nothrow_safe() == 8); 1973 } 1974 /* test for linkage */ 1975 { 1976 struct S 1977 { 1978 extern(C) static void xtrnC() {} 1979 extern(D) static void xtrnD() {} 1980 } 1981 auto dg_xtrnC = toDelegate(&S.xtrnC); 1982 auto dg_xtrnD = toDelegate(&S.xtrnD); 1983 static assert(! is(typeof(dg_xtrnC) == typeof(dg_xtrnD))); 1984 } 1985 } 1986 1987 1988 @safe unittest 1989 { 1990 static struct S1 { static void opCall()() { } } 1991 static struct S2 { static T opCall(T = int)(T x) {return x; } } 1992 1993 S1 i1; 1994 const dg1 = toDelegate(i1); 1995 dg1(); 1996 1997 S2 i2; 1998 assert(toDelegate(i2)(0xBED) == 0xBED); 1999 } 2000 2001 @safe unittest 2002 { 2003 static void fun() @system pure nothrow @nogc 2004 { 2005 return; 2006 } 2007 2008 auto fn = &fun; 2009 static assert( is(typeof(fn) == void function() @system pure nothrow @nogc)); 2010 static assert(!is(typeof(fn) == void function() @safe pure nothrow @nogc)); 2011 2012 auto dg = fn.toDelegate(); 2013 static assert( is(typeof(dg) == void delegate() @system pure nothrow @nogc)); 2014 static assert(!is(typeof(dg) == void delegate() @safe pure nothrow @nogc)); 2015 } 2016 2017 /** 2018 * Passes the fields of a struct as arguments to a function. 2019 * 2020 * Can be used with a $(LINK2 https://dlang.org/spec/expression.html#function_literals, 2021 * function literal) to give temporary names to the fields of a struct or 2022 * tuple. 2023 * 2024 * Params: 2025 * fun = Callable that the struct's fields will be passed to. 2026 * 2027 * Returns: 2028 * A function that accepts a single struct as an argument and passes its 2029 * fields to `fun` when called. 2030 */ 2031 template bind(alias fun) 2032 { 2033 /** 2034 * Params: 2035 * args = The struct or tuple whose fields will be used as arguments. 2036 * 2037 * Returns: `fun(args.tupleof)` 2038 */ 2039 auto ref bind(T)(auto ref T args) 2040 if (is(T == struct)) 2041 { 2042 import std.meta : Map = staticMap; 2043 import core.lifetime : move; 2044 2045 // Forwards the i'th member of `args` 2046 // Needed because core.lifetime.forward doesn't work on struct members 2047 template forwardArg(size_t i) 2048 { 2049 static if (__traits(isRef, args) || !is(typeof(move(args.tupleof[i])))) 2050 enum forwardArg = "args.tupleof[" ~ toCtString!i ~ "], "; 2051 else 2052 enum forwardArg = "move(args.tupleof[" ~ toCtString!i ~ "]), "; 2053 } 2054 2055 static if (args.tupleof.length == 0) 2056 enum argList = ""; 2057 else 2058 alias argList = Map!(forwardArg, Iota!(args.tupleof.length)); 2059 2060 return mixin("fun(", argList, ")"); 2061 } 2062 } 2063 2064 /// Giving names to tuple elements 2065 @safe unittest 2066 { 2067 import std.typecons : tuple; 2068 2069 auto name = tuple("John", "Doe"); 2070 string full = name.bind!((first, last) => first ~ " " ~ last); 2071 assert(full == "John Doe"); 2072 } 2073 2074 /// Passing struct fields to a function 2075 @safe unittest 2076 { 2077 import std.algorithm.comparison : min, max; 2078 2079 struct Pair 2080 { 2081 int a; 2082 int b; 2083 } 2084 2085 auto p = Pair(123, 456); 2086 assert(p.bind!min == 123); // min(p.a, p.b) 2087 assert(p.bind!max == 456); // max(p.a, p.b) 2088 } 2089 2090 /// In a range pipeline 2091 @safe unittest 2092 { 2093 import std.algorithm.iteration : map, filter; 2094 import std.algorithm.comparison : equal; 2095 import std.typecons : tuple; 2096 2097 auto ages = [ 2098 tuple("Alice", 35), 2099 tuple("Bob", 64), 2100 tuple("Carol", 21), 2101 tuple("David", 39), 2102 tuple("Eve", 50) 2103 ]; 2104 2105 auto overForty = ages 2106 .filter!(bind!((name, age) => age > 40)) 2107 .map!(bind!((name, age) => name)); 2108 2109 assert(overForty.equal(["Bob", "Eve"])); 2110 } 2111 2112 // Zero arguments 2113 @safe unittest 2114 { 2115 struct Empty {} 2116 2117 assert(Empty().bind!(() => 123) == 123); 2118 } 2119 2120 // Non-copyable arguments 2121 @safe unittest 2122 { 2123 import std.typecons : tuple; 2124 2125 static struct NoCopy 2126 { 2127 int n; 2128 @disable this(this); 2129 } 2130 2131 static struct Pair 2132 { 2133 NoCopy a, b; 2134 } 2135 2136 static auto fun(NoCopy a, NoCopy b) 2137 { 2138 return tuple(a.n, b.n); 2139 } 2140 2141 auto expected = fun(NoCopy(1), NoCopy(2)); 2142 assert(Pair(NoCopy(1), NoCopy(2)).bind!fun == expected); 2143 } 2144 2145 // ref arguments 2146 @safe unittest 2147 { 2148 import std.typecons : tuple; 2149 2150 auto t = tuple(123, 456); 2151 t.bind!((ref int a, int b) { a = 789; b = 1011; }); 2152 2153 assert(t[0] == 789); 2154 assert(t[1] == 456); 2155 } 2156 2157 // auto ref arguments 2158 @safe unittest 2159 { 2160 import std.typecons : tuple; 2161 2162 auto t = tuple(123); 2163 t.bind!((auto ref x) { 2164 static assert(__traits(isRef, x)); 2165 }); 2166 tuple(123).bind!((auto ref x) { 2167 static assert(!__traits(isRef, x)); 2168 }); 2169 }