{"id":18521802,"url":"https://github.com/simphotonics/lazy_memo","last_synced_at":"2025-04-09T09:33:27.463Z","repository":{"id":56833756,"uuid":"306096510","full_name":"simphotonics/lazy_memo","owner":"simphotonics","description":"Lazy variables that can be re-initialized and memoized functions for Dart. ","archived":false,"fork":false,"pushed_at":"2024-04-04T10:29:36.000Z","size":133,"stargazers_count":4,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-24T04:50:53.426Z","etag":null,"topics":["cache","dart2","lazy-initialization","memoize","null-safety"],"latest_commit_sha":null,"homepage":"https://pub.dev/packages/lazy_memo","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/simphotonics.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-10-21T17:17:47.000Z","updated_at":"2024-05-18T10:08:49.000Z","dependencies_parsed_at":"2024-04-04T11:30:35.320Z","dependency_job_id":"5eaa625c-cf2e-4b89-aade-66a7a77c863e","html_url":"https://github.com/simphotonics/lazy_memo","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simphotonics%2Flazy_memo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simphotonics%2Flazy_memo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simphotonics%2Flazy_memo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simphotonics%2Flazy_memo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/simphotonics","download_url":"https://codeload.github.com/simphotonics/lazy_memo/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248012864,"owners_count":21033254,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cache","dart2","lazy-initialization","memoize","null-safety"],"created_at":"2024-11-06T17:27:40.770Z","updated_at":"2025-04-09T09:33:25.439Z","avatar_url":"https://github.com/simphotonics.png","language":"Dart","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# Lazy Variables for Dart\n[![Dart](https://github.com/simphotonics/lazy_memo/actions/workflows/dart.yml/badge.svg)](https://github.com/simphotonics/lazy_memo/actions/workflows/dart.yml)\n\n## Introduction\n\nMinimizing CPU and memory usage are two important goals of software optimization.\nIf sufficient memory is available, costly operations (such as sorting a large list)\ncan be avoided by storing the result and reusing it as long as the relevant\ninput (e.g. the unsorted list) has not changed.\nThe technique of storing the result of function calls\nwas coined [memoization][memoization].\n\nA different strategy to minimize CPU usage is to delay the initialization of variables.\n[Lazy initialization][lazy_initialization] is particularly\nuseful in event driven scenarios where there is no definite execution path and\na certain variable might never be used.\n\nThe package [`lazy_memo`][lazy_memo] provides generic classes that can be used\nto define [lazy variables](#1-lazy-variables) and\n[memoized functions](#4-memoized-functions).\n\n\n## Usage\n\nTo use this library include [`lazy_memo`][lazy_memo] as a dependency\nin your pubspec.yaml file.\n\u003cbr\u003e\n\n### 1. Lazy Variables\n\n**Note**: To define variables that are going to be initalized *once* use Dart's\n`late` modifier.\n\nTo define lazy variables that can be marked for *re-initialization*\nuse the generic class [`Lazy\u003cT\u003e`][Lazy].\nIt is often useful to declare *lazy* variables\nusing Darts *late* modifier since it makes it possible to\ninitialize e.g. a final instance variable at the point of definition:\n```Dart\nclass A{\n  late final _value = Lazy\u003cdouble\u003e(() =\u003e costlyCalculation());\n  double value get =\u003e _value();\n}\n```\n\n1. Lazy variables are declared using the constructor of\n   the generic class [`Lazy\u003cT\u003e`][Lazy].\n2. The constructor requires a callback, [`ObjectFactory`][ObjectFactory],\n   that returns an  object of type `T`.\n3. To access the cached object, the lazy variable is called like a function\n   (see example below).\n4. The optional parameter `updateCache` can be used to request an\n   update of the cached object.\n   If `updateCache` is true, the object is re-initialized\n   by calling the object factory [`ObjectFactory`][ObjectFactory] with the\n   current value of the input arguments.\n\n```Dart\nimport 'dart:math';\n\nimport 'package:lazy_memo/lazy_memo.dart';\n\n// To run this program navigate to\n// the root folder of your local copy of 'lazy_memo' and use the command:\n//\n// # dart example/bin/lazy_example.dart\nvoid main() {\n  print('Running lazy_example.dart.\\n');\n\n  final random = Random();\n  final mean = 4.0;\n\n  print('Generating a random sample with size 5000 and mean: 4.0:');\n  // Generating a random sample\n  final sample = List\u003cdouble\u003e.generate(\n      5000, (_) =\u003e -mean * log(1.0 - random.nextDouble()));\n\n  // Initializing lazy variables\n  final sampleSum = Lazy\u003cdouble\u003e(\n    () =\u003e sample.reduce((sum, current) =\u003e sum += current),\n  );\n\n  // Calculating sample mean\n  final sampleMean = Lazy\u003cdouble\u003e(\n    () =\u003e sampleSum(updateCache: true) / sample.length,\n  );\n\n  print('  Initial value of sampleSum: ${sampleSum()}');\n  print('  Initial value of sampleMean: ${sampleMean()}\\n');\n  print('Adding outliers to random sample: [1500.0, 1200.0]');\n\n  // Adding outliers\n  sample.addAll([1500.0, 1200.0]);\n\n  print('  Updated value of sampleMean: '\n      '${sampleMean(updateCache: true)}');\n  print('  Updated value of sampleSum: ${sampleSum()}');\n}\n\n```\n\u003c/details\u003e\n\n\u003cbr\u003e\n\n### 2. Dependent Lazy Variables\n\nIt is possible to declare dependent lazy variables by using an\nexpression containing one lazy variable to declare another lazy variable.\nIn the example above, `sampleMean` depends on `sampleSum` since the callback\npassed to the constructor of `sampleMean` references `sampleSum`.\n\nThe optional parameter `updateCache` can be used strategically to trigger an\nupdate of cached variables along the\ndependency tree. In the example above, `sampleSum(updateCache: true)`\nis called every time `sampleMean` is updated.\nTherefore, an update of `sampleMean` triggers an update of `sampleSum`.\n\nNote: An update of a lazy variable can also be requested by calling the\nmethod: `updateCache()`.\n\n\u003cbr\u003e\n\n### 3. Lazy Collections\n\nLazy variables can be used to cache objects of type `List`, `Set`, `Map`, etc.\nHowever, as the example below demonstrates, the cached object can be modified.\n```Dart\nfinal lazyList = Lazy\u003cList\u003cint\u003e\u003e(() =\u003e [1, 2, 3]);\nfinal list = lazyList();\nlist.add(4); // lazyList() now returns: [1, 2, 3, 4]\n```\nIn order to prevent users from (inadvertently) modifying the cached object one\nmay use the classes `LazyList\u003cT\u003e`, `LazySet\u003cT\u003e`, and `LazyMap\u003cK, V\u003e`. These\nclasses cache and return an *unmodifiable view* of the collection.\n\n------\n\n### 4. Memoized Functions\n\nMemoized functions maintain a lookup table of previously calculated results.\nWhen called,\na memoized function checks if it was called previously with the same set of arguments.\nIf that is the case it will return a cached result.\n\nMemoizing a function comes at the cost of additional indirections,\nhigher memory usage, and the complexity of having to maintain a function table.\nFor this reason, memoization should be used for\n**computationally expensive** functions that are likely to be\ncalled **repeatedly** with the **same** set of **input arguments**.\nExamples include: repeatedly accessing statistics of a large\ndata sample, calculating the factorial of an integer,\nrepeatedly evaluating higher degree polynomials.\n\nThe example below demonstrates how to define the *memoized functions*\n`factorial(n)` and `combinations(n, k)`, k-combinations of n objects.\nNote: For the sake of simplicity, validation of arguments is omitted. A\ncomplete version of these functions is provided with the library\n[`utils.dart`][utils].\n\n\u003cdetails\u003e  \u003csummary\u003e Click to show souce code. \u003c/summary\u003e\n\n ```Dart\n  import 'package:lazy_memo/lazy_memo.dart';\n\n  /// Computationally expensive function with a single argument.\n  int _factorial(int x) =\u003e (x == 0 || x == 1) ? 1 : x * _factorial(x - 1);\n\n  /// Returns the factorial of a positive integer.\n  final factorial = MemoizedFunction(\n    _factorial,\n    functionTable: {8: 40320}, // Optional initial function table.\n  );\n\n  /// Computationally expensive function with two arguments.\n  int _combinations(int n, int k) {\n    if (k \u003e n ~/ 2) {\n      return _combinations(n, n - k);\n    } else if (k \u003e n) {\n      return 0;\n    } else {\n      int result = 1;\n      int m = 1;\n      for (var i = n; i \u003e n - k; i--) {\n        result = (result * i) ~/ m;\n        m++;\n      }\n      return result;\n    }\n  }\n\n  /// Returns the number of k-combinations of n distinct objects. More formally,\n  /// let S be a set containing n distinct objects.\n  /// Then the number of subsets containing k objects is given\n  /// by combinations(n, k).\n  /// * combinations(n, n) = 1\n  /// * combinations(n, k) = combinations(n, n - k)\n  /// * combinations(n, 0) = 1\n  final combinations = MemoizedFunction2(_combinations);\n\n  // To run this program navigate to\n  // the root folder of your local copy of 'lazy_memo' and use the command:\n  //\n  // # dart example/bin/lazy_function_example.dart\n  void main() {\n    print('Running lazy_function_example.dart.\\n');\n\n    print('------------- Factorial --------------');\n    print('Calculates and stores the result');\n    print('factorial(12) = ${factorial(12)}\\n');\n\n    // The current function table\n    print('Function table:');\n    print(factorial.functionTable);\n    print('');\n\n    // Returning a cached result.\n    print('Cached result:');\n    print('factorial(12) = ${factorial(12)}');\n\n    print('\\n----- k-combinations of n objects -----');\n\n    print('Calculates and stores the result of: ');\n    print('combinations(10, 5): ${combinations(10, 5)}');\n    print('');\n\n    print('The current function table');\n    print(c.functionTable);\n    print('');\n\n    print('Returns a cached result.');\n    print('combinations(10, 5): ${combinations(10, 5)}');\n  }\n\n```\n\u003c/details\u003e\n\u003cdetails\u003e  \u003csummary\u003e Click to show console output. \u003c/summary\u003e\n\n ```Console\n $ dart example/bin/lazy_example.dart\n Running lazy_function_example.dart.\n\n ------------- Factorial --------------\n Calculates and stores the result\n factorial(12) = 479001600\n\n Function table:\n {8: 40320, 12: 479001600}\n\n Cached result:\n factorial(12) = 479001600\n\n ----- k-combinations of n objects -----\n Calculates and stores the result of:\n combinations(10, 5): 252\n\n The current function table\n {10: {5: 252}}\n\n Returns a cached result.\n combinations(10, 5): 252\n ```\n\n\u003c/details\u003e\n\n## Examples\n\nThe source code listed above is available in the folder [example].\n\n\n## Features and bugs\n\nPlease file feature requests and bugs at the [issue tracker].\n\n[issue tracker]: https://github.com/simphotonics/lazy_memo/issues\n\n[example]: https://github.com/simphotonics/lazy_memo/tree/main/example\n\n[lazy_memo]: https://pub.dev/packages/lazy_memo\n\n[lazy_initialization]: https://en.wikipedia.org/wiki/Lazy_initialization\n\n[Lazy]: https://pub.dev/documentation/lazy_memo/latest/lazy_memo/Lazy-class.html\n\n[memoization]: https://en.wikipedia.org/wiki/Memoization\n\n[null-safety]: https://dart.dev/null-safety\n\n[ObjectFactory]: https://pub.dev/documentation/lazy_memo/latest/lazy_memo/ObjectFactory.html\n\n[utils]: https://github.com/simphotonics/lazy_memo/tree/main/lib/src/utils.dart","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimphotonics%2Flazy_memo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsimphotonics%2Flazy_memo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimphotonics%2Flazy_memo/lists"}