[{"name":"UseMemoizedLazyLambda","comment":" Require calling `lazy` exclusively at the top level of a point free function with a lambda expression as its first argument.\n\n@docs rule\n\n","unions":[],"aliases":[],"values":[{"name":"rule","comment":" This is a **highly** opinionated rule that requires all calls of `lazy` to be at the top level of a point-free function with a lambda expression as the first argument.\nThis prevents errors in the view function argument to lazy.\n\n\n### What does this look like?\n\n    view : Model -> Html a\n    view = lazy (\\model -> ...)\n\n    view2 : Model -> Time.Zone -> Html a\n    view2 = lazy (\\model timezone -> ...)\n\n\n## Motivation\n\nProper use of `lazy` is **extremely** hard to get right and on top of that maintaining correctness in the presence of refactorings is even worse!\n\nIn order for `lazy` to be able to skip evaluating the view function (and thus avoiding a potentionally expensive computation)\nthe Elm runtime will check each argument to `lazy` against the value from the previous call using Javascript reference equality (think `===`). Note\nthat this includes the first function argument to lazy as well!\n\nA very common source of errors is to not have a top-level function as the first arugment\nto an unmemoized lazy call, but instead having a partially applied function or a function defined in a let or a function composition or a lambda expression.\n\nFor example all of the following functions are bad and will result in lazy calls _never_ being cached:\n\n    badView1 : Model -> Int -> Html a\n    badView1 model counter =\n        lazy (viewFunc counter) model\n\n    badView2 : Model -> Html a\n    badView2 model =\n        lazy (\\m -> viewFunc model) model\n\n    badView3 : Model -> Html a\n    badView3 model =\n        let viewFunc m = ...\n        in\n        lazy viewFunc model\n\n\n## A Better Path\n\nHowever, if we define our view to be point-free, then our application of the view function to lazy is effectively memoized, and the paritially applied and lambda styles above are permissable.\n\nFor example:\n\n    goodView1 : Model -> Html a\n    goodView1 =\n        lazy (viewFunc x)\n\n    goodView2 : Model -> Html a\n    goodView2 =\n        lazy (\\model -> viewFunc model)\n\nAs this is an opinionated rule, we choose to enforce the lambda expression form for several reasons:\n\n1.  It forces the remaining lazy arguments to have explicitly defined local names, which improves readability as the point-free requirement means they are not named in the function definition itself.\n2.  The code for the entire view can remain in one function, if the author so wishes.\n3.  It just plain looks like a standard function definition (e.g. `func = \\x1 x2 -> x1 + x2`). Some functional languages (like Roc) even require functions to be defined in this form.\n\n\n## Minutiae\n\nThis rule also adds a couple additional contraints that aren't stricly necessary, but we think are helpful for clarity:\n\n1.  Functions calling lazy must have a type signature (which assists the other rules in this package).\n2.  The lambda expression argument must be of full airity for the given `lazy` function. `lazy` requires a labmda expression accepting 1 argument, `lazy2` requires a lambda with 2 arguments and so on.\n\n\n## Additional Notes\n\nThis rule applies to all calls of `lazy` ... `lazy8` from [Html.Lazy](https://package.elm-lang.org/packages/elm/html/latest/Html-Lazy)\nand `lazy` ... `lazy7` from [Html.Styled.Lazy](https://package.elm-lang.org/packages/rtfeldman/elm-css/latest/Html.Styled.Lazy)\n\n","type":"Review.Rule.Rule"}],"binops":[]}]