[{"data":1,"prerenderedAt":2864},["ShallowReactive",2],{"page-\u002Fdart\u002F05-functions-and-scope":3},{"id":4,"title":5,"body":6,"description":2857,"extension":2858,"meta":2859,"navigation":63,"path":2860,"seo":2861,"stem":2862,"__hash__":2863},"content\u002Fdart\u002F05-functions-and-scope.md","Dart — Functions, Closures & Generator Semantics",{"type":7,"value":8,"toc":2845},"minimark",[9,13,18,530,534,933,937,1397,1408,1926,1934,2379,2383,2457,2461,2641,2645,2649,2703,2714,2841],[10,11,5],"h1",{"id":12},"dart-functions-closures-generator-semantics",[14,15,17],"h2",{"id":16},"parameter-architecture-positional-named-required","Parameter Architecture — Positional, Named, Required",[19,20,22],"code-wrapper",{"language":21},"dart",[23,24,28],"pre",{"className":25,"code":26,"language":21,"meta":27,"style":27},"language-dart shiki shiki-themes github-light github-dark","\u002F\u002F Dart has three parameter categories with strict ordering rules:\n\u002F\u002F 1. Required positional (no brackets)\n\u002F\u002F 2. Optional positional (in [...])\n\u002F\u002F 3. Named parameters (in {...}) — optional or `required`\n\n\u002F\u002F All three can coexist, but order is mandatory:\nvoid createServer(\n  String host,              \u002F\u002F required positional (must come first)\n  int port,                 \u002F\u002F required positional\n  [String? certPath]        \u002F\u002F optional positional (nullable or with default)\n  , {\n  required String name,     \u002F\u002F required named (must be provided by name)\n  int backlog = 128,        \u002F\u002F optional named with default\n  bool tls = false,         \u002F\u002F optional named with default\n}) {\n  \u002F\u002F ...\n}\n\ncreateServer('0.0.0.0', 8080, '\u002Fcert.pem', name: 'api', tls: true);\ncreateServer('0.0.0.0', 8080, name: 'api');  \u002F\u002F certPath omitted, backlog=128, tls=false\n\n\u002F\u002F ❌ Anti-pattern: boolean positional flags — unclear at the call site.\nvoid init(bool debug, bool verbose, bool color) { ... }\ninit(true, false, true);  \u002F\u002F what do these mean?!\n\n\u002F\u002F ✓ Correct: named parameters for booleans and options.\nvoid init({bool debug = false, bool verbose = false, bool color = true}) { ... }\ninit(debug: true, color: false);  \u002F\u002F self-documenting\n\n\u002F\u002F Default values must be compile-time constants:\nvoid configure({Duration timeout = const Duration(seconds: 30)}) { ... }\n\u002F\u002F void configure({String dir = getHomeDir()}) { ... }  \u002F\u002F ✗ not a const\n\u002F\u002F ✓ Use null default + ?? for runtime defaults:\nvoid configure({String? dir}) {\n  final resolved = dir ?? getHomeDir();  \u002F\u002F runtime default\n}\n","",[29,30,31,40,46,52,58,65,71,86,99,111,129,135,150,170,189,195,201,207,212,256,281,286,292,318,343,348,354,398,422,427,433,468,477,483,499,525],"code",{"__ignoreMap":27},[32,33,36],"span",{"class":34,"line":35},"line",1,[32,37,39],{"class":38},"sdCPZ","\u002F\u002F Dart has three parameter categories with strict ordering rules:\n",[32,41,43],{"class":34,"line":42},2,[32,44,45],{"class":38},"\u002F\u002F 1. Required positional (no brackets)\n",[32,47,49],{"class":34,"line":48},3,[32,50,51],{"class":38},"\u002F\u002F 2. Optional positional (in [...])\n",[32,53,55],{"class":34,"line":54},4,[32,56,57],{"class":38},"\u002F\u002F 3. Named parameters (in {...}) — optional or `required`\n",[32,59,61],{"class":34,"line":60},5,[32,62,64],{"emptyLinePlaceholder":63},true,"\n",[32,66,68],{"class":34,"line":67},6,[32,69,70],{"class":38},"\u002F\u002F All three can coexist, but order is mandatory:\n",[32,72,74,78,82],{"class":34,"line":73},7,[32,75,77],{"class":76},"svdQ7","void",[32,79,81],{"class":80},"sIsaT"," createServer",[32,83,85],{"class":84},"ssxIu","(\n",[32,87,89,93,96],{"class":34,"line":88},8,[32,90,92],{"class":91},"snvgF","  String",[32,94,95],{"class":84}," host,              ",[32,97,98],{"class":38},"\u002F\u002F required positional (must come first)\n",[32,100,102,105,108],{"class":34,"line":101},9,[32,103,104],{"class":91},"  int",[32,106,107],{"class":84}," port,                 ",[32,109,110],{"class":38},"\u002F\u002F required positional\n",[32,112,114,117,120,123,126],{"class":34,"line":113},10,[32,115,116],{"class":84},"  [",[32,118,119],{"class":91},"String",[32,121,122],{"class":76},"?",[32,124,125],{"class":84}," certPath]        ",[32,127,128],{"class":38},"\u002F\u002F optional positional (nullable or with default)\n",[32,130,132],{"class":34,"line":131},11,[32,133,134],{"class":84},"  , {\n",[32,136,138,141,144,147],{"class":34,"line":137},12,[32,139,140],{"class":76},"  required",[32,142,143],{"class":91}," String",[32,145,146],{"class":84}," name,     ",[32,148,149],{"class":38},"\u002F\u002F required named (must be provided by name)\n",[32,151,153,155,158,161,164,167],{"class":34,"line":152},13,[32,154,104],{"class":91},[32,156,157],{"class":84}," backlog ",[32,159,160],{"class":76},"=",[32,162,163],{"class":91}," 128",[32,165,166],{"class":84},",        ",[32,168,169],{"class":38},"\u002F\u002F optional named with default\n",[32,171,173,176,179,181,184,187],{"class":34,"line":172},14,[32,174,175],{"class":91},"  bool",[32,177,178],{"class":84}," tls ",[32,180,160],{"class":76},[32,182,183],{"class":91}," false",[32,185,186],{"class":84},",         ",[32,188,169],{"class":38},[32,190,192],{"class":34,"line":191},15,[32,193,194],{"class":84},"}) {\n",[32,196,198],{"class":34,"line":197},16,[32,199,200],{"class":38},"  \u002F\u002F ...\n",[32,202,204],{"class":34,"line":203},17,[32,205,206],{"class":84},"}\n",[32,208,210],{"class":34,"line":209},18,[32,211,64],{"emptyLinePlaceholder":63},[32,213,215,218,221,225,228,231,233,236,239,242,245,248,250,253],{"class":34,"line":214},19,[32,216,217],{"class":80},"createServer",[32,219,220],{"class":84},"(",[32,222,224],{"class":223},"sJ6F3","'0.0.0.0'",[32,226,227],{"class":84},", ",[32,229,230],{"class":91},"8080",[32,232,227],{"class":84},[32,234,235],{"class":223},"'\u002Fcert.pem'",[32,237,238],{"class":84},", name",[32,240,241],{"class":76},":",[32,243,244],{"class":223}," 'api'",[32,246,247],{"class":84},", tls",[32,249,241],{"class":76},[32,251,252],{"class":91}," true",[32,254,255],{"class":84},");\n",[32,257,259,261,263,265,267,269,271,273,275,278],{"class":34,"line":258},20,[32,260,217],{"class":80},[32,262,220],{"class":84},[32,264,224],{"class":223},[32,266,227],{"class":84},[32,268,230],{"class":91},[32,270,238],{"class":84},[32,272,241],{"class":76},[32,274,244],{"class":223},[32,276,277],{"class":84},");  ",[32,279,280],{"class":38},"\u002F\u002F certPath omitted, backlog=128, tls=false\n",[32,282,284],{"class":34,"line":283},21,[32,285,64],{"emptyLinePlaceholder":63},[32,287,289],{"class":34,"line":288},22,[32,290,291],{"class":38},"\u002F\u002F ❌ Anti-pattern: boolean positional flags — unclear at the call site.\n",[32,293,295,297,300,302,305,308,310,313,315],{"class":34,"line":294},23,[32,296,77],{"class":76},[32,298,299],{"class":80}," init",[32,301,220],{"class":84},[32,303,304],{"class":91},"bool",[32,306,307],{"class":84}," debug, ",[32,309,304],{"class":91},[32,311,312],{"class":84}," verbose, ",[32,314,304],{"class":91},[32,316,317],{"class":84}," color) { ... }\n",[32,319,321,324,326,329,331,334,336,338,340],{"class":34,"line":320},24,[32,322,323],{"class":80},"init",[32,325,220],{"class":84},[32,327,328],{"class":91},"true",[32,330,227],{"class":84},[32,332,333],{"class":91},"false",[32,335,227],{"class":84},[32,337,328],{"class":91},[32,339,277],{"class":84},[32,341,342],{"class":38},"\u002F\u002F what do these mean?!\n",[32,344,346],{"class":34,"line":345},25,[32,347,64],{"emptyLinePlaceholder":63},[32,349,351],{"class":34,"line":350},26,[32,352,353],{"class":38},"\u002F\u002F ✓ Correct: named parameters for booleans and options.\n",[32,355,357,359,361,364,366,369,371,373,375,377,380,382,384,386,388,391,393,395],{"class":34,"line":356},27,[32,358,77],{"class":76},[32,360,299],{"class":80},[32,362,363],{"class":84},"({",[32,365,304],{"class":91},[32,367,368],{"class":84}," debug ",[32,370,160],{"class":76},[32,372,183],{"class":91},[32,374,227],{"class":84},[32,376,304],{"class":91},[32,378,379],{"class":84}," verbose ",[32,381,160],{"class":76},[32,383,183],{"class":91},[32,385,227],{"class":84},[32,387,304],{"class":91},[32,389,390],{"class":84}," color ",[32,392,160],{"class":76},[32,394,252],{"class":91},[32,396,397],{"class":84},"}) { ... }\n",[32,399,401,403,406,408,410,413,415,417,419],{"class":34,"line":400},28,[32,402,323],{"class":80},[32,404,405],{"class":84},"(debug",[32,407,241],{"class":76},[32,409,252],{"class":91},[32,411,412],{"class":84},", color",[32,414,241],{"class":76},[32,416,183],{"class":91},[32,418,277],{"class":84},[32,420,421],{"class":38},"\u002F\u002F self-documenting\n",[32,423,425],{"class":34,"line":424},29,[32,426,64],{"emptyLinePlaceholder":63},[32,428,430],{"class":34,"line":429},30,[32,431,432],{"class":38},"\u002F\u002F Default values must be compile-time constants:\n",[32,434,436,438,441,443,446,449,451,454,457,460,462,465],{"class":34,"line":435},31,[32,437,77],{"class":76},[32,439,440],{"class":80}," configure",[32,442,363],{"class":84},[32,444,445],{"class":91},"Duration",[32,447,448],{"class":84}," timeout ",[32,450,160],{"class":76},[32,452,453],{"class":76}," const",[32,455,456],{"class":91}," Duration",[32,458,459],{"class":84},"(seconds",[32,461,241],{"class":76},[32,463,464],{"class":91}," 30",[32,466,467],{"class":84},")}) { ... }\n",[32,469,471,474],{"class":34,"line":470},32,[32,472,473],{"class":38},"\u002F\u002F void configure({String dir = getHomeDir()}) { ... }",[32,475,476],{"class":38},"  \u002F\u002F ✗ not a const\n",[32,478,480],{"class":34,"line":479},33,[32,481,482],{"class":38},"\u002F\u002F ✓ Use null default + ?? for runtime defaults:\n",[32,484,486,488,490,492,494,496],{"class":34,"line":485},34,[32,487,77],{"class":76},[32,489,440],{"class":80},[32,491,363],{"class":84},[32,493,119],{"class":91},[32,495,122],{"class":76},[32,497,498],{"class":84}," dir}) {\n",[32,500,502,505,508,510,513,516,519,522],{"class":34,"line":501},35,[32,503,504],{"class":76},"  final",[32,506,507],{"class":84}," resolved ",[32,509,160],{"class":76},[32,511,512],{"class":84}," dir ",[32,514,515],{"class":76},"??",[32,517,518],{"class":80}," getHomeDir",[32,520,521],{"class":84},"();  ",[32,523,524],{"class":38},"\u002F\u002F runtime default\n",[32,526,528],{"class":34,"line":527},36,[32,529,206],{"class":84},[14,531,533],{"id":532},"closures-capture-semantics-memory","Closures — Capture Semantics & Memory",[19,535,536],{"language":21},[23,537,539],{"className":25,"code":538,"language":21,"meta":27,"style":27},"\u002F\u002F Closures capture variables BY REFERENCE (not by value) from the enclosing scope.\n\u002F\u002F The captured variable stays alive as long as the closure exists (GC root).\n\n\u002F\u002F Each invocation of makeAdder creates a NEW `increment` on the stack,\n\u002F\u002F and the returned closure captures it — each closure has its own `increment`.\nFunction makeAdder(int increment) {\n  return (int x) => x + increment;  \u002F\u002F captures `increment` from this invocation\n}\n\nvar add5 = makeAdder(5);\nvar add10 = makeAdder(10);\nprint(add5(3));   \u002F\u002F 8  — its own captured increment=5\nprint(add10(3));  \u002F\u002F 13 — its own captured increment=10\n\n\u002F\u002F ❌ Anti-pattern: closures in a loop capture the loop variable (shared, mutated).\nvar handlers = \u003Cvoid Function()>[];\nfor (var i = 0; i \u003C 3; i++) {\n  handlers.add(() => print(i));\n}\nhandlers.forEach((f) => f());  \u002F\u002F 3, 3, 3 — all see the final value of i\n\n\u002F\u002F ✓ Correct: capture per-iteration in a final local.\nvar handlersFixed = \u003Cvoid Function()>[];\nfor (var i = 0; i \u003C 3; i++) {\n  final j = i;  \u002F\u002F fresh, immutable per iteration\n  handlersFixed.add(() => print(j));\n}\nhandlersFixed.forEach((f) => f());  \u002F\u002F 0, 1, 2\n\n\u002F\u002F Memory implication: closures keep captured variables alive (prevent GC).\n\u002F\u002F A closure stored in a long-lived collection can extend a variable's lifetime\n\u002F\u002F beyond its expected scope — be careful in long-running processes.\n",[29,540,541,546,551,555,560,565,581,609,613,617,636,654,675,694,698,703,727,762,781,785,807,811,816,835,861,876,892,896,914,918,923,928],{"__ignoreMap":27},[32,542,543],{"class":34,"line":35},[32,544,545],{"class":38},"\u002F\u002F Closures capture variables BY REFERENCE (not by value) from the enclosing scope.\n",[32,547,548],{"class":34,"line":42},[32,549,550],{"class":38},"\u002F\u002F The captured variable stays alive as long as the closure exists (GC root).\n",[32,552,553],{"class":34,"line":48},[32,554,64],{"emptyLinePlaceholder":63},[32,556,557],{"class":34,"line":54},[32,558,559],{"class":38},"\u002F\u002F Each invocation of makeAdder creates a NEW `increment` on the stack,\n",[32,561,562],{"class":34,"line":60},[32,563,564],{"class":38},"\u002F\u002F and the returned closure captures it — each closure has its own `increment`.\n",[32,566,567,570,573,575,578],{"class":34,"line":67},[32,568,569],{"class":91},"Function",[32,571,572],{"class":80}," makeAdder",[32,574,220],{"class":84},[32,576,577],{"class":91},"int",[32,579,580],{"class":84}," increment) {\n",[32,582,583,586,589,591,594,597,600,603,606],{"class":34,"line":73},[32,584,585],{"class":76},"  return",[32,587,588],{"class":84}," (",[32,590,577],{"class":91},[32,592,593],{"class":84}," x) ",[32,595,596],{"class":76},"=>",[32,598,599],{"class":84}," x ",[32,601,602],{"class":76},"+",[32,604,605],{"class":84}," increment;  ",[32,607,608],{"class":38},"\u002F\u002F captures `increment` from this invocation\n",[32,610,611],{"class":34,"line":88},[32,612,206],{"class":84},[32,614,615],{"class":34,"line":101},[32,616,64],{"emptyLinePlaceholder":63},[32,618,619,622,625,627,629,631,634],{"class":34,"line":113},[32,620,621],{"class":76},"var",[32,623,624],{"class":84}," add5 ",[32,626,160],{"class":76},[32,628,572],{"class":80},[32,630,220],{"class":84},[32,632,633],{"class":91},"5",[32,635,255],{"class":84},[32,637,638,640,643,645,647,649,652],{"class":34,"line":131},[32,639,621],{"class":76},[32,641,642],{"class":84}," add10 ",[32,644,160],{"class":76},[32,646,572],{"class":80},[32,648,220],{"class":84},[32,650,651],{"class":91},"10",[32,653,255],{"class":84},[32,655,656,659,661,664,666,669,672],{"class":34,"line":137},[32,657,658],{"class":80},"print",[32,660,220],{"class":84},[32,662,663],{"class":80},"add5",[32,665,220],{"class":84},[32,667,668],{"class":91},"3",[32,670,671],{"class":84},"));   ",[32,673,674],{"class":38},"\u002F\u002F 8  — its own captured increment=5\n",[32,676,677,679,681,684,686,688,691],{"class":34,"line":152},[32,678,658],{"class":80},[32,680,220],{"class":84},[32,682,683],{"class":80},"add10",[32,685,220],{"class":84},[32,687,668],{"class":91},[32,689,690],{"class":84},"));  ",[32,692,693],{"class":38},"\u002F\u002F 13 — its own captured increment=10\n",[32,695,696],{"class":34,"line":172},[32,697,64],{"emptyLinePlaceholder":63},[32,699,700],{"class":34,"line":191},[32,701,702],{"class":38},"\u002F\u002F ❌ Anti-pattern: closures in a loop capture the loop variable (shared, mutated).\n",[32,704,705,707,710,712,715,718,721,724],{"class":34,"line":197},[32,706,621],{"class":76},[32,708,709],{"class":84}," handlers ",[32,711,160],{"class":76},[32,713,714],{"class":76}," \u003Cvoid",[32,716,717],{"class":91}," Function",[32,719,720],{"class":84},"()",[32,722,723],{"class":76},">",[32,725,726],{"class":84},"[];\n",[32,728,729,732,734,736,739,741,744,747,750,753,756,759],{"class":34,"line":203},[32,730,731],{"class":76},"for",[32,733,588],{"class":84},[32,735,621],{"class":76},[32,737,738],{"class":84}," i ",[32,740,160],{"class":76},[32,742,743],{"class":91}," 0",[32,745,746],{"class":84},"; i ",[32,748,749],{"class":76},"\u003C",[32,751,752],{"class":91}," 3",[32,754,755],{"class":84},"; i",[32,757,758],{"class":76},"++",[32,760,761],{"class":84},") {\n",[32,763,764,767,770,773,775,778],{"class":34,"line":209},[32,765,766],{"class":84},"  handlers.",[32,768,769],{"class":80},"add",[32,771,772],{"class":84},"(() ",[32,774,596],{"class":76},[32,776,777],{"class":80}," print",[32,779,780],{"class":84},"(i));\n",[32,782,783],{"class":34,"line":214},[32,784,206],{"class":84},[32,786,787,790,793,796,798,801,804],{"class":34,"line":258},[32,788,789],{"class":84},"handlers.",[32,791,792],{"class":80},"forEach",[32,794,795],{"class":84},"((f) ",[32,797,596],{"class":76},[32,799,800],{"class":80}," f",[32,802,803],{"class":84},"());  ",[32,805,806],{"class":38},"\u002F\u002F 3, 3, 3 — all see the final value of i\n",[32,808,809],{"class":34,"line":283},[32,810,64],{"emptyLinePlaceholder":63},[32,812,813],{"class":34,"line":288},[32,814,815],{"class":38},"\u002F\u002F ✓ Correct: capture per-iteration in a final local.\n",[32,817,818,820,823,825,827,829,831,833],{"class":34,"line":294},[32,819,621],{"class":76},[32,821,822],{"class":84}," handlersFixed ",[32,824,160],{"class":76},[32,826,714],{"class":76},[32,828,717],{"class":91},[32,830,720],{"class":84},[32,832,723],{"class":76},[32,834,726],{"class":84},[32,836,837,839,841,843,845,847,849,851,853,855,857,859],{"class":34,"line":320},[32,838,731],{"class":76},[32,840,588],{"class":84},[32,842,621],{"class":76},[32,844,738],{"class":84},[32,846,160],{"class":76},[32,848,743],{"class":91},[32,850,746],{"class":84},[32,852,749],{"class":76},[32,854,752],{"class":91},[32,856,755],{"class":84},[32,858,758],{"class":76},[32,860,761],{"class":84},[32,862,863,865,868,870,873],{"class":34,"line":345},[32,864,504],{"class":76},[32,866,867],{"class":84}," j ",[32,869,160],{"class":76},[32,871,872],{"class":84}," i;  ",[32,874,875],{"class":38},"\u002F\u002F fresh, immutable per iteration\n",[32,877,878,881,883,885,887,889],{"class":34,"line":350},[32,879,880],{"class":84},"  handlersFixed.",[32,882,769],{"class":80},[32,884,772],{"class":84},[32,886,596],{"class":76},[32,888,777],{"class":80},[32,890,891],{"class":84},"(j));\n",[32,893,894],{"class":34,"line":356},[32,895,206],{"class":84},[32,897,898,901,903,905,907,909,911],{"class":34,"line":400},[32,899,900],{"class":84},"handlersFixed.",[32,902,792],{"class":80},[32,904,795],{"class":84},[32,906,596],{"class":76},[32,908,800],{"class":80},[32,910,803],{"class":84},[32,912,913],{"class":38},"\u002F\u002F 0, 1, 2\n",[32,915,916],{"class":34,"line":424},[32,917,64],{"emptyLinePlaceholder":63},[32,919,920],{"class":34,"line":429},[32,921,922],{"class":38},"\u002F\u002F Memory implication: closures keep captured variables alive (prevent GC).\n",[32,924,925],{"class":34,"line":435},[32,926,927],{"class":38},"\u002F\u002F A closure stored in a long-lived collection can extend a variable's lifetime\n",[32,929,930],{"class":34,"line":470},[32,931,932],{"class":38},"\u002F\u002F beyond its expected scope — be careful in long-running processes.\n",[14,934,936],{"id":935},"typedefs-function-types","Typedefs & Function Types",[19,938,939],{"language":21},[23,940,942],{"className":25,"code":941,"language":21,"meta":27,"style":27},"\u002F\u002F Typedefs name function types — use for callbacks, handlers, strategy patterns.\ntypedef Validator\u003CT> = String? Function(T value);  \u002F\u002F returns error message or null\n\n\u002F\u002F Generic function type:\ntypedef Mapper\u003CS, T> = T Function(S source);\n\n\u002F\u002F Using the typedef in APIs:\nclass FormField\u003CT> {\n  final Validator\u003CT> validator;\n  FormField(this.validator);\n\n  String? validate(T value) => validator(value);\n}\n\n\u002F\u002F Type-safe handler registration:\ntypedef EventHandler\u003CT extends Event> = void Function(T event);\n\nclass EventBus {\n  final _handlers = \u003CType, List\u003CFunction>>{};\n\n  void subscribe\u003CT extends Event>(EventHandler\u003CT> handler) {\n    (_handlers[T] ??= \u003CFunction>[]).add(handler);\n  }\n\n  void publish\u003CT extends Event>(T event) {\n    for (final h in _handlers[T] ?? []) {\n      (h as EventHandler\u003CT>)(event);\n  }\n  }\n}\n\n\u002F\u002F ❌ Anti-pattern: using `Function` (untyped) — accepts anything, no type safety.\nvoid registerCallback(Function fn) { ... }  \u002F\u002F any function signature accepted\n\n\u002F\u002F ✓ Correct: use a function type or typedef.\nvoid registerCallback(EventHandler\u003CClick> fn) { ... }  \u002F\u002F only the right signature\n",[29,943,944,949,983,987,992,1024,1028,1033,1048,1061,1074,1078,1102,1106,1110,1115,1148,1152,1162,1193,1197,1226,1253,1258,1262,1284,1312,1329,1333,1337,1341,1345,1350,1367,1371,1376],{"__ignoreMap":27},[32,945,946],{"class":34,"line":35},[32,947,948],{"class":38},"\u002F\u002F Typedefs name function types — use for callbacks, handlers, strategy patterns.\n",[32,950,951,954,957,959,962,965,967,969,971,973,975,977,980],{"class":34,"line":42},[32,952,953],{"class":76},"typedef",[32,955,956],{"class":91}," Validator",[32,958,749],{"class":84},[32,960,961],{"class":91},"T",[32,963,964],{"class":84},"> ",[32,966,160],{"class":76},[32,968,143],{"class":91},[32,970,122],{"class":76},[32,972,717],{"class":91},[32,974,220],{"class":84},[32,976,961],{"class":91},[32,978,979],{"class":84}," value);  ",[32,981,982],{"class":38},"\u002F\u002F returns error message or null\n",[32,984,985],{"class":34,"line":48},[32,986,64],{"emptyLinePlaceholder":63},[32,988,989],{"class":34,"line":54},[32,990,991],{"class":38},"\u002F\u002F Generic function type:\n",[32,993,994,996,999,1001,1004,1006,1008,1010,1012,1015,1017,1019,1021],{"class":34,"line":60},[32,995,953],{"class":76},[32,997,998],{"class":91}," Mapper",[32,1000,749],{"class":84},[32,1002,1003],{"class":91},"S",[32,1005,227],{"class":84},[32,1007,961],{"class":91},[32,1009,964],{"class":84},[32,1011,160],{"class":76},[32,1013,1014],{"class":91}," T",[32,1016,717],{"class":91},[32,1018,220],{"class":84},[32,1020,1003],{"class":91},[32,1022,1023],{"class":84}," source);\n",[32,1025,1026],{"class":34,"line":67},[32,1027,64],{"emptyLinePlaceholder":63},[32,1029,1030],{"class":34,"line":73},[32,1031,1032],{"class":38},"\u002F\u002F Using the typedef in APIs:\n",[32,1034,1035,1038,1041,1043,1045],{"class":34,"line":88},[32,1036,1037],{"class":76},"class",[32,1039,1040],{"class":91}," FormField",[32,1042,749],{"class":84},[32,1044,961],{"class":91},[32,1046,1047],{"class":84},"> {\n",[32,1049,1050,1052,1054,1056,1058],{"class":34,"line":101},[32,1051,504],{"class":76},[32,1053,956],{"class":91},[32,1055,749],{"class":84},[32,1057,961],{"class":91},[32,1059,1060],{"class":84},"> validator;\n",[32,1062,1063,1066,1068,1071],{"class":34,"line":113},[32,1064,1065],{"class":91},"  FormField",[32,1067,220],{"class":84},[32,1069,1070],{"class":91},"this",[32,1072,1073],{"class":84},".validator);\n",[32,1075,1076],{"class":34,"line":131},[32,1077,64],{"emptyLinePlaceholder":63},[32,1079,1080,1082,1084,1087,1089,1091,1094,1096,1099],{"class":34,"line":137},[32,1081,92],{"class":91},[32,1083,122],{"class":76},[32,1085,1086],{"class":80}," validate",[32,1088,220],{"class":84},[32,1090,961],{"class":91},[32,1092,1093],{"class":84}," value) ",[32,1095,596],{"class":76},[32,1097,1098],{"class":80}," validator",[32,1100,1101],{"class":84},"(value);\n",[32,1103,1104],{"class":34,"line":152},[32,1105,206],{"class":84},[32,1107,1108],{"class":34,"line":172},[32,1109,64],{"emptyLinePlaceholder":63},[32,1111,1112],{"class":34,"line":191},[32,1113,1114],{"class":38},"\u002F\u002F Type-safe handler registration:\n",[32,1116,1117,1119,1122,1124,1126,1129,1132,1134,1136,1139,1141,1143,1145],{"class":34,"line":197},[32,1118,953],{"class":76},[32,1120,1121],{"class":91}," EventHandler",[32,1123,749],{"class":84},[32,1125,961],{"class":91},[32,1127,1128],{"class":76}," extends",[32,1130,1131],{"class":91}," Event",[32,1133,964],{"class":84},[32,1135,160],{"class":76},[32,1137,1138],{"class":76}," void",[32,1140,717],{"class":91},[32,1142,220],{"class":84},[32,1144,961],{"class":91},[32,1146,1147],{"class":84}," event);\n",[32,1149,1150],{"class":34,"line":203},[32,1151,64],{"emptyLinePlaceholder":63},[32,1153,1154,1156,1159],{"class":34,"line":209},[32,1155,1037],{"class":76},[32,1157,1158],{"class":91}," EventBus",[32,1160,1161],{"class":84}," {\n",[32,1163,1164,1166,1169,1171,1174,1177,1179,1182,1184,1186,1188,1190],{"class":34,"line":214},[32,1165,504],{"class":76},[32,1167,1168],{"class":84}," _handlers ",[32,1170,160],{"class":76},[32,1172,1173],{"class":76}," \u003C",[32,1175,1176],{"class":91},"Type",[32,1178,227],{"class":84},[32,1180,1181],{"class":91},"List",[32,1183,749],{"class":84},[32,1185,569],{"class":91},[32,1187,723],{"class":84},[32,1189,723],{"class":76},[32,1191,1192],{"class":84},"{};\n",[32,1194,1195],{"class":34,"line":258},[32,1196,64],{"emptyLinePlaceholder":63},[32,1198,1199,1202,1205,1207,1209,1211,1213,1216,1219,1221,1223],{"class":34,"line":283},[32,1200,1201],{"class":76},"  void",[32,1203,1204],{"class":80}," subscribe",[32,1206,749],{"class":84},[32,1208,961],{"class":91},[32,1210,1128],{"class":76},[32,1212,1131],{"class":91},[32,1214,1215],{"class":84},">(",[32,1217,1218],{"class":91},"EventHandler",[32,1220,749],{"class":84},[32,1222,961],{"class":91},[32,1224,1225],{"class":84},"> handler) {\n",[32,1227,1228,1231,1233,1236,1239,1241,1243,1245,1248,1250],{"class":34,"line":288},[32,1229,1230],{"class":84},"    (_handlers[",[32,1232,961],{"class":91},[32,1234,1235],{"class":84},"] ",[32,1237,1238],{"class":76},"??=",[32,1240,1173],{"class":76},[32,1242,569],{"class":91},[32,1244,723],{"class":76},[32,1246,1247],{"class":84},"[]).",[32,1249,769],{"class":80},[32,1251,1252],{"class":84},"(handler);\n",[32,1254,1255],{"class":34,"line":294},[32,1256,1257],{"class":84},"  }\n",[32,1259,1260],{"class":34,"line":320},[32,1261,64],{"emptyLinePlaceholder":63},[32,1263,1264,1266,1269,1271,1273,1275,1277,1279,1281],{"class":34,"line":345},[32,1265,1201],{"class":76},[32,1267,1268],{"class":80}," publish",[32,1270,749],{"class":84},[32,1272,961],{"class":91},[32,1274,1128],{"class":76},[32,1276,1131],{"class":91},[32,1278,1215],{"class":84},[32,1280,961],{"class":91},[32,1282,1283],{"class":84}," event) {\n",[32,1285,1286,1289,1291,1294,1297,1300,1303,1305,1307,1309],{"class":34,"line":350},[32,1287,1288],{"class":76},"    for",[32,1290,588],{"class":84},[32,1292,1293],{"class":76},"final",[32,1295,1296],{"class":84}," h ",[32,1298,1299],{"class":76},"in",[32,1301,1302],{"class":84}," _handlers[",[32,1304,961],{"class":91},[32,1306,1235],{"class":84},[32,1308,515],{"class":76},[32,1310,1311],{"class":84}," []) {\n",[32,1313,1314,1317,1320,1322,1324,1326],{"class":34,"line":356},[32,1315,1316],{"class":84},"      (h ",[32,1318,1319],{"class":76},"as",[32,1321,1121],{"class":91},[32,1323,749],{"class":84},[32,1325,961],{"class":91},[32,1327,1328],{"class":84},">)(event);\n",[32,1330,1331],{"class":34,"line":400},[32,1332,1257],{"class":84},[32,1334,1335],{"class":34,"line":424},[32,1336,1257],{"class":84},[32,1338,1339],{"class":34,"line":429},[32,1340,206],{"class":84},[32,1342,1343],{"class":34,"line":435},[32,1344,64],{"emptyLinePlaceholder":63},[32,1346,1347],{"class":34,"line":470},[32,1348,1349],{"class":38},"\u002F\u002F ❌ Anti-pattern: using `Function` (untyped) — accepts anything, no type safety.\n",[32,1351,1352,1354,1357,1359,1361,1364],{"class":34,"line":479},[32,1353,77],{"class":76},[32,1355,1356],{"class":80}," registerCallback",[32,1358,220],{"class":84},[32,1360,569],{"class":91},[32,1362,1363],{"class":84}," fn) { ... }  ",[32,1365,1366],{"class":38},"\u002F\u002F any function signature accepted\n",[32,1368,1369],{"class":34,"line":485},[32,1370,64],{"emptyLinePlaceholder":63},[32,1372,1373],{"class":34,"line":501},[32,1374,1375],{"class":38},"\u002F\u002F ✓ Correct: use a function type or typedef.\n",[32,1377,1378,1380,1382,1384,1386,1388,1391,1394],{"class":34,"line":527},[32,1379,77],{"class":76},[32,1381,1356],{"class":80},[32,1383,220],{"class":84},[32,1385,1218],{"class":91},[32,1387,749],{"class":84},[32,1389,1390],{"class":91},"Click",[32,1392,1393],{"class":84},"> fn) { ... }  ",[32,1395,1396],{"class":38},"\u002F\u002F only the right signature\n",[14,1398,1400,1401,1404,1405],{"id":1399},"generators-sync-and-async","Generators — ",[29,1402,1403],{},"sync*"," and ",[29,1406,1407],{},"async*",[19,1409,1410],{"language":21},[23,1411,1413],{"className":25,"code":1412,"language":21,"meta":27,"style":27},"\u002F\u002F sync* returns a lazy Iterable — values produced on demand (pull-based).\n\u002F\u002F The generator suspends at each `yield` and resumes when the next value is requested.\nIterable\u003Cint> fibonacci() sync* {\n  var a = 0, b = 1;\n  while (true) {\n    yield a;          \u002F\u002F suspend here, resume on next iteration\n    final next = a + b;\n    a = b;\n    b = next;\n  }\n}\n\n\u002F\u002F Take only what you need — infinite sequence, finite consumption:\nprint(fibonacci().take(10).toList());  \u002F\u002F [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]\n\u002F\u002F `.take(10)` pulls 10 values; the generator never runs beyond that.\n\n\u002F\u002F yield* delegates to another generator (flattens):\nIterable\u003Cint> naturals(int n) sync* {\n  yield* List.generate(n, (i) => i + 1);  \u002F\u002F yields all elements of the iterable\n}\n\n\u002F\u002F async* returns a lazy Stream — values produced over time (push-based).\n\u002F\u002F Each `yield` emits to the listener; the generator suspends until the\n\u002F\u002F listener requests more (single-subscription) or the stream is listened to.\nStream\u003Cint> timedCounter(int max, Duration interval) async* {\n  for (var i = 1; i \u003C= max; i++) {\n    await Future.delayed(interval);  \u002F\u002F async pause between emissions\n    yield i;  \u002F\u002F emit value to listener\n  }\n}\n\n\u002F\u002F Consuming:\nvoid main() async {\n  await for (final n in timedCounter(5, Duration(seconds: 1))) {\n    print(n);  \u002F\u002F 1 (after 1s), 2 (after 2s), ..., 5 (after 5s)\n  }\n}\n\n\u002F\u002F yield* with async* delegates to another stream:\nStream\u003Cint> mergedStream() async* {\n  yield* timedCounter(3, Duration(seconds: 1));  \u002F\u002F emits 1, 2, 3\n  yield* timedCounter(3, Duration(seconds: 2));  \u002F\u002F then emits 1, 2, 3 (slower)\n}\n",[29,1414,1415,1420,1425,1446,1469,1480,1491,1508,1517,1527,1531,1535,1539,1544,1573,1578,1582,1587,1611,1641,1645,1649,1654,1659,1664,1694,1721,1740,1749,1753,1757,1761,1766,1780,1817,1828,1832,1837,1842,1848,1868,1894,1921],{"__ignoreMap":27},[32,1416,1417],{"class":34,"line":35},[32,1418,1419],{"class":38},"\u002F\u002F sync* returns a lazy Iterable — values produced on demand (pull-based).\n",[32,1421,1422],{"class":34,"line":42},[32,1423,1424],{"class":38},"\u002F\u002F The generator suspends at each `yield` and resumes when the next value is requested.\n",[32,1426,1427,1430,1432,1434,1436,1439,1442,1444],{"class":34,"line":48},[32,1428,1429],{"class":91},"Iterable",[32,1431,749],{"class":84},[32,1433,577],{"class":91},[32,1435,964],{"class":84},[32,1437,1438],{"class":80},"fibonacci",[32,1440,1441],{"class":84},"() ",[32,1443,1403],{"class":76},[32,1445,1161],{"class":84},[32,1447,1448,1451,1454,1456,1458,1461,1463,1466],{"class":34,"line":54},[32,1449,1450],{"class":76},"  var",[32,1452,1453],{"class":84}," a ",[32,1455,160],{"class":76},[32,1457,743],{"class":91},[32,1459,1460],{"class":84},", b ",[32,1462,160],{"class":76},[32,1464,1465],{"class":91}," 1",[32,1467,1468],{"class":84},";\n",[32,1470,1471,1474,1476,1478],{"class":34,"line":60},[32,1472,1473],{"class":76},"  while",[32,1475,588],{"class":84},[32,1477,328],{"class":91},[32,1479,761],{"class":84},[32,1481,1482,1485,1488],{"class":34,"line":67},[32,1483,1484],{"class":76},"    yield",[32,1486,1487],{"class":84}," a;          ",[32,1489,1490],{"class":38},"\u002F\u002F suspend here, resume on next iteration\n",[32,1492,1493,1496,1499,1501,1503,1505],{"class":34,"line":73},[32,1494,1495],{"class":76},"    final",[32,1497,1498],{"class":84}," next ",[32,1500,160],{"class":76},[32,1502,1453],{"class":84},[32,1504,602],{"class":76},[32,1506,1507],{"class":84}," b;\n",[32,1509,1510,1513,1515],{"class":34,"line":88},[32,1511,1512],{"class":84},"    a ",[32,1514,160],{"class":76},[32,1516,1507],{"class":84},[32,1518,1519,1522,1524],{"class":34,"line":101},[32,1520,1521],{"class":84},"    b ",[32,1523,160],{"class":76},[32,1525,1526],{"class":84}," next;\n",[32,1528,1529],{"class":34,"line":113},[32,1530,1257],{"class":84},[32,1532,1533],{"class":34,"line":131},[32,1534,206],{"class":84},[32,1536,1537],{"class":34,"line":137},[32,1538,64],{"emptyLinePlaceholder":63},[32,1540,1541],{"class":34,"line":152},[32,1542,1543],{"class":38},"\u002F\u002F Take only what you need — infinite sequence, finite consumption:\n",[32,1545,1546,1548,1550,1552,1555,1558,1560,1562,1565,1568,1570],{"class":34,"line":172},[32,1547,658],{"class":80},[32,1549,220],{"class":84},[32,1551,1438],{"class":80},[32,1553,1554],{"class":84},"().",[32,1556,1557],{"class":80},"take",[32,1559,220],{"class":84},[32,1561,651],{"class":91},[32,1563,1564],{"class":84},").",[32,1566,1567],{"class":80},"toList",[32,1569,803],{"class":84},[32,1571,1572],{"class":38},"\u002F\u002F [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]\n",[32,1574,1575],{"class":34,"line":191},[32,1576,1577],{"class":38},"\u002F\u002F `.take(10)` pulls 10 values; the generator never runs beyond that.\n",[32,1579,1580],{"class":34,"line":197},[32,1581,64],{"emptyLinePlaceholder":63},[32,1583,1584],{"class":34,"line":203},[32,1585,1586],{"class":38},"\u002F\u002F yield* delegates to another generator (flattens):\n",[32,1588,1589,1591,1593,1595,1597,1600,1602,1604,1607,1609],{"class":34,"line":209},[32,1590,1429],{"class":91},[32,1592,749],{"class":84},[32,1594,577],{"class":91},[32,1596,964],{"class":84},[32,1598,1599],{"class":80},"naturals",[32,1601,220],{"class":84},[32,1603,577],{"class":91},[32,1605,1606],{"class":84}," n) ",[32,1608,1403],{"class":76},[32,1610,1161],{"class":84},[32,1612,1613,1616,1619,1622,1625,1628,1630,1632,1634,1636,1638],{"class":34,"line":214},[32,1614,1615],{"class":76},"  yield*",[32,1617,1618],{"class":91}," List",[32,1620,1621],{"class":84},".",[32,1623,1624],{"class":80},"generate",[32,1626,1627],{"class":84},"(n, (i) ",[32,1629,596],{"class":76},[32,1631,738],{"class":84},[32,1633,602],{"class":76},[32,1635,1465],{"class":91},[32,1637,277],{"class":84},[32,1639,1640],{"class":38},"\u002F\u002F yields all elements of the iterable\n",[32,1642,1643],{"class":34,"line":258},[32,1644,206],{"class":84},[32,1646,1647],{"class":34,"line":283},[32,1648,64],{"emptyLinePlaceholder":63},[32,1650,1651],{"class":34,"line":288},[32,1652,1653],{"class":38},"\u002F\u002F async* returns a lazy Stream — values produced over time (push-based).\n",[32,1655,1656],{"class":34,"line":294},[32,1657,1658],{"class":38},"\u002F\u002F Each `yield` emits to the listener; the generator suspends until the\n",[32,1660,1661],{"class":34,"line":320},[32,1662,1663],{"class":38},"\u002F\u002F listener requests more (single-subscription) or the stream is listened to.\n",[32,1665,1666,1669,1671,1673,1675,1678,1680,1682,1685,1687,1690,1692],{"class":34,"line":345},[32,1667,1668],{"class":91},"Stream",[32,1670,749],{"class":84},[32,1672,577],{"class":91},[32,1674,964],{"class":84},[32,1676,1677],{"class":80},"timedCounter",[32,1679,220],{"class":84},[32,1681,577],{"class":91},[32,1683,1684],{"class":84}," max, ",[32,1686,445],{"class":91},[32,1688,1689],{"class":84}," interval) ",[32,1691,1407],{"class":76},[32,1693,1161],{"class":84},[32,1695,1696,1699,1701,1703,1705,1707,1709,1711,1714,1717,1719],{"class":34,"line":350},[32,1697,1698],{"class":76},"  for",[32,1700,588],{"class":84},[32,1702,621],{"class":76},[32,1704,738],{"class":84},[32,1706,160],{"class":76},[32,1708,1465],{"class":91},[32,1710,746],{"class":84},[32,1712,1713],{"class":76},"\u003C=",[32,1715,1716],{"class":84}," max; i",[32,1718,758],{"class":76},[32,1720,761],{"class":84},[32,1722,1723,1726,1729,1731,1734,1737],{"class":34,"line":356},[32,1724,1725],{"class":76},"    await",[32,1727,1728],{"class":91}," Future",[32,1730,1621],{"class":84},[32,1732,1733],{"class":80},"delayed",[32,1735,1736],{"class":84},"(interval);  ",[32,1738,1739],{"class":38},"\u002F\u002F async pause between emissions\n",[32,1741,1742,1744,1746],{"class":34,"line":400},[32,1743,1484],{"class":76},[32,1745,872],{"class":84},[32,1747,1748],{"class":38},"\u002F\u002F emit value to listener\n",[32,1750,1751],{"class":34,"line":424},[32,1752,1257],{"class":84},[32,1754,1755],{"class":34,"line":429},[32,1756,206],{"class":84},[32,1758,1759],{"class":34,"line":435},[32,1760,64],{"emptyLinePlaceholder":63},[32,1762,1763],{"class":34,"line":470},[32,1764,1765],{"class":38},"\u002F\u002F Consuming:\n",[32,1767,1768,1770,1773,1775,1778],{"class":34,"line":479},[32,1769,77],{"class":76},[32,1771,1772],{"class":80}," main",[32,1774,1441],{"class":84},[32,1776,1777],{"class":76},"async",[32,1779,1161],{"class":84},[32,1781,1782,1785,1788,1790,1792,1795,1797,1800,1802,1804,1806,1808,1810,1812,1814],{"class":34,"line":485},[32,1783,1784],{"class":76},"  await",[32,1786,1787],{"class":76}," for",[32,1789,588],{"class":84},[32,1791,1293],{"class":76},[32,1793,1794],{"class":84}," n ",[32,1796,1299],{"class":76},[32,1798,1799],{"class":80}," timedCounter",[32,1801,220],{"class":84},[32,1803,633],{"class":91},[32,1805,227],{"class":84},[32,1807,445],{"class":91},[32,1809,459],{"class":84},[32,1811,241],{"class":76},[32,1813,1465],{"class":91},[32,1815,1816],{"class":84},"))) {\n",[32,1818,1819,1822,1825],{"class":34,"line":501},[32,1820,1821],{"class":80},"    print",[32,1823,1824],{"class":84},"(n);  ",[32,1826,1827],{"class":38},"\u002F\u002F 1 (after 1s), 2 (after 2s), ..., 5 (after 5s)\n",[32,1829,1830],{"class":34,"line":527},[32,1831,1257],{"class":84},[32,1833,1835],{"class":34,"line":1834},37,[32,1836,206],{"class":84},[32,1838,1840],{"class":34,"line":1839},38,[32,1841,64],{"emptyLinePlaceholder":63},[32,1843,1845],{"class":34,"line":1844},39,[32,1846,1847],{"class":38},"\u002F\u002F yield* with async* delegates to another stream:\n",[32,1849,1851,1853,1855,1857,1859,1862,1864,1866],{"class":34,"line":1850},40,[32,1852,1668],{"class":91},[32,1854,749],{"class":84},[32,1856,577],{"class":91},[32,1858,964],{"class":84},[32,1860,1861],{"class":80},"mergedStream",[32,1863,1441],{"class":84},[32,1865,1407],{"class":76},[32,1867,1161],{"class":84},[32,1869,1871,1873,1875,1877,1879,1881,1883,1885,1887,1889,1891],{"class":34,"line":1870},41,[32,1872,1615],{"class":76},[32,1874,1799],{"class":80},[32,1876,220],{"class":84},[32,1878,668],{"class":91},[32,1880,227],{"class":84},[32,1882,445],{"class":91},[32,1884,459],{"class":84},[32,1886,241],{"class":76},[32,1888,1465],{"class":91},[32,1890,690],{"class":84},[32,1892,1893],{"class":38},"\u002F\u002F emits 1, 2, 3\n",[32,1895,1897,1899,1901,1903,1905,1907,1909,1911,1913,1916,1918],{"class":34,"line":1896},42,[32,1898,1615],{"class":76},[32,1900,1799],{"class":80},[32,1902,220],{"class":84},[32,1904,668],{"class":91},[32,1906,227],{"class":84},[32,1908,445],{"class":91},[32,1910,459],{"class":84},[32,1912,241],{"class":76},[32,1914,1915],{"class":91}," 2",[32,1917,690],{"class":84},[32,1919,1920],{"class":38},"\u002F\u002F then emits 1, 2, 3 (slower)\n",[32,1922,1924],{"class":34,"line":1923},43,[32,1925,206],{"class":84},[14,1927,1929,1930,1933],{"id":1928},"callable-classes-call-method","Callable Classes — ",[29,1931,1932],{},"call()"," Method",[19,1935,1936],{"language":21},[23,1937,1939],{"className":25,"code":1938,"language":21,"meta":27,"style":27},"\u002F\u002F A class with a `call()` method can be invoked like a function.\n\u002F\u002F This enables objects that are also functions — useful for validators,\n\u002F\u002F comparators, state machines, and DSLs.\n\nclass Validator {\n  final List\u003CString? Function(String)> _rules;\n  Validator(this._rules);\n\n  \u002F\u002F `call` allows `validator(value)` syntax — invokes this method.\n  String? call(String value) {\n    for (final rule in _rules) {\n      final error = rule(value);\n      if (error != null) return error;\n    }\n    return null;\n  }\n\n  \u002F\u002F Compose validators with operator overloading:\n  Validator operator +(Validator other) => Validator([..._rules, ...other._rules]);\n}\n\nfinal emailValidator = Validator([\n  (s) => s.isEmpty ? 'Required' : null,\n  (s) => !s.contains('@') ? 'Invalid email' : null,\n]);\n\n\u002F\u002F Called like a function (invokes `call`):\nprint(emailValidator('test@example.com'));  \u002F\u002F null (valid)\nprint(emailValidator(''));                   \u002F\u002F 'Required'\nprint(emailValidator('no-at-sign'));         \u002F\u002F 'Invalid email'\n\n\u002F\u002F Use case: comparator objects for sort:\nclass ByLength {\n  int call(String a, String b) => a.length.compareTo(b.length);\n}\nvar words = ['banana', 'hi', 'cherry'];\nwords.sort(ByLength());  \u002F\u002F sort by length: ['hi', 'banana', 'cherry']\n",[29,1940,1941,1946,1951,1956,1960,1968,1990,2002,2006,2011,2027,2043,2058,2081,2086,2095,2099,2103,2108,2133,2137,2141,2155,2178,2211,2216,2220,2225,2244,2263,2282,2286,2291,2300,2329,2333,2361],{"__ignoreMap":27},[32,1942,1943],{"class":34,"line":35},[32,1944,1945],{"class":38},"\u002F\u002F A class with a `call()` method can be invoked like a function.\n",[32,1947,1948],{"class":34,"line":42},[32,1949,1950],{"class":38},"\u002F\u002F This enables objects that are also functions — useful for validators,\n",[32,1952,1953],{"class":34,"line":48},[32,1954,1955],{"class":38},"\u002F\u002F comparators, state machines, and DSLs.\n",[32,1957,1958],{"class":34,"line":54},[32,1959,64],{"emptyLinePlaceholder":63},[32,1961,1962,1964,1966],{"class":34,"line":60},[32,1963,1037],{"class":76},[32,1965,956],{"class":91},[32,1967,1161],{"class":84},[32,1969,1970,1972,1974,1976,1978,1981,1983,1985,1987],{"class":34,"line":67},[32,1971,504],{"class":76},[32,1973,1618],{"class":91},[32,1975,749],{"class":84},[32,1977,119],{"class":91},[32,1979,1980],{"class":84},"? ",[32,1982,569],{"class":91},[32,1984,220],{"class":84},[32,1986,119],{"class":91},[32,1988,1989],{"class":84},")> _rules;\n",[32,1991,1992,1995,1997,1999],{"class":34,"line":73},[32,1993,1994],{"class":91},"  Validator",[32,1996,220],{"class":84},[32,1998,1070],{"class":91},[32,2000,2001],{"class":84},"._rules);\n",[32,2003,2004],{"class":34,"line":88},[32,2005,64],{"emptyLinePlaceholder":63},[32,2007,2008],{"class":34,"line":101},[32,2009,2010],{"class":38},"  \u002F\u002F `call` allows `validator(value)` syntax — invokes this method.\n",[32,2012,2013,2015,2017,2020,2022,2024],{"class":34,"line":113},[32,2014,92],{"class":91},[32,2016,122],{"class":76},[32,2018,2019],{"class":80}," call",[32,2021,220],{"class":84},[32,2023,119],{"class":91},[32,2025,2026],{"class":84}," value) {\n",[32,2028,2029,2031,2033,2035,2038,2040],{"class":34,"line":131},[32,2030,1288],{"class":76},[32,2032,588],{"class":84},[32,2034,1293],{"class":76},[32,2036,2037],{"class":84}," rule ",[32,2039,1299],{"class":76},[32,2041,2042],{"class":84}," _rules) {\n",[32,2044,2045,2048,2051,2053,2056],{"class":34,"line":137},[32,2046,2047],{"class":76},"      final",[32,2049,2050],{"class":84}," error ",[32,2052,160],{"class":76},[32,2054,2055],{"class":80}," rule",[32,2057,1101],{"class":84},[32,2059,2060,2063,2066,2069,2072,2075,2078],{"class":34,"line":152},[32,2061,2062],{"class":76},"      if",[32,2064,2065],{"class":84}," (error ",[32,2067,2068],{"class":76},"!=",[32,2070,2071],{"class":91}," null",[32,2073,2074],{"class":84},") ",[32,2076,2077],{"class":76},"return",[32,2079,2080],{"class":84}," error;\n",[32,2082,2083],{"class":34,"line":172},[32,2084,2085],{"class":84},"    }\n",[32,2087,2088,2091,2093],{"class":34,"line":191},[32,2089,2090],{"class":76},"    return",[32,2092,2071],{"class":91},[32,2094,1468],{"class":84},[32,2096,2097],{"class":34,"line":197},[32,2098,1257],{"class":84},[32,2100,2101],{"class":34,"line":203},[32,2102,64],{"emptyLinePlaceholder":63},[32,2104,2105],{"class":34,"line":209},[32,2106,2107],{"class":38},"  \u002F\u002F Compose validators with operator overloading:\n",[32,2109,2110,2112,2115,2118,2120,2123,2126,2128,2130],{"class":34,"line":214},[32,2111,1994],{"class":91},[32,2113,2114],{"class":76}," operator",[32,2116,2117],{"class":76}," +",[32,2119,220],{"class":84},[32,2121,2122],{"class":91},"Validator",[32,2124,2125],{"class":84}," other) ",[32,2127,596],{"class":76},[32,2129,956],{"class":91},[32,2131,2132],{"class":84},"([..._rules, ...other._rules]);\n",[32,2134,2135],{"class":34,"line":258},[32,2136,206],{"class":84},[32,2138,2139],{"class":34,"line":283},[32,2140,64],{"emptyLinePlaceholder":63},[32,2142,2143,2145,2148,2150,2152],{"class":34,"line":288},[32,2144,1293],{"class":76},[32,2146,2147],{"class":84}," emailValidator ",[32,2149,160],{"class":76},[32,2151,956],{"class":91},[32,2153,2154],{"class":84},"([\n",[32,2156,2157,2160,2162,2165,2167,2170,2173,2175],{"class":34,"line":294},[32,2158,2159],{"class":84},"  (s) ",[32,2161,596],{"class":76},[32,2163,2164],{"class":84}," s.isEmpty ",[32,2166,122],{"class":76},[32,2168,2169],{"class":223}," 'Required'",[32,2171,2172],{"class":76}," :",[32,2174,2071],{"class":91},[32,2176,2177],{"class":84},",\n",[32,2179,2180,2182,2184,2187,2190,2193,2195,2198,2200,2202,2205,2207,2209],{"class":34,"line":320},[32,2181,2159],{"class":84},[32,2183,596],{"class":76},[32,2185,2186],{"class":76}," !",[32,2188,2189],{"class":84},"s.",[32,2191,2192],{"class":80},"contains",[32,2194,220],{"class":84},[32,2196,2197],{"class":223},"'@'",[32,2199,2074],{"class":84},[32,2201,122],{"class":76},[32,2203,2204],{"class":223}," 'Invalid email'",[32,2206,2172],{"class":76},[32,2208,2071],{"class":91},[32,2210,2177],{"class":84},[32,2212,2213],{"class":34,"line":345},[32,2214,2215],{"class":84},"]);\n",[32,2217,2218],{"class":34,"line":350},[32,2219,64],{"emptyLinePlaceholder":63},[32,2221,2222],{"class":34,"line":356},[32,2223,2224],{"class":38},"\u002F\u002F Called like a function (invokes `call`):\n",[32,2226,2227,2229,2231,2234,2236,2239,2241],{"class":34,"line":400},[32,2228,658],{"class":80},[32,2230,220],{"class":84},[32,2232,2233],{"class":80},"emailValidator",[32,2235,220],{"class":84},[32,2237,2238],{"class":223},"'test@example.com'",[32,2240,690],{"class":84},[32,2242,2243],{"class":38},"\u002F\u002F null (valid)\n",[32,2245,2246,2248,2250,2252,2254,2257,2260],{"class":34,"line":424},[32,2247,658],{"class":80},[32,2249,220],{"class":84},[32,2251,2233],{"class":80},[32,2253,220],{"class":84},[32,2255,2256],{"class":223},"''",[32,2258,2259],{"class":84},"));                   ",[32,2261,2262],{"class":38},"\u002F\u002F 'Required'\n",[32,2264,2265,2267,2269,2271,2273,2276,2279],{"class":34,"line":429},[32,2266,658],{"class":80},[32,2268,220],{"class":84},[32,2270,2233],{"class":80},[32,2272,220],{"class":84},[32,2274,2275],{"class":223},"'no-at-sign'",[32,2277,2278],{"class":84},"));         ",[32,2280,2281],{"class":38},"\u002F\u002F 'Invalid email'\n",[32,2283,2284],{"class":34,"line":435},[32,2285,64],{"emptyLinePlaceholder":63},[32,2287,2288],{"class":34,"line":470},[32,2289,2290],{"class":38},"\u002F\u002F Use case: comparator objects for sort:\n",[32,2292,2293,2295,2298],{"class":34,"line":479},[32,2294,1037],{"class":76},[32,2296,2297],{"class":91}," ByLength",[32,2299,1161],{"class":84},[32,2301,2302,2304,2306,2308,2310,2313,2315,2318,2320,2323,2326],{"class":34,"line":485},[32,2303,104],{"class":91},[32,2305,2019],{"class":80},[32,2307,220],{"class":84},[32,2309,119],{"class":91},[32,2311,2312],{"class":84}," a, ",[32,2314,119],{"class":91},[32,2316,2317],{"class":84}," b) ",[32,2319,596],{"class":76},[32,2321,2322],{"class":84}," a.length.",[32,2324,2325],{"class":80},"compareTo",[32,2327,2328],{"class":84},"(b.length);\n",[32,2330,2331],{"class":34,"line":501},[32,2332,206],{"class":84},[32,2334,2335,2337,2340,2342,2345,2348,2350,2353,2355,2358],{"class":34,"line":527},[32,2336,621],{"class":76},[32,2338,2339],{"class":84}," words ",[32,2341,160],{"class":76},[32,2343,2344],{"class":84}," [",[32,2346,2347],{"class":223},"'banana'",[32,2349,227],{"class":84},[32,2351,2352],{"class":223},"'hi'",[32,2354,227],{"class":84},[32,2356,2357],{"class":223},"'cherry'",[32,2359,2360],{"class":84},"];\n",[32,2362,2363,2366,2369,2371,2374,2376],{"class":34,"line":1834},[32,2364,2365],{"class":84},"words.",[32,2367,2368],{"class":80},"sort",[32,2370,220],{"class":84},[32,2372,2373],{"class":91},"ByLength",[32,2375,803],{"class":84},[32,2377,2378],{"class":38},"\u002F\u002F sort by length: ['hi', 'banana', 'cherry']\n",[14,2380,2382],{"id":2381},"tips-tricks","💡 Tips & Tricks",[2384,2385,2386,2405,2416,2427,2442],"ul",{},[2387,2388,2389,2393,2394,2397,2398,2401,2402,1621],"li",{},[2390,2391,2392],"strong",{},"Idiom",": use ",[29,2395,2396],{},"required"," named parameters for mandatory arguments — ",[29,2399,2400],{},"{required String apiKey}"," ensures the caller provides it with a clear compile error if missing. Named parameters self-document at the call site: ",[29,2403,2404],{},"createClient(apiKey: '...', timeout: 30)",[2387,2406,2407,2393,2409,2411,2412,2415],{},[2390,2408,2392],{},[29,2410,1403],{}," generators for lazy sequences — ",[29,2413,2414],{},"Iterable\u003Cint> gen() sync* { for (...) yield i; }"," produces values on demand. Zero allocation until iterated. Use for infinite sequences, large computed ranges, and pull-based pipelines.",[2387,2417,2418,2393,2420,2422,2423,2426],{},[2390,2419,2392],{},[29,2421,1407],{}," for time-series streams — ",[29,2424,2425],{},"Stream\u003CT> events() async* { while (...) { await wait; yield event; } }"," produces values over time. Use for polling, sensor data, and push-based pipelines.",[2387,2428,2429,2393,2431,2433,2434,2437,2438,2441],{},[2390,2430,2392],{},[29,2432,953],{}," for function types in public APIs — ",[29,2435,2436],{},"typedef Validator\u003CT> = String? Function(T value)"," is clearer than ",[29,2439,2440],{},"String? Function(T)"," repeated everywhere. Enables generic function types in signatures.",[2387,2443,2444,2393,2446,2448,2449,2452,2453,2456],{},[2390,2445,2392],{},[29,2447,1932],{}," for callable domain objects — ",[29,2450,2451],{},"validator(value)"," is cleaner than ",[29,2454,2455],{},"validator.validate(value)",". Use for validators, comparators, strategy objects that are \"functions with state.\"",[14,2458,2460],{"id":2459},"️-edge-cases-gotchas","⚠️ Edge Cases & Gotchas",[2384,2462,2463,2481,2496,2512,2530,2550,2579,2596,2612,2628],{},[2387,2464,2465,2472,2473,2476,2477,2480],{},[2390,2466,2467,2468,2471],{},"Optional positional params (",[29,2469,2470],{},"[...]",") must come after required",": ",[29,2474,2475],{},"void f(int a, [int b])"," is valid; ",[29,2478,2479],{},"void f([int b], int a)"," is a compile error.",[2387,2482,2483,2472,2490,2476,2493,2480],{},[2390,2484,2485,2486,2489],{},"Named params (",[29,2487,2488],{},"{...}",") must come after all positional params",[29,2491,2492],{},"void f(int a, {int b})",[29,2494,2495],{},"void f({int b}, int a)",[2387,2497,2498,2472,2501,2504,2505,2508,2509,2511],{},[2390,2499,2500],{},"Default values must be compile-time constants",[29,2502,2503],{},"void f({int x = someRuntimeVar})"," fails. Use ",[29,2506,2507],{},"null"," default + ",[29,2510,515],{}," inside for runtime defaults.",[2387,2513,2514,2472,2519,2522,2523,2526,2527,2529],{},[2390,2515,2516,2518],{},[29,2517,569],{}," type is untyped",[29,2520,2521],{},"Function fn"," accepts any function signature — no type safety. Use ",[29,2524,2525],{},"void Function(int)"," or a ",[29,2528,953],{}," instead.",[2387,2531,2532,2535,2536,2539,2540,2542,2543,2546,2547,1621],{},[2390,2533,2534],{},"Closures capture by reference, not value",": the captured variable is shared. ",[29,2537,2538],{},"var i = 0; var f = () => i; i = 5; f()"," returns ",[29,2541,633],{},", not ",[29,2544,2545],{},"0",". For per-iteration capture, use ",[29,2548,2549],{},"final captured = i;",[2387,2551,2552,2472,2560,2539,2563,2542,2566,2568,2569,2571,2572,2574,2575,2578],{},[2390,2553,2554,2556,2557],{},[29,2555,1777],{}," functions return ",[29,2558,2559],{},"Future",[29,2561,2562],{},"int f() async { return 5; }",[29,2564,2565],{},"Future\u003Cint>",[29,2567,577],{},". The ",[29,2570,1777],{}," keyword wraps the return in a ",[29,2573,2559],{},". ",[29,2576,2577],{},"Future\u003Cvoid> f() async {}"," for async functions with no return value.",[2387,2580,2581,2592,2593,2595],{},[2390,2582,2583,2586,2587,2589,2590],{},[29,2584,2585],{},"yield"," only in ",[29,2588,1403],{},"\u002F",[29,2591,1407],{},": using ",[29,2594,2585],{}," outside a generator function is a compile error. Regular functions can't yield.",[2387,2597,2598,2603,2604,2607,2608,2611],{},[2390,2599,2600,2602],{},[29,2601,1403],{}," iterables are lazy and re-evaluate",": each iteration re-runs the generator. ",[29,2605,2606],{},"var gen = fibonacci(); gen.take(10).toList(); gen.take(10).toList();"," runs the generator twice. Cache with ",[29,2609,2610],{},".toList()"," if you need to iterate multiple times.",[2387,2613,2614,2619,2620,2623,2624,2627],{},[2390,2615,2616,2618],{},[29,2617,1407],{}," streams are single-subscription by default",": listening twice throws ",[29,2621,2622],{},"StateError",". Use ",[29,2625,2626],{},".asBroadcastStream()"," for multiple listeners (but loses pause\u002Fresume\u002Fbuffering guarantees).",[2387,2629,2630,2633,2634,2637,2638,2640],{},[2390,2631,2632],{},"Lexical scope, not dynamic",": a function defined in ",[29,2635,2636],{},"outer"," accesses ",[29,2639,2636],{},"'s variables even if called from elsewhere. Scope is determined by code structure, not the call stack.",[14,2642,2644],{"id":2643},"spot-the-bug","🧠 Spot the Bug",[2646,2647,2648],"p",{},"A developer creates event handlers in a loop, but all handlers report the same button index:",[19,2650,2651],{"language":21},[23,2652,2654],{"className":25,"code":2653,"language":21,"meta":27,"style":27},"for (var i = 0; i \u003C buttons.length; i++) {\n  buttons[i].onClick.listen((_) => handleClick(i));\n}\n",[29,2655,2656,2681,2699],{"__ignoreMap":27},[32,2657,2658,2660,2662,2664,2666,2668,2670,2672,2674,2677,2679],{"class":34,"line":35},[32,2659,731],{"class":76},[32,2661,588],{"class":84},[32,2663,621],{"class":76},[32,2665,738],{"class":84},[32,2667,160],{"class":76},[32,2669,743],{"class":91},[32,2671,746],{"class":84},[32,2673,749],{"class":76},[32,2675,2676],{"class":84}," buttons.length; i",[32,2678,758],{"class":76},[32,2680,761],{"class":84},[32,2682,2683,2686,2689,2692,2694,2697],{"class":34,"line":42},[32,2684,2685],{"class":84},"  buttons[i].onClick.",[32,2687,2688],{"class":80},"listen",[32,2690,2691],{"class":84},"((_) ",[32,2693,596],{"class":76},[32,2695,2696],{"class":80}," handleClick",[32,2698,780],{"class":84},[32,2700,2701],{"class":34,"line":48},[32,2702,206],{"class":84},[2646,2704,2705,2706,2709,2710,2713],{},"When any button is clicked, ",[29,2707,2708],{},"handleClick"," always receives ",[29,2711,2712],{},"buttons.length",". Why?",[2715,2716,2717,2721,2757,2766,2827],"details",{},[2718,2719,2720],"summary",{},"Answer",[2646,2722,2723,2724,2727,2728,2731,2732,2735,2736,2738,2739,2741,2742,2745,2746,2748,2749,2751,2752,2754,2755,1621],{},"The closure ",[29,2725,2726],{},"(_) => handleClick(i)"," captures ",[29,2729,2730],{},"i"," ",[2390,2733,2734],{},"by reference",". Dart's ",[29,2737,731],{}," loop variable ",[29,2740,2730],{}," is a single variable reassigned each iteration (not fresh per iteration like JS ",[29,2743,2744],{},"let","). All closures capture the same ",[29,2747,2730],{},", which ends at ",[29,2750,2712],{}," after the loop. When any button is clicked, the closure reads the current value of ",[29,2753,2730],{}," — ",[29,2756,2712],{},[2646,2758,2759,2760,2762,2763,2765],{},"The fix — capture ",[29,2761,2730],{}," in a ",[29,2764,1293],{}," local per iteration:",[23,2767,2769],{"className":25,"code":2768,"language":21,"meta":27,"style":27},"for (var i = 0; i \u003C buttons.length; i++) {\n  final index = i;  \u002F\u002F fresh, immutable per iteration\n  buttons[i].onClick.listen((_) => handleClick(index));\n}\n",[29,2770,2771,2795,2808,2823],{"__ignoreMap":27},[32,2772,2773,2775,2777,2779,2781,2783,2785,2787,2789,2791,2793],{"class":34,"line":35},[32,2774,731],{"class":76},[32,2776,588],{"class":84},[32,2778,621],{"class":76},[32,2780,738],{"class":84},[32,2782,160],{"class":76},[32,2784,743],{"class":91},[32,2786,746],{"class":84},[32,2788,749],{"class":76},[32,2790,2676],{"class":84},[32,2792,758],{"class":76},[32,2794,761],{"class":84},[32,2796,2797,2799,2802,2804,2806],{"class":34,"line":42},[32,2798,504],{"class":76},[32,2800,2801],{"class":84}," index ",[32,2803,160],{"class":76},[32,2805,872],{"class":84},[32,2807,875],{"class":38},[32,2809,2810,2812,2814,2816,2818,2820],{"class":34,"line":48},[32,2811,2685],{"class":84},[32,2813,2688],{"class":80},[32,2815,2691],{"class":84},[32,2817,596],{"class":76},[32,2819,2696],{"class":80},[32,2821,2822],{"class":84},"(index));\n",[32,2824,2825],{"class":34,"line":54},[32,2826,206],{"class":84},[2646,2828,2829,2830,2833,2834,227,2837,2840],{},"Now each closure captures its own ",[29,2831,2832],{},"index",", which is immutable and holds the correct value for that iteration. ",[29,2835,2836],{},"handleClick(0)",[29,2838,2839],{},"handleClick(1)",", etc.",[2842,2843,2844],"style",{},"html pre.shiki code .sdCPZ, html code.shiki .sdCPZ{--shiki-default:#6A737D;--shiki-github-dark:#6A737D}html pre.shiki code .svdQ7, html code.shiki .svdQ7{--shiki-default:#D73A49;--shiki-github-dark:#F97583}html pre.shiki code .sIsaT, html code.shiki .sIsaT{--shiki-default:#6F42C1;--shiki-github-dark:#B392F0}html pre.shiki code .ssxIu, html code.shiki .ssxIu{--shiki-default:#24292E;--shiki-github-dark:#E1E4E8}html pre.shiki code .snvgF, html code.shiki .snvgF{--shiki-default:#005CC5;--shiki-github-dark:#79B8FF}html pre.shiki code .sJ6F3, html code.shiki .sJ6F3{--shiki-default:#032F62;--shiki-github-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html.github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}",{"title":27,"searchDepth":42,"depth":42,"links":2846},[2847,2848,2849,2850,2852,2854,2855,2856],{"id":16,"depth":42,"text":17},{"id":532,"depth":42,"text":533},{"id":935,"depth":42,"text":936},{"id":1399,"depth":42,"text":2851},"Generators — sync* and async*",{"id":1928,"depth":42,"text":2853},"Callable Classes — call() Method",{"id":2381,"depth":42,"text":2382},{"id":2459,"depth":42,"text":2460},{"id":2643,"depth":42,"text":2644},"Deep-dive into Dart function parameter semantics, closure capture mechanics, typedef usage, sync\u002Fasync generators, and callable classes. Code-first engineering reference.","md",{},"\u002Fdart\u002F05-functions-and-scope",{"title":5,"description":2857},"dart\u002F05-functions-and-scope","FQRvzVjnqDTJQ12JK9nQKdmJCWsTE7RcTFE9PlsQQ_Q",1789924647684]