lazebny / ramda-ruby

Ruby port of http://ramdajs.com
MIT License
108 stars 7 forks source link
functional-programming ramda ruby

Ramda Ruby

This is a ruby version of Ramda Js library.

Gem Version Functions Travis badge AppVeyor status Coverage Status Code Climate Badge Inch CI Dependency Status License

Information

This library uses some stuff like curry and __ which reduces performance. Please review benchmarks section.

Installation

Add this line to your application's Gemfile:

gem 'ramda-ruby'

And then execute:

$ bundle

Or install it yourself as:

$ gem install ramda-ruby

And then require:

require 'ramda'

Documentation

You can use Ramda docs as a documentation or to check Ruby examples.

Algebraic structures

Methods which supports algebraic types:

Supported libraries (comparison):

dry-monads

works with ruby >= 2.1

kleisli works from this fork:


gem 'kleisli', git: 'git@github.com:lazebny/kleisli.git', branch: 'ramda-ruby'

Differences:

Usage

Pointless Style:


  R = Ramda

  players = [
    { name: 'Andrey', score: 100 },
    { name: 'Ivan', score: 200 },
    { name: 'Masha', score: 150 }
  ]

  best_player = R.pipe(R.sort_by(R.prop(:score)), R.reverse, R.head, R.prop(:name))
  best_player.call(players) # Ivan

Placeholder:


  reset_to_default = R.merge(R.__, x: 0)
  reset_to_default.call(x: 5, y: 2) # { x: 0, y: 2 }

Transducers:


  appender = R.flip(R.append)

  xform = R.map(R.add(10))
  R.transduce(xform, appender, [], [1, 2, 3, 4]) # [11, 12, 13, 14]

  xform = R.filter(:odd?.to_proc)
  R.transduce(xform, appender, [], [1, 2, 3, 4]) # [1, 3]

  xform = R.compose(R.map(R.add(10)), R.take(2))
  R.transduce(xform, appender, [], [1, 2, 3, 4]) # [11, 12]

  xform = R.compose(R.filter(:odd?.to_proc), R.take(2))
  R.transduce(xform, R.add, 100, [1, 2, 3, 4, 5]) # 104)
  R.transduce(xform, appender, [], [1, 2, 3, 4, 5]) # [1, 3])
  R.into([], xform, [1, 2, 3, 4, 5]) # [1, 3])

With algebraic structures:


  # ap
  R.ap(R.ap(Maybe.of(R.add), Maybe.of(3)), Maybe.of(5)) # Some(8)

  # chain
  R.chain(->(x) { Maybe.of(R.add(5, x)) }, Maybe.of(3)) # Some(8)

  # map
  R.map(R.add(3), Maybe.of(5)) # Some(8)

  # lift
  add_m = R.lift(R.add)
  add_m.call(Maybe.of(3), Maybe.of(5)) # Some(8)

  # lift_n
  add_m = R.lift_n(3, -> (a, b, c) { a + b + c })
  add_m.call(Maybe.of(3), Maybe.of(5), Maybe.of(10)) # Some(18)

Change exceptions handler:


  # To use a default 'with_narrow' handler:
  Ramda.exception_handler = nil
  # the same as:
  Ramda.exception_handler = -> Ramda::ExceptionHandler.method(:with_narrow)

  # Set a custom handler:
  Ramda.exception_handler = -> (e, _method_name) { raise e, e.exception, e.backtrace }
  # the same as:
  Ramda.exception_handler = -> Ramda::ExceptionHandler.method(:default)

Ramda in debug mode shows calls trace. Notice: trace is shown only for Ramda functions and not for regular procs. If you want to show a whole trace you can wrap your proc in Ramda.curry function (pleaes see example below).

Enable debug mode:


  Ramda.debug_mode = true

  # Example:

  Ramda.filter(Ramda.curry(:even?.to_proc, [1, 2, 3, 4])

  # -> curry(#<Proc:0x...@/srv/app/spec/ramda/list_spec.rb:130 (lambda)>) # #<Proc:0x... (lambda)>
  # -> curry(1) # false
  # -> curry(2) # true
  # -> curry(3) # false
  # -> curry(4) # true
  # -> filter(#<Proc:0x0055ff3fad4640 (lambda)>, 1, 2, 3, 4) # [2, 4]

Resources

Benchmarks

Send all results to STDOUT

bundle exec rake ramda:run_benchmark

Send one function type results to STDOUT

bundle exec rake ramda:run_benchmark[bench/list/*]

Update all files in bench_results

bundle exec rake ramda:run_benchmark_to_file

Update one type of function in bench_results

bundle exec rake ramda:run_benchmark_to_file[bench/list/*]

Development

You can use either regular approach with installing gems on local machine or with docker-compose which is handy when you are playing with ruby versions.

With docker-compose:

  1. Install Docker
  2. Install Docker Compose
  3. Run tests

touch .bashrc.docker .pry_history.docker
docker-compose run --rm app bash
bundle
rspec

To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.

Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Make changes
  4. Check with Rubocop and resolve all issues(rubocop -aD)
  5. Commit your changes (git commit -am 'Add some feature')
  6. Push to the branch (git push origin my-new-feature)
  7. Create new Pull Request

License

The gem is available as open source under the terms of the MIT License.