RobertDober/lab42_core

View on GitHub
params.json

Summary

Maintainability
Test Coverage
{"name":"Lab42::Core","tagline":"Ruby Core Module Extensions (in the spirit of lab419/core)","body":"# lab42\\_core\r\n\r\nRuby Core Module Extensions (in the spirit of lab419/core)\r\n\r\n## Motivation\r\n\r\nThis Ruby extension library tries to ease the developper's work by means of two fundamental\r\nconcepts.\r\n\r\n### Concepts\r\n\r\n* Extension of Behavior\r\n\r\n* Unification of Behavior\r\n\r\nThis is achieved by a conventional argument API on top of Ruby's core API, and is highly\r\nopinnionated.\r\n\r\n### Opinions\r\n\r\n#### The Symbol#to_proc kludge is a crime.\r\n\r\nAs useful as it is it has two shortcomings and I cannot find any viewpoint that allows\r\nme to not see at least one of these two.\r\nEither I adhere to the point of view, that it cannot be the responsability of `Symbol`\r\nto transform itself to a method. Or if I could I would need to point out that it does\r\nit very badly. Here is my cannonical example for that point.\r\n\r\n```ruby\r\n  (1..10).filter( &:even? )\r\n  # and how can I do this?\r\n  (1..10).filter( &:>, 10 )???\r\n```\r\n\r\nI could not even come up with a & based notation that would parse...\r\n\r\nAs YHS is very heavily influenced by functional style it might not come as a surprise\r\nthat he thinks that the responsibility to convert a symbol to behavior, is to be with\r\nthe behavior consumer.\r\nOf course there are countless behavior consumers, as a matter of fact one could call\r\nthem Higher Order Methods, and it would be impractical not to provide one single point\r\nof responsability for that behavior provision. But by freeing `Symbol` from this \r\nresponsibility we can accomplish much more in a single, dedicated place.\r\n\r\n\r\nThis dedicated place, which is automatically loaded if you require `lab42/core` does\r\nhowever not introduce the API methods into `Kernel`. If you want that to happen, you\r\nneed to require `lab42/core/kernel` so that it is up to you, if you want the `Kernel`\r\nnamespace polluted or not.\r\n\r\nThis too is a guiding principle of this gem. Require `lab42/core` and get the `Lab42`\r\nnamespace filled up with everything available. Require anything in particular to get\r\nonly part of it and / or monkey patches for `Kernel`, `Enumerable` and their friends.\r\n\r\n#### Enumerables Need a Unified API\r\n\r\nAnd this goes beyond passing the `Symbol#to_proc` kludge. Therefore one can count on\r\nthe `Behavior` based implementation of the API.\r\n\r\n# The API\r\n\r\n## Behavior\r\n\r\n\r\n## Dir\r\n\r\n\r\n```ruby\r\n  require 'lab42/core/dir'\r\n  Dir.files \"**/*\" do | partial_path, full_path |\r\n  end\r\n```\r\n\r\n## Enumerable\r\n\r\n```ruby\r\n  require 'lab42/core/enumerable'\r\n\r\n  enum.grep2 expr # ===>\r\n  enum.partition{ |ele| expr === ele }\r\n  # But for non behavior parameters ...\r\n  enum.partition expr\r\n  # the same effect can be achieved by the predicate semantics.\r\n```\r\n\r\n## Hash\r\n\r\n```ruby\r\n  require 'lab42/core/hash'\r\n\r\n  {a: 42, b: 43}.only :a, :c # ===> {a: 42}\r\n```\r\n\r\n## Fn\r\n\r\n### Access to methods\r\n\r\n```ruby\r\n  require 'lab42/core/fn'\r\n\r\n  # Get method of an object\r\n  printer = Kernel.fn.puts\r\n  printer.( 42 )   \r\n  2.times(&printer)\r\n\r\n  # It also extends some enumerable methods for easier execution\r\n  %w{hello world}.each printer\r\n```\r\n\r\nThusly `fn` gives us access to methods of objects, but what about instance methods?\r\n\r\n### Access to instance methods\r\n\r\nIs realized via `fm`.\r\n\r\n```ruby\r\n  require 'lab42/core/fn'\r\n\r\n  (1..100).reduce Fixnum.fm.+ # ---> 5050\r\n```\r\n\r\n### Objects as constant procs\r\n\r\nWhile `Object#self` will return the obvious, so will by extension `object.fn.self`.\r\n\r\nThis can be very useful, e.g. in this nice way to create an empty array ;)\r\n\r\n```ruby\r\n  (1..100).filter(false.fn.self)\r\n```\r\n\r\nIf you hesitate to use this all, have a look into Kernel#const_lambda\r\n\r\n### Partial Application\r\n\r\n```ruby\r\n  f = Array.fm.push :next\r\n  [[],[1]].map( f ) # ---> [[:next], [1, :next]]\r\n\r\n  a=[]\r\n  f = a.fn.push :first\r\n  f.(1) # a ---> [:first, 1]\r\n```\r\n\r\n## OpenObject\r\n\r\nImmutable Open Objects\r\n\r\nThey are described in detail [here](dox/OpenObject.md) \r\n","google":"","note":"Don't delete this file! It's used internally to help with page regeneration."}