[{"data":1,"prerenderedAt":1777},["ShallowReactive",2],{"author-nicolas-poirier":3,"author-articles-nicolas-poirier":22,"authors":1461},{"id":4,"title":5,"body":6,"description":10,"extension":13,"meta":14,"name":15,"navigation":16,"path":17,"readingTime":18,"seo":19,"stem":20,"__hash__":21},"authors\u002Fauthors\u002Fnicolas-poirier.md","Engineering Manager",{"type":7,"value":8,"toc":9},"minimark",[],{"title":10,"searchDepth":11,"depth":11,"links":12},"",2,[],"md",{},"Nicolas Poirier",true,"\u002Fauthors\u002Fnicolas-poirier",1,{"title":5,"description":10},"authors\u002Fnicolas-poirier","dXrJkYo8az4SN_D23aYc3fQ7z8s1dR2a0lt1ogjAjJs",[23,1102],{"id":24,"title":25,"author":26,"body":27,"date":1092,"description":1093,"extension":13,"lang":1094,"meta":1095,"navigation":16,"path":1096,"published":16,"readingTime":115,"seo":1097,"stem":1098,"tags":1099,"__hash__":1101},"articles\u002Farticles\u002F2022-06-23-the-interesting-properties-of-pure-functions.md","The interesting properties of pure functions","nicolas-poirier",{"type":7,"value":28,"toc":1076},[29,34,38,48,52,55,58,186,189,240,243,248,255,260,263,266,289,292,301,308,311,367,375,379,382,386,389,536,540,543,650,653,710,717,721,724,735,954,958,961,965,968,971,979,983,986,994,998,1001,1072],[30,31,33],"h2",{"id":32},"what-is-a-pure-function","What is a pure function?",[35,36,37],"p",{},"A pure function has two properties :",[39,40,41,45],"ol",{},[42,43,44],"li",{},"Output depends only on input",[42,46,47],{},"No side effects",[49,50,44],"h3",{"id":51},"output-depends-only-on-input",[35,53,54],{},"Output only depends on input, no matter when or where you call the function in your code.",[35,56,57],{},"To implement such a function, you could simply map input to output.",[59,60,64],"pre",{"className":61,"code":62,"language":63,"meta":10,"style":10},"language-ts shiki shiki-themes github-light github-dark","const square = {\n    0: 0,\n    1: 1,\n    2: 4,\n    3: 9,\n    4: 16,\n    …\n};\n\nsquare[2]; \u002F\u002F is always 4\n","ts",[65,66,67,86,100,113,126,139,152,158,164,170],"code",{"__ignoreMap":10},[68,69,71,75,79,82],"span",{"class":70,"line":18},"line",[68,72,74],{"class":73},"szBVR","const",[68,76,78],{"class":77},"sj4cs"," square",[68,80,81],{"class":73}," =",[68,83,85],{"class":84},"sVt8B"," {\n",[68,87,88,91,94,97],{"class":70,"line":11},[68,89,90],{"class":77},"    0",[68,92,93],{"class":84},": ",[68,95,96],{"class":77},"0",[68,98,99],{"class":84},",\n",[68,101,103,106,108,111],{"class":70,"line":102},3,[68,104,105],{"class":77},"    1",[68,107,93],{"class":84},[68,109,110],{"class":77},"1",[68,112,99],{"class":84},[68,114,116,119,121,124],{"class":70,"line":115},4,[68,117,118],{"class":77},"    2",[68,120,93],{"class":84},[68,122,123],{"class":77},"4",[68,125,99],{"class":84},[68,127,129,132,134,137],{"class":70,"line":128},5,[68,130,131],{"class":77},"    3",[68,133,93],{"class":84},[68,135,136],{"class":77},"9",[68,138,99],{"class":84},[68,140,142,145,147,150],{"class":70,"line":141},6,[68,143,144],{"class":77},"    4",[68,146,93],{"class":84},[68,148,149],{"class":77},"16",[68,151,99],{"class":84},[68,153,155],{"class":70,"line":154},7,[68,156,157],{"class":84},"    …\n",[68,159,161],{"class":70,"line":160},8,[68,162,163],{"class":84},"};\n",[68,165,167],{"class":70,"line":166},9,[68,168,169],{"emptyLinePlaceholder":16},"\n",[68,171,173,176,179,182],{"class":70,"line":172},10,[68,174,175],{"class":84},"square[",[68,177,178],{"class":77},"2",[68,180,181],{"class":84},"]; ",[68,183,185],{"class":184},"sJ8bj","\u002F\u002F is always 4\n",[35,187,188],{},"Writing all possible pairs (input, output) can be tedious. So you calculate the output from the\ninput",[59,190,192],{"className":61,"code":191,"language":63,"meta":10,"style":10},"const square = (x) => x * x;\nsquare(2); \u002F\u002F is always 4\n",[65,193,194,225],{"__ignoreMap":10},[68,195,196,198,201,203,206,210,213,216,219,222],{"class":70,"line":18},[68,197,74],{"class":73},[68,199,78],{"class":200},"sScJk",[68,202,81],{"class":73},[68,204,205],{"class":84}," (",[68,207,209],{"class":208},"s4XuR","x",[68,211,212],{"class":84},") ",[68,214,215],{"class":73},"=>",[68,217,218],{"class":84}," x ",[68,220,221],{"class":73},"*",[68,223,224],{"class":84}," x;\n",[68,226,227,230,233,235,238],{"class":70,"line":11},[68,228,229],{"class":200},"square",[68,231,232],{"class":84},"(",[68,234,178],{"class":77},[68,236,237],{"class":84},"); ",[68,239,185],{"class":184},[35,241,242],{},"These two implementations of square are equivalent and you always have",[35,244,245],{},[65,246,247],{},"square(2) = square(2)",[35,249,250,251,254],{},"On the contrary, ",[65,252,253],{},"Math.random()"," is impure as the output depends on when it is called.",[35,256,257],{},[65,258,259],{},"Math.random() ≠ Math.random()",[49,261,47],{"id":262},"no-side-effects",[35,264,265],{},"A side effect is an observable effect other than returning a value:",[267,268,269,286],"ul",{},[42,270,271,272],{},"I\u002FO operation\n",[267,273,274,277,280,283],{},[42,275,276],{},"Writing to database or file",[42,278,279],{},"making an HTTP call",[42,281,282],{},"Logging",[42,284,285],{},"Printing on screen",[42,287,288],{},"Mutation",[35,290,291],{},"Being pure means leaving I\u002FO operations outside of the function and using immutability.",[35,293,294,297,298],{},[65,295,296],{},"const a = square(2)"," is equivalent to ",[65,299,300],{},"const a = 4",[35,302,303,304,307],{},"Nothing happens during the computation of ",[65,305,306],{},"square(2)"," other than returning 4.",[35,309,310],{},"An implementation with side effect could be",[59,312,314],{"className":61,"code":313,"language":63,"meta":10,"style":10},"const impureSquare = (x) => {\n  console.log(\"square\", x);\n  return x * x;\n};\n",[65,315,316,335,352,363],{"__ignoreMap":10},[68,317,318,320,323,325,327,329,331,333],{"class":70,"line":18},[68,319,74],{"class":73},[68,321,322],{"class":200}," impureSquare",[68,324,81],{"class":73},[68,326,205],{"class":84},[68,328,209],{"class":208},[68,330,212],{"class":84},[68,332,215],{"class":73},[68,334,85],{"class":84},[68,336,337,340,343,345,349],{"class":70,"line":11},[68,338,339],{"class":84},"  console.",[68,341,342],{"class":200},"log",[68,344,232],{"class":84},[68,346,348],{"class":347},"sZZnC","\"square\"",[68,350,351],{"class":84},", x);\n",[68,353,354,357,359,361],{"class":70,"line":102},[68,355,356],{"class":73},"  return",[68,358,218],{"class":84},[68,360,221],{"class":73},[68,362,224],{"class":84},[68,364,365],{"class":70,"line":115},[68,366,163],{"class":84},[35,368,369,372,373],{},[65,370,371],{},"const a = impureSquare(2)"," is not equivalent to ",[65,374,300],{},[30,376,378],{"id":377},"why-is-it-interesting","Why is it interesting?",[35,380,381],{},"As output only depends on input without side effects, pure functions are independent of time and\nstate. Pure functions are predictable.",[49,383,385],{"id":384},"referentially-transparent","Referentially transparent",[35,387,388],{},"An expression is referentially transparent when it may be replaced by its value without changing the\nresult of the program. It makes the code easier to read, understand and test.",[59,390,392],{"className":61,"code":391,"language":63,"meta":10,"style":10},"const add2 = (x) => x + 2;\nconst multiplyBy2 = (x) => x * 2;\nconst add2AndMultiplyBy2 = (x) => multiplyBy2(add2(x));\n\nconst result = add2AndMultiplyBy2(3);\n\u002F\u002F is equivalent to\nconst result = multiplyBy2(5);\n\u002F\u002F is equivalent to\nconst result = 10;\n",[65,393,394,422,447,474,478,497,502,519,523],{"__ignoreMap":10},[68,395,396,398,401,403,405,407,409,411,413,416,419],{"class":70,"line":18},[68,397,74],{"class":73},[68,399,400],{"class":200}," add2",[68,402,81],{"class":73},[68,404,205],{"class":84},[68,406,209],{"class":208},[68,408,212],{"class":84},[68,410,215],{"class":73},[68,412,218],{"class":84},[68,414,415],{"class":73},"+",[68,417,418],{"class":77}," 2",[68,420,421],{"class":84},";\n",[68,423,424,426,429,431,433,435,437,439,441,443,445],{"class":70,"line":11},[68,425,74],{"class":73},[68,427,428],{"class":200}," multiplyBy2",[68,430,81],{"class":73},[68,432,205],{"class":84},[68,434,209],{"class":208},[68,436,212],{"class":84},[68,438,215],{"class":73},[68,440,218],{"class":84},[68,442,221],{"class":73},[68,444,418],{"class":77},[68,446,421],{"class":84},[68,448,449,451,454,456,458,460,462,464,466,468,471],{"class":70,"line":102},[68,450,74],{"class":73},[68,452,453],{"class":200}," add2AndMultiplyBy2",[68,455,81],{"class":73},[68,457,205],{"class":84},[68,459,209],{"class":208},[68,461,212],{"class":84},[68,463,215],{"class":73},[68,465,428],{"class":200},[68,467,232],{"class":84},[68,469,470],{"class":200},"add2",[68,472,473],{"class":84},"(x));\n",[68,475,476],{"class":70,"line":115},[68,477,169],{"emptyLinePlaceholder":16},[68,479,480,482,485,487,489,491,494],{"class":70,"line":128},[68,481,74],{"class":73},[68,483,484],{"class":77}," result",[68,486,81],{"class":73},[68,488,453],{"class":200},[68,490,232],{"class":84},[68,492,493],{"class":77},"3",[68,495,496],{"class":84},");\n",[68,498,499],{"class":70,"line":141},[68,500,501],{"class":184},"\u002F\u002F is equivalent to\n",[68,503,504,506,508,510,512,514,517],{"class":70,"line":154},[68,505,74],{"class":73},[68,507,484],{"class":77},[68,509,81],{"class":73},[68,511,428],{"class":200},[68,513,232],{"class":84},[68,515,516],{"class":77},"5",[68,518,496],{"class":84},[68,520,521],{"class":70,"line":160},[68,522,501],{"class":184},[68,524,525,527,529,531,534],{"class":70,"line":166},[68,526,74],{"class":73},[68,528,484],{"class":77},[68,530,81],{"class":73},[68,532,533],{"class":77}," 10",[68,535,421],{"class":84},[49,537,539],{"id":538},"testable","Testable",[35,541,542],{},"Pure functions are easily testable.",[59,544,546],{"className":61,"code":545,"language":63,"meta":10,"style":10},"const tomorrow = today => today.add({ days: 1 });\n\n\u002F\u002F You simply test it with\nexpect(tomorrow(Temporal.PlainDate.from(‘2022-05-28’)))\n    .toEqual(Temporal.PlainDate.from(‘2022-05-29’));\n",[65,547,548,577,581,586,622],{"__ignoreMap":10},[68,549,550,552,555,557,560,563,566,569,572,574],{"class":70,"line":18},[68,551,74],{"class":73},[68,553,554],{"class":200}," tomorrow",[68,556,81],{"class":73},[68,558,559],{"class":208}," today",[68,561,562],{"class":73}," =>",[68,564,565],{"class":84}," today.",[68,567,568],{"class":200},"add",[68,570,571],{"class":84},"({ days: ",[68,573,110],{"class":77},[68,575,576],{"class":84}," });\n",[68,578,579],{"class":70,"line":11},[68,580,169],{"emptyLinePlaceholder":16},[68,582,583],{"class":70,"line":102},[68,584,585],{"class":184},"\u002F\u002F You simply test it with\n",[68,587,588,591,593,596,599,602,605,608,611,614,616,619],{"class":70,"line":115},[68,589,590],{"class":200},"expect",[68,592,232],{"class":84},[68,594,595],{"class":200},"tomorrow",[68,597,598],{"class":84},"(Temporal.PlainDate.",[68,600,601],{"class":200},"from",[68,603,604],{"class":84},"(‘",[68,606,607],{"class":77},"2022",[68,609,610],{"class":73},"-",[68,612,613],{"class":77},"05",[68,615,610],{"class":73},[68,617,618],{"class":77},"28",[68,620,621],{"class":84},"’)))\n",[68,623,624,627,630,632,634,636,638,640,642,644,647],{"class":70,"line":128},[68,625,626],{"class":84},"    .",[68,628,629],{"class":200},"toEqual",[68,631,598],{"class":84},[68,633,601],{"class":200},[68,635,604],{"class":84},[68,637,607],{"class":77},[68,639,610],{"class":73},[68,641,613],{"class":77},[68,643,610],{"class":73},[68,645,646],{"class":77},"29",[68,648,649],{"class":84},"’));\n",[35,651,652],{},"What if it were an impure function?",[59,654,656],{"className":61,"code":655,"language":63,"meta":10,"style":10},"const impureTomorrow = () => {\n  const today = Temporal.Now.plainDateISO();\n  return today.add({ days: 1 });\n};\n",[65,657,658,674,692,706],{"__ignoreMap":10},[68,659,660,662,665,667,670,672],{"class":70,"line":18},[68,661,74],{"class":73},[68,663,664],{"class":200}," impureTomorrow",[68,666,81],{"class":73},[68,668,669],{"class":84}," () ",[68,671,215],{"class":73},[68,673,85],{"class":84},[68,675,676,679,681,683,686,689],{"class":70,"line":11},[68,677,678],{"class":73},"  const",[68,680,559],{"class":77},[68,682,81],{"class":73},[68,684,685],{"class":84}," Temporal.Now.",[68,687,688],{"class":200},"plainDateISO",[68,690,691],{"class":84},"();\n",[68,693,694,696,698,700,702,704],{"class":70,"line":102},[68,695,356],{"class":73},[68,697,565],{"class":84},[68,699,568],{"class":200},[68,701,571],{"class":84},[68,703,110],{"class":77},[68,705,576],{"class":84},[68,707,708],{"class":70,"line":115},[68,709,163],{"class":84},[35,711,712,713,716],{},"Impure function is tricky to test as you have to mock ",[65,714,715],{},"Temporal.Now.plainDateISO()",".",[49,718,720],{"id":719},"cacheable","Cacheable",[35,722,723],{},"Pure function output is cacheable. Simply map input to output and the next time you need the result\nof this extensive function call, use the cached value. No need to worry about time to live.",[35,725,726,727,734],{},"To do that, you can use ",[728,729,733],"a",{"href":730,"rel":731},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FMemoization",[732],"nofollow","memoization",". Here is a basic\nimplementation:",[59,736,738],{"className":61,"code":737,"language":63,"meta":10,"style":10},"const memoize = (f) => {\n  const cache = {};\n\n  return (...args) => {\n    const key = JSON.stringify(args);\n\n    if (key in cache) {\n      return cache[key];\n    }\n\n    const result = f(...args);\n    cache[key] = result;\n    return result;\n  };\n};\n\nconst memoizedSquare = memoize(square);\n\nmemoizedSquare(2); \u002F\u002F is 4. It calls square()\nmemoizedSquare(2); \u002F\u002F is 4. It uses the cached result. Doesn’t call square()\n",[65,739,740,760,772,776,794,815,819,833,841,846,850,869,881,889,895,900,905,920,925,940],{"__ignoreMap":10},[68,741,742,744,747,749,751,754,756,758],{"class":70,"line":18},[68,743,74],{"class":73},[68,745,746],{"class":200}," memoize",[68,748,81],{"class":73},[68,750,205],{"class":84},[68,752,753],{"class":208},"f",[68,755,212],{"class":84},[68,757,215],{"class":73},[68,759,85],{"class":84},[68,761,762,764,767,769],{"class":70,"line":11},[68,763,678],{"class":73},[68,765,766],{"class":77}," cache",[68,768,81],{"class":73},[68,770,771],{"class":84}," {};\n",[68,773,774],{"class":70,"line":102},[68,775,169],{"emptyLinePlaceholder":16},[68,777,778,780,782,785,788,790,792],{"class":70,"line":115},[68,779,356],{"class":73},[68,781,205],{"class":84},[68,783,784],{"class":73},"...",[68,786,787],{"class":208},"args",[68,789,212],{"class":84},[68,791,215],{"class":73},[68,793,85],{"class":84},[68,795,796,799,802,804,807,809,812],{"class":70,"line":128},[68,797,798],{"class":73},"    const",[68,800,801],{"class":77}," key",[68,803,81],{"class":73},[68,805,806],{"class":77}," JSON",[68,808,716],{"class":84},[68,810,811],{"class":200},"stringify",[68,813,814],{"class":84},"(args);\n",[68,816,817],{"class":70,"line":141},[68,818,169],{"emptyLinePlaceholder":16},[68,820,821,824,827,830],{"class":70,"line":154},[68,822,823],{"class":73},"    if",[68,825,826],{"class":84}," (key ",[68,828,829],{"class":73},"in",[68,831,832],{"class":84}," cache) {\n",[68,834,835,838],{"class":70,"line":160},[68,836,837],{"class":73},"      return",[68,839,840],{"class":84}," cache[key];\n",[68,842,843],{"class":70,"line":166},[68,844,845],{"class":84},"    }\n",[68,847,848],{"class":70,"line":172},[68,849,169],{"emptyLinePlaceholder":16},[68,851,853,855,857,859,862,864,866],{"class":70,"line":852},11,[68,854,798],{"class":73},[68,856,484],{"class":77},[68,858,81],{"class":73},[68,860,861],{"class":200}," f",[68,863,232],{"class":84},[68,865,784],{"class":73},[68,867,868],{"class":84},"args);\n",[68,870,872,875,878],{"class":70,"line":871},12,[68,873,874],{"class":84},"    cache[key] ",[68,876,877],{"class":73},"=",[68,879,880],{"class":84}," result;\n",[68,882,884,887],{"class":70,"line":883},13,[68,885,886],{"class":73},"    return",[68,888,880],{"class":84},[68,890,892],{"class":70,"line":891},14,[68,893,894],{"class":84},"  };\n",[68,896,898],{"class":70,"line":897},15,[68,899,163],{"class":84},[68,901,903],{"class":70,"line":902},16,[68,904,169],{"emptyLinePlaceholder":16},[68,906,908,910,913,915,917],{"class":70,"line":907},17,[68,909,74],{"class":73},[68,911,912],{"class":77}," memoizedSquare",[68,914,81],{"class":73},[68,916,746],{"class":200},[68,918,919],{"class":84},"(square);\n",[68,921,923],{"class":70,"line":922},18,[68,924,169],{"emptyLinePlaceholder":16},[68,926,928,931,933,935,937],{"class":70,"line":927},19,[68,929,930],{"class":200},"memoizedSquare",[68,932,232],{"class":84},[68,934,178],{"class":77},[68,936,237],{"class":84},[68,938,939],{"class":184},"\u002F\u002F is 4. It calls square()\n",[68,941,943,945,947,949,951],{"class":70,"line":942},20,[68,944,930],{"class":200},[68,946,232],{"class":84},[68,948,178],{"class":77},[68,950,237],{"class":84},[68,952,953],{"class":184},"\u002F\u002F is 4. It uses the cached result. Doesn’t call square()\n",[49,955,957],{"id":956},"runnable-in-parallel","Runnable in parallel",[35,959,960],{},"Pure functions can run in parallel as no access to shared memory means no race condition.",[30,962,964],{"id":963},"how-do-we-use-them-at-indy","How do we use them at Indy?",[35,966,967],{},"Due to the power of pure functions, we use them at Indy.",[35,969,970],{},"We have two kind of functions:",[267,972,973,976],{},[42,974,975],{},"model functions (pure) contain all the logic of the application",[42,977,978],{},"service functions (impure) handle I\u002FO operations",[49,980,982],{"id":981},"model-functions","Model functions",[35,984,985],{},"Model functions are pure and contain all the logic of the application. No logic should be in impure\nfunctions.",[267,987,988,991],{},[42,989,990],{},"Calculating business (mainly bookkeeping) rules",[42,992,993],{},"Mapping data at interfaces (business model \u002F database, business model \u002F web)",[49,995,997],{"id":996},"service-functions","Service functions",[35,999,1000],{},"Service functions gather data, use model functions and save results. No logic here.",[59,1002,1004],{"className":61,"code":1003,"language":63,"meta":10,"style":10},"async function doSomething() {\n  const data = await getData();\n  \u002F\u002F all the logic is in this pure function from the model\n  const result = computeSomething(data);\n  await saveResult(result);\n}\n",[65,1005,1006,1020,1037,1042,1056,1067],{"__ignoreMap":10},[68,1007,1008,1011,1014,1017],{"class":70,"line":18},[68,1009,1010],{"class":73},"async",[68,1012,1013],{"class":73}," function",[68,1015,1016],{"class":200}," doSomething",[68,1018,1019],{"class":84},"() {\n",[68,1021,1022,1024,1027,1029,1032,1035],{"class":70,"line":11},[68,1023,678],{"class":73},[68,1025,1026],{"class":77}," data",[68,1028,81],{"class":73},[68,1030,1031],{"class":73}," await",[68,1033,1034],{"class":200}," getData",[68,1036,691],{"class":84},[68,1038,1039],{"class":70,"line":102},[68,1040,1041],{"class":184},"  \u002F\u002F all the logic is in this pure function from the model\n",[68,1043,1044,1046,1048,1050,1053],{"class":70,"line":115},[68,1045,678],{"class":73},[68,1047,484],{"class":77},[68,1049,81],{"class":73},[68,1051,1052],{"class":200}," computeSomething",[68,1054,1055],{"class":84},"(data);\n",[68,1057,1058,1061,1064],{"class":70,"line":128},[68,1059,1060],{"class":73},"  await",[68,1062,1063],{"class":200}," saveResult",[68,1065,1066],{"class":84},"(result);\n",[68,1068,1069],{"class":70,"line":141},[68,1070,1071],{"class":84},"}\n",[1073,1074,1075],"style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}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 .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}",{"title":10,"searchDepth":11,"depth":11,"links":1077},[1078,1082,1088],{"id":32,"depth":11,"text":33,"children":1079},[1080,1081],{"id":51,"depth":102,"text":44},{"id":262,"depth":102,"text":47},{"id":377,"depth":11,"text":378,"children":1083},[1084,1085,1086,1087],{"id":384,"depth":102,"text":385},{"id":538,"depth":102,"text":539},{"id":719,"depth":102,"text":720},{"id":956,"depth":102,"text":957},{"id":963,"depth":11,"text":964,"children":1089},[1090,1091],{"id":981,"depth":102,"text":982},{"id":996,"depth":102,"text":997},"2022-06-23","What is a pure function, why is it interesting and how do we use them at Indy?","en",{},"\u002Farticles\u002F2022-06-23-the-interesting-properties-of-pure-functions",{"title":25,"description":1093},"articles\u002F2022-06-23-the-interesting-properties-of-pure-functions",[1100],"Tech","cZKQgi_vTPRSNKbphM80ENxdQ7O8tpg_7RNMt8wa9pA",{"id":1103,"title":1104,"author":26,"body":1105,"date":1453,"description":1454,"extension":13,"lang":1094,"meta":1455,"navigation":16,"path":1456,"published":16,"readingTime":102,"seo":1457,"stem":1458,"tags":1459,"__hash__":1460},"articles\u002Farticles\u002F2022-06-02-tail-call-optimizing-recursion.md","Tail call: Optimizing recursion",{"type":7,"value":1106,"toc":1449},[1107,1118,1121,1145,1149,1248,1251,1257,1266,1273,1282,1288,1292,1295,1298,1301,1407,1409,1414,1430,1433,1438,1443,1446],[35,1108,1109,1110,1113,1114,1117],{},"Recursive functions are recommended to solve some problems, or imposed by languages like pure\nfunctional programming languages which don’t have ",[65,1111,1112],{},"for"," and ",[65,1115,1116],{},"while"," loops. But recursion may comes\nat a price.",[35,1119,1120],{},"Let’s use recursion to sum the elements of an array and understand how to optimize it with tail call\noptimization.",[35,1122,1123,1124,99,1129,99,1134,1139,1140,716],{},"Note that I use JavaScript and although tail call optimization appeared in\n",[728,1125,1128],{"href":1126,"rel":1127},"https:\u002F\u002F262.ecma-international.org\u002F6.0\u002F#sec-tail-position-calls",[732],"ES 6 specifications",[728,1130,1133],{"href":1131,"rel":1132},"https:\u002F\u002Fkangax.github.io\u002Fcompat-table\u002Fes6\u002F",[732],"most engines don’t implement it",[728,1135,1138],{"href":1136,"rel":1137},"https:\u002F\u002Fv8.dev\u002Fblog\u002Fmodern-javascript#proper-tail-calls",[732],"including V8",". Apple WebKit is one of the\nonly ones where it is available. Other languages implementing tail call optimization are listed in\nthe ",[728,1141,1144],{"href":1142,"rel":1143},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FTail_call#Language_support",[732],"Wikipedia article about tail call",[30,1146,1148],{"id":1147},"naive-implementation","Naive implementation",[59,1150,1152],{"className":61,"code":1151,"language":63,"meta":10,"style":10},"function sum(x) {\n  \u002F\u002F Base case. The sum of no elements is 0\n  if (x.length === 0) {\n    return 0;\n  }\n\n  \u002F\u002F Add the first element to the sum of all the other elements\n  return x[0] + sum(x.slice(1));\n}\n",[65,1153,1154,1169,1174,1193,1201,1206,1210,1215,1244],{"__ignoreMap":10},[68,1155,1156,1159,1162,1164,1166],{"class":70,"line":18},[68,1157,1158],{"class":73},"function",[68,1160,1161],{"class":200}," sum",[68,1163,232],{"class":84},[68,1165,209],{"class":208},[68,1167,1168],{"class":84},") {\n",[68,1170,1171],{"class":70,"line":11},[68,1172,1173],{"class":184},"  \u002F\u002F Base case. The sum of no elements is 0\n",[68,1175,1176,1179,1182,1185,1188,1191],{"class":70,"line":102},[68,1177,1178],{"class":73},"  if",[68,1180,1181],{"class":84}," (x.",[68,1183,1184],{"class":77},"length",[68,1186,1187],{"class":73}," ===",[68,1189,1190],{"class":77}," 0",[68,1192,1168],{"class":84},[68,1194,1195,1197,1199],{"class":70,"line":115},[68,1196,886],{"class":73},[68,1198,1190],{"class":77},[68,1200,421],{"class":84},[68,1202,1203],{"class":70,"line":128},[68,1204,1205],{"class":84},"  }\n",[68,1207,1208],{"class":70,"line":141},[68,1209,169],{"emptyLinePlaceholder":16},[68,1211,1212],{"class":70,"line":154},[68,1213,1214],{"class":184},"  \u002F\u002F Add the first element to the sum of all the other elements\n",[68,1216,1217,1219,1222,1224,1227,1229,1231,1234,1237,1239,1241],{"class":70,"line":160},[68,1218,356],{"class":73},[68,1220,1221],{"class":84}," x[",[68,1223,96],{"class":77},[68,1225,1226],{"class":84},"] ",[68,1228,415],{"class":73},[68,1230,1161],{"class":200},[68,1232,1233],{"class":84},"(x.",[68,1235,1236],{"class":200},"slice",[68,1238,232],{"class":84},[68,1240,110],{"class":77},[68,1242,1243],{"class":84},"));\n",[68,1245,1246],{"class":70,"line":166},[68,1247,1071],{"class":84},[35,1249,1250],{},"It runs like this:",[35,1252,1253],{},[1254,1255],"img",{"alt":10,"src":1256},"\u002Fimages\u002Fimage-1-1.webp",[35,1258,1259,1260,1265],{},"Comes ",[728,1261,1264],{"href":1262,"rel":1263},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FGlossary\u002FCall_stack",[732],"the call stack",". The call stack\nkeeps track of where the interpreter is in a program that calls multiple functions. When the program\ncalls a function, the interpreter adds that function on the top of the call stack. When the function\nis finished, the interpreter takes it off the stack.",[35,1267,1268,1269,1272],{},"Basically that’s how it computes ",[65,1270,1271],{},"sum([1, 2, 3])",":",[35,1274,1276,1277],{"align":1275},"center","\n  ",[1254,1278],{"src":1279,"alt":1280,"style":1281},"\u002Fimages\u002Fcall-stack-no-tail-call-1-_2_.jpg","Call Stack Example","width:150px; object-fit:contain;",[35,1283,1284,1287],{},[65,1285,1286],{},"[]"," is the base case. It returns 0. The interpreter has stacked 4 frames. Now it can start\nunstacking. With bigger arrays (about 10 000 elements depending on configuration), the call stack\ncould reach its maximum size, crashing the program.",[30,1289,1291],{"id":1290},"tail-call-to-the-rescue","Tail call to the rescue",[35,1293,1294],{},"Tail call means that the final action of a function is a function call.",[35,1296,1297],{},"In the previous implementation, the final action of the function was an addition.",[35,1299,1300],{},"Let’s apply tail call. To do that, you have to add an accumulator argument to the function to save\nthe partial sum. Using an accumulator is often required to apply tail call.",[59,1302,1304],{"className":61,"code":1303,"language":63,"meta":10,"style":10},"function sum(x, acc = 0) {\n  \u002F\u002F Base case: no more elements, returns the accumulator\n  if (x.length === 0) {\n    return acc;\n  }\n\n  \u002F\u002F Call sum() without the first element\n  \u002F\u002F Add the first element to the accumulator\n  \u002F\u002F The recursive call to sum() is now the final action of the function\n  return sum(x.slice(1), acc + x[0]);\n}\n",[65,1305,1306,1328,1333,1347,1354,1358,1362,1367,1372,1377,1403],{"__ignoreMap":10},[68,1307,1308,1310,1312,1314,1316,1319,1322,1324,1326],{"class":70,"line":18},[68,1309,1158],{"class":73},[68,1311,1161],{"class":200},[68,1313,232],{"class":84},[68,1315,209],{"class":208},[68,1317,1318],{"class":84},", ",[68,1320,1321],{"class":208},"acc",[68,1323,81],{"class":73},[68,1325,1190],{"class":77},[68,1327,1168],{"class":84},[68,1329,1330],{"class":70,"line":11},[68,1331,1332],{"class":184},"  \u002F\u002F Base case: no more elements, returns the accumulator\n",[68,1334,1335,1337,1339,1341,1343,1345],{"class":70,"line":102},[68,1336,1178],{"class":73},[68,1338,1181],{"class":84},[68,1340,1184],{"class":77},[68,1342,1187],{"class":73},[68,1344,1190],{"class":77},[68,1346,1168],{"class":84},[68,1348,1349,1351],{"class":70,"line":115},[68,1350,886],{"class":73},[68,1352,1353],{"class":84}," acc;\n",[68,1355,1356],{"class":70,"line":128},[68,1357,1205],{"class":84},[68,1359,1360],{"class":70,"line":141},[68,1361,169],{"emptyLinePlaceholder":16},[68,1363,1364],{"class":70,"line":154},[68,1365,1366],{"class":184},"  \u002F\u002F Call sum() without the first element\n",[68,1368,1369],{"class":70,"line":160},[68,1370,1371],{"class":184},"  \u002F\u002F Add the first element to the accumulator\n",[68,1373,1374],{"class":70,"line":166},[68,1375,1376],{"class":184},"  \u002F\u002F The recursive call to sum() is now the final action of the function\n",[68,1378,1379,1381,1383,1385,1387,1389,1391,1394,1396,1398,1400],{"class":70,"line":172},[68,1380,356],{"class":73},[68,1382,1161],{"class":200},[68,1384,1233],{"class":84},[68,1386,1236],{"class":200},[68,1388,232],{"class":84},[68,1390,110],{"class":77},[68,1392,1393],{"class":84},"), acc ",[68,1395,415],{"class":73},[68,1397,1221],{"class":84},[68,1399,96],{"class":77},[68,1401,1402],{"class":84},"]);\n",[68,1404,1405],{"class":70,"line":852},[68,1406,1071],{"class":84},[35,1408,1250],{},[35,1410,1411],{},[1254,1412],{"alt":10,"src":1413},"\u002Fimages\u002Fimage-1.png",[35,1415,1416,1417,1420,1421,1424,1425,1427,1428,716],{},"The interpreter doesn’t have to go back to the previous ",[65,1418,1419],{},"sum()"," call. It only has to go back to the\noriginal caller ",[65,1422,1423],{},"sumCaller()",". Thereby, the call stack doesn’t need to keep track of all calls to\n",[65,1426,1419],{},". That allows an optimization called tail call optimization. Interpreters that implement tail\ncall optimization will only use one frame to keep track of the current call to ",[65,1429,1419],{},[35,1431,1432],{},"With tail call optimization, the call stack is like this:",[35,1434,1276,1435],{"align":1275},[1254,1436],{"src":1437,"alt":1280,"style":1281},"\u002Fimages\u002Fcall-stack-tail-call-1.png",[35,1439,1440,1441,716],{},"Now, even with bigger arrays, the call stack will only use one frame to compute ",[65,1442,1419],{},[35,1444,1445],{},"Be careful using recursion and think about tail call optimization.",[1073,1447,1448],{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}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 .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":10,"searchDepth":11,"depth":11,"links":1450},[1451,1452],{"id":1147,"depth":11,"text":1148},{"id":1290,"depth":11,"text":1291},"2022-06-02","Let’s use recursion to sum the elements of an array and understand how to optimize it with tail call optimization.",{},"\u002Farticles\u002F2022-06-02-tail-call-optimizing-recursion",{"title":1104,"description":1454},"articles\u002F2022-06-02-tail-call-optimizing-recursion",[1100],"vmFzQVTjF9PAQgSx1HNX5gB2xfudOQXPaQqbUvuxPx0",[1462,1475,1487,1499,1512,1524,1536,1549,1562,1575,1587,1599,1612,1624,1636,1648,1660,1672,1679,1691,1704,1716,1728,1741,1753,1765],{"id":1463,"title":1464,"body":1465,"description":10,"extension":13,"meta":1469,"name":1470,"navigation":16,"path":1471,"readingTime":18,"seo":1472,"stem":1473,"__hash__":1474},"authors\u002Fauthors\u002Falexandre-guillon.md","Software Engineer",{"type":7,"value":1466,"toc":1467},[],{"title":10,"searchDepth":11,"depth":11,"links":1468},[],{},"Alexandre Guillon","\u002Fauthors\u002Falexandre-guillon",{"title":1464,"description":10},"authors\u002Falexandre-guillon","4tf48mjyjFNqItOHaulICbrjeCyMag1o6801uHeTz98",{"id":1476,"title":1464,"body":1477,"description":10,"extension":13,"meta":1481,"name":1482,"navigation":16,"path":1483,"readingTime":18,"seo":1484,"stem":1485,"__hash__":1486},"authors\u002Fauthors\u002Falexis-ablain.md",{"type":7,"value":1478,"toc":1479},[],{"title":10,"searchDepth":11,"depth":11,"links":1480},[],{},"Alexis Ablain","\u002Fauthors\u002Falexis-ablain",{"title":1464,"description":10},"authors\u002Falexis-ablain","_SIAtB7f-39e5t3GiJof81NP47s6MGo2n4gaHkTy1uQ",{"id":1488,"title":5,"body":1489,"description":10,"extension":13,"meta":1493,"name":1494,"navigation":16,"path":1495,"readingTime":18,"seo":1496,"stem":1497,"__hash__":1498},"authors\u002Fauthors\u002Faxel-shaita.md",{"type":7,"value":1490,"toc":1491},[],{"title":10,"searchDepth":11,"depth":11,"links":1492},[],{},"Axel Shaïta","\u002Fauthors\u002Faxel-shaita",{"title":5,"description":10},"authors\u002Faxel-shaita","fK0argUhsBkWLjpTAhY13oYLVzQthcEYkCEdtHWmIgE",{"id":1500,"title":1501,"body":1502,"description":10,"extension":13,"meta":1506,"name":1507,"navigation":16,"path":1508,"readingTime":18,"seo":1509,"stem":1510,"__hash__":1511},"authors\u002Fauthors\u002Fbaptiste-faure.md","Head of Talent Acquisition",{"type":7,"value":1503,"toc":1504},[],{"title":10,"searchDepth":11,"depth":11,"links":1505},[],{},"Baptiste Faure","\u002Fauthors\u002Fbaptiste-faure",{"title":1501,"description":10},"authors\u002Fbaptiste-faure","ELisToYtcgHmgdVWZkCclTPV6exZtfyXqhpx1jjbJHs",{"id":1513,"title":1464,"body":1514,"description":10,"extension":13,"meta":1518,"name":1519,"navigation":16,"path":1520,"readingTime":18,"seo":1521,"stem":1522,"__hash__":1523},"authors\u002Fauthors\u002Fbenjamin-bouillot.md",{"type":7,"value":1515,"toc":1516},[],{"title":10,"searchDepth":11,"depth":11,"links":1517},[],{},"Benjamin Bouillot","\u002Fauthors\u002Fbenjamin-bouillot",{"title":1464,"description":10},"authors\u002Fbenjamin-bouillot","tbhCFZyfTt7ZM5b5YgqQ2nhgnSTl8BweaQQryc87fHo",{"id":1525,"title":5,"body":1526,"description":10,"extension":13,"meta":1530,"name":1531,"navigation":16,"path":1532,"readingTime":18,"seo":1533,"stem":1534,"__hash__":1535},"authors\u002Fauthors\u002Fcedric-nicoloso.md",{"type":7,"value":1527,"toc":1528},[],{"title":10,"searchDepth":11,"depth":11,"links":1529},[],{},"Cédric Nicoloso","\u002Fauthors\u002Fcedric-nicoloso",{"title":5,"description":10},"authors\u002Fcedric-nicoloso","ibSoh4VZYiWYTuLOnZTedaAfcnvet1Q9H7ogW0LgorY",{"id":1537,"title":1538,"body":1539,"description":10,"extension":13,"meta":1543,"name":1544,"navigation":16,"path":1545,"readingTime":18,"seo":1546,"stem":1547,"__hash__":1548},"authors\u002Fauthors\u002Fdavid-touzet.md","Staff Engineer",{"type":7,"value":1540,"toc":1541},[],{"title":10,"searchDepth":11,"depth":11,"links":1542},[],{},"David Touzet","\u002Fauthors\u002Fdavid-touzet",{"title":1538,"description":10},"authors\u002Fdavid-touzet","dHWwnQxb1Ubt-WwXWEODGEo9AFoq1cJUhfg3kdnYSBM",{"id":1550,"title":1551,"body":1552,"description":10,"extension":13,"meta":1556,"name":1557,"navigation":16,"path":1558,"readingTime":18,"seo":1559,"stem":1560,"__hash__":1561},"authors\u002Fauthors\u002Feloise-chizat.md","Data Engineer",{"type":7,"value":1553,"toc":1554},[],{"title":10,"searchDepth":11,"depth":11,"links":1555},[],{},"Eloïse Chizat","\u002Fauthors\u002Feloise-chizat",{"title":1551,"description":10},"authors\u002Feloise-chizat","Utd72Vm9qT4hh2ZbFi6a2_nXw5Wb494Ed_HL1ra5yw8",{"id":1563,"title":1564,"body":1565,"description":10,"extension":13,"meta":1569,"name":1570,"navigation":16,"path":1571,"readingTime":18,"seo":1572,"stem":1573,"__hash__":1574},"authors\u002Fauthors\u002Femmanuel-auclair.md","Staff engineer",{"type":7,"value":1566,"toc":1567},[],{"title":10,"searchDepth":11,"depth":11,"links":1568},[],{},"Emmanuel Auclair","\u002Fauthors\u002Femmanuel-auclair",{"title":1564,"description":10},"authors\u002Femmanuel-auclair","MtsA8THNLEn0dTtYEIQaGwDuf7MjQL55IOeei5gugEg",{"id":1576,"title":1464,"body":1577,"description":10,"extension":13,"meta":1581,"name":1582,"navigation":16,"path":1583,"readingTime":18,"seo":1584,"stem":1585,"__hash__":1586},"authors\u002Fauthors\u002Fhoreb-parraud.md",{"type":7,"value":1578,"toc":1579},[],{"title":10,"searchDepth":11,"depth":11,"links":1580},[],{},"Horeb Parraud","\u002Fauthors\u002Fhoreb-parraud",{"title":1464,"description":10},"authors\u002Fhoreb-parraud","ajjsnUX4ohZI-ghMdbb92q_taWDkKXVZSLZXoAeLQtg",{"id":1588,"title":5,"body":1589,"description":10,"extension":13,"meta":1593,"name":1594,"navigation":16,"path":1595,"readingTime":18,"seo":1596,"stem":1597,"__hash__":1598},"authors\u002Fauthors\u002Fhugo-contreras.md",{"type":7,"value":1590,"toc":1591},[],{"title":10,"searchDepth":11,"depth":11,"links":1592},[],{},"Hugo Contreras","\u002Fauthors\u002Fhugo-contreras",{"title":5,"description":10},"authors\u002Fhugo-contreras","2nc3VMu9ASq9Z6Pwx2-7-Ye991Pww4p-UEDBQFfjF-Q",{"id":1600,"title":1601,"body":1602,"description":10,"extension":13,"meta":1606,"name":1607,"navigation":16,"path":1608,"readingTime":18,"seo":1609,"stem":1610,"__hash__":1611},"authors\u002Fauthors\u002Fjulien-tassin.md","Head of Engineering",{"type":7,"value":1603,"toc":1604},[],{"title":10,"searchDepth":11,"depth":11,"links":1605},[],{},"Julien Tassin","\u002Fauthors\u002Fjulien-tassin",{"title":1601,"description":10},"authors\u002Fjulien-tassin","iUIHI7SITje38Jh9X9uvYs4-VsHx4eCdt6hAlyLFG_o",{"id":1613,"title":1464,"body":1614,"description":10,"extension":13,"meta":1618,"name":1619,"navigation":16,"path":1620,"readingTime":18,"seo":1621,"stem":1622,"__hash__":1623},"authors\u002Fauthors\u002Flaurent-renard.md",{"type":7,"value":1615,"toc":1616},[],{"title":10,"searchDepth":11,"depth":11,"links":1617},[],{},"Laurent Renard","\u002Fauthors\u002Flaurent-renard",{"title":1464,"description":10},"authors\u002Flaurent-renard","5BP7Ed-pt1SQHjh0UJ1XUrlLTcdlFaDoKBCP4deHq8A",{"id":1625,"title":1464,"body":1626,"description":10,"extension":13,"meta":1630,"name":1631,"navigation":16,"path":1632,"readingTime":18,"seo":1633,"stem":1634,"__hash__":1635},"authors\u002Fauthors\u002Fleo-martin.md",{"type":7,"value":1627,"toc":1628},[],{"title":10,"searchDepth":11,"depth":11,"links":1629},[],{},"Léo Martin","\u002Fauthors\u002Fleo-martin",{"title":1464,"description":10},"authors\u002Fleo-martin","eYxCHkRgbGDV7shKdTA9s7Tu0zGV4yDGFoKR5MHQntY",{"id":1637,"title":1464,"body":1638,"description":10,"extension":13,"meta":1642,"name":1643,"navigation":16,"path":1644,"readingTime":18,"seo":1645,"stem":1646,"__hash__":1647},"authors\u002Fauthors\u002Floic-bousquet.md",{"type":7,"value":1639,"toc":1640},[],{"title":10,"searchDepth":11,"depth":11,"links":1641},[],{},"Loïc Bousquet","\u002Fauthors\u002Floic-bousquet",{"title":1464,"description":10},"authors\u002Floic-bousquet","ko12qZwiGL8XNjAoy9oWypPkIjr29Pbq7vhdtgldqeQ",{"id":1649,"title":1464,"body":1650,"description":10,"extension":13,"meta":1654,"name":1655,"navigation":16,"path":1656,"readingTime":18,"seo":1657,"stem":1658,"__hash__":1659},"authors\u002Fauthors\u002Floic-poullain.md",{"type":7,"value":1651,"toc":1652},[],{"title":10,"searchDepth":11,"depth":11,"links":1653},[],{},"Loïc Poullain","\u002Fauthors\u002Floic-poullain",{"title":1464,"description":10},"authors\u002Floic-poullain","oRIyJhFRTqxy5dLCYQ2OnYZ1DB-gLDUM-85vTSYuTF0",{"id":1661,"title":1551,"body":1662,"description":10,"extension":13,"meta":1666,"name":1667,"navigation":16,"path":1668,"readingTime":18,"seo":1669,"stem":1670,"__hash__":1671},"authors\u002Fauthors\u002Fmaud-lelu.md",{"type":7,"value":1663,"toc":1664},[],{"title":10,"searchDepth":11,"depth":11,"links":1665},[],{},"Maud Lélu","\u002Fauthors\u002Fmaud-lelu",{"title":1551,"description":10},"authors\u002Fmaud-lelu","MMbsCKuE41OMHusrl12FIEsI-Trx7l8Nn_ANhvj2_y4",{"id":4,"title":5,"body":1673,"description":10,"extension":13,"meta":1677,"name":15,"navigation":16,"path":17,"readingTime":18,"seo":1678,"stem":20,"__hash__":21},{"type":7,"value":1674,"toc":1675},[],{"title":10,"searchDepth":11,"depth":11,"links":1676},[],{},{"title":5,"description":10},{"id":1680,"title":5,"body":1681,"description":10,"extension":13,"meta":1685,"name":1686,"navigation":16,"path":1687,"readingTime":18,"seo":1688,"stem":1689,"__hash__":1690},"authors\u002Fauthors\u002Fraphael-sauget.md",{"type":7,"value":1682,"toc":1683},[],{"title":10,"searchDepth":11,"depth":11,"links":1684},[],{},"Raphaël Sauget","\u002Fauthors\u002Fraphael-sauget",{"title":5,"description":10},"authors\u002Fraphael-sauget","Uri9bcq0QDuxRA0PbBoNtu7p_5L3dALu4kzcXVW0xyM",{"id":1692,"title":1693,"body":1694,"description":10,"extension":13,"meta":1698,"name":1699,"navigation":16,"path":1700,"readingTime":18,"seo":1701,"stem":1702,"__hash__":1703},"authors\u002Fauthors\u002Fromain-koenig.md","Co-funder & Head of innovation",{"type":7,"value":1695,"toc":1696},[],{"title":10,"searchDepth":11,"depth":11,"links":1697},[],{},"Romain Koenig","\u002Fauthors\u002Fromain-koenig",{"title":1693,"description":10},"authors\u002Fromain-koenig","uyS8--eG2_ezyqRABcJnMJmQKKuSArhPWd14aUvFeEw",{"id":1705,"title":5,"body":1706,"description":10,"extension":13,"meta":1710,"name":1711,"navigation":16,"path":1712,"readingTime":18,"seo":1713,"stem":1714,"__hash__":1715},"authors\u002Fauthors\u002Fromaric-juniet.md",{"type":7,"value":1707,"toc":1708},[],{"title":10,"searchDepth":11,"depth":11,"links":1709},[],{},"Romaric Juniet","\u002Fauthors\u002Fromaric-juniet",{"title":5,"description":10},"authors\u002Fromaric-juniet","4Zb2artgT-eo-PHLXi3xi4d5t7s6PfhUxeSfXIikSUY",{"id":1717,"title":1464,"body":1718,"description":10,"extension":13,"meta":1722,"name":1723,"navigation":16,"path":1724,"readingTime":18,"seo":1725,"stem":1726,"__hash__":1727},"authors\u002Fauthors\u002Fstanyslas-bres.md",{"type":7,"value":1719,"toc":1720},[],{"title":10,"searchDepth":11,"depth":11,"links":1721},[],{},"Stanyslas Bres","\u002Fauthors\u002Fstanyslas-bres",{"title":1464,"description":10},"authors\u002Fstanyslas-bres","Xa0SahETuiN4q1jrmR2ych3moAqcZ2LbU7vSfEt2RuU",{"id":1729,"title":1730,"body":1731,"description":10,"extension":13,"meta":1735,"name":1736,"navigation":16,"path":1737,"readingTime":18,"seo":1738,"stem":1739,"__hash__":1740},"authors\u002Fauthors\u002Ftalent-acquisition.md","Talent Acquisition",{"type":7,"value":1732,"toc":1733},[],{"title":10,"searchDepth":11,"depth":11,"links":1734},[],{},"Équipe Talent Acquisition","\u002Fauthors\u002Ftalent-acquisition",{"description":10},"authors\u002Ftalent-acquisition","doDfE76txftQ4wIiKjJoDmSpyzSKk0tzlgVAp6-opAY",{"id":1742,"title":1464,"body":1743,"description":10,"extension":13,"meta":1747,"name":1748,"navigation":16,"path":1749,"readingTime":18,"seo":1750,"stem":1751,"__hash__":1752},"authors\u002Fauthors\u002Fvictor-borg.md",{"type":7,"value":1744,"toc":1745},[],{"title":10,"searchDepth":11,"depth":11,"links":1746},[],{},"Victor Borg","\u002Fauthors\u002Fvictor-borg",{"title":1464,"description":10},"authors\u002Fvictor-borg","-Za-JweoiP6hyclue_WkxMXdRUDTczPGlJf6AZckjUc",{"id":1754,"title":1464,"body":1755,"description":10,"extension":13,"meta":1759,"name":1760,"navigation":16,"path":1761,"readingTime":18,"seo":1762,"stem":1763,"__hash__":1764},"authors\u002Fauthors\u002Fvirgil-roger.md",{"type":7,"value":1756,"toc":1757},[],{"title":10,"searchDepth":11,"depth":11,"links":1758},[],{},"Virgil Roger","\u002Fauthors\u002Fvirgil-roger",{"title":1464,"description":10},"authors\u002Fvirgil-roger","DfVFe5j0bCgXeEr381ZYOM5DP4m-pWb93J9-m_muKJ0",{"id":1766,"title":1464,"body":1767,"description":10,"extension":13,"meta":1771,"name":1772,"navigation":16,"path":1773,"readingTime":18,"seo":1774,"stem":1775,"__hash__":1776},"authors\u002Fauthors\u002Fyukan-zhao.md",{"type":7,"value":1768,"toc":1769},[],{"title":10,"searchDepth":11,"depth":11,"links":1770},[],{},"Yukan Zhao","\u002Fauthors\u002Fyukan-zhao",{"title":1464,"description":10},"authors\u002Fyukan-zhao","LRPHugtAJnWHsmHxy9_SR5Zas_C5p-GR_uHEs1Fhk_E",1778159249175]