Class: Curry
- Inherits:
-
Object
- Object
- Curry
- Defined in:
- lib/curry.rb
Overview
Ruby Murray is a Ruby port of Perl’s Sub::Curry library that allows curried blocks and methods to be handled in a pretty flexible way.
See search.cpan.org/~lodin/Sub-Curry-0.8/lib/Sub/Curry.pm and search.cpan.org/~lodin/Sub-Curry-0.8/lib/Sub/Curry/Cookbook.pod for details on the original, and some general background.
Simple usage:
curry = lambda { |*args| args }.curry(Curry::HOLE, "foo", Curry::HOLE)
curry.call(1,3) # => [1, "foo", 3]
curry = "string".method(:slice).curry(Curry::HOLE, 2)
curry.call(0) # => "st"
curry.call(2) # => "ri"
The curry
methods are provided by the Curriable
module, which simply provides convenient wrapping for Curry.new. There are a few variations between the various forms, but mostly they are equivalent and can be used interchangeably.
See TestCurry (and click the method signatures) for more usage.
Curried procs are immutable once created. If you wish to apply further special spice to a curried method, you may do so either using the instance method new
to create a new curried proc by applying new spice to the old spice, or by passing the special spices directly to a call
.
You can download Ruby Murray (with documentation and explanatory comments) from roscopeco.co.uk/ruby-quiz-entries/64/curry.rb
Defined Under Namespace
Classes: AntiSpiceArg, BlackHoleArg, HoleArg, LazySpice, SpiceArg
Constant Summary collapse
- VERSION =
'0.1.2'
- WHITEHOLE =
A whitehole removes the blackhole, but the spice that has been put into the blackhole remains since blackholes themselves don’t store anything.
Object.new
- ANTIHOLE =
An antihole put in a hole makes the hole disappear. If the spice is 1, <HOLE>, 3, <HOLE>, 4 and 2, <ANTIHOLE>, 5 is applied then the result will become 1, 2, 3, 4, 5.
Object.new
- HOLE =
A hole is what it sounds like: a gap in the argument list. Later, when the subroutine is called the holes are filled in. So if the spice is 1, <HOLE>, 3 and then 2, 4 is applied to the curried proc, the resulting argument list is 1, 2, 3, 4.
Holes can be called “scalar inserters” that default to
nil
. HoleArg.instance
- BLACKHOLE =
A blackhole is like a hole for lists that never gets full. There’s an imaginary untouchable blackhole at the end of the spice. The blackhole thusly inserts the new spice before itself. The blackhole never gets full because nothing is ever stored in a blackhole as it isn’t a hole really…
Blackholes are used to move the point of insertion from the end to somewhere else, so you can curry the end of the argument list.
Blackholes can be called “list inserters” that defaults to the empty list.
BlackHoleArg.instance
- ANTISPICE =
An antispice is like a hole except that when it’s filled it disappears. It’s like a combination of a hole and an antihole. If the spice is 1, <ANTISPICE>, 3 and 2, 4 is applied, then the result will become 1, 3, 4.
AntiSpiceArg.instance
Instance Attribute Summary collapse
-
#spice ⇒ Object
readonly
The raw spice held by this curried proc.
-
#uncurried ⇒ Object
readonly
The block (
Proc
) for which arguments are curried.
Instance Method Summary collapse
-
#[](*args) ⇒ Object
Had some trouble with aliases and doc so it’s done this way.
-
#call(*args, &blk) ⇒ Object
call-seq: some_curry.call(*args) { |b| … } -> result some_curry { |b| … } -> result Call the curried proc, passing the supplied arguments.
-
#initialize(*spice, &block) ⇒ Curry
constructor
call-seq: Curry.new(*spice) { |*args| … } -> #<Curry…> Curry.new(callable, *spice) -> #<Curry…> Create a new curry with the specified spice and block or callable object.
-
#new(*spice) ⇒ Object
call-seq: some_curry.new(*spice) -> #<Curry…> Create a new curried proc by applying the supplied spice to the current spice in this curried proc.
-
#to_proc ⇒ Object
call-seq: some_curry.to_proc -> #<Proc…> Convert to a proc.
Constructor Details
#initialize(*spice, &block) ⇒ Curry
call-seq:
Curry.new(*spice) { |*args| ... } -> #<Curry...>
Curry.new(callable, *spice) -> #<Curry...>
Create a new curry with the specified spice and block or callable object. The second form requires only that the first argument respond_to?(:call)
172 173 174 175 176 |
# File 'lib/curry.rb', line 172 def initialize(*spice, &block) block = block || (spice.shift if spice.first.respond_to?(:call)) raise ArgumentError, "No block supplied" unless block @spice, @uncurried = spice, block end |
Instance Attribute Details
#spice ⇒ Object (readonly)
The raw spice held by this curried proc. May contain special spices.
160 161 162 |
# File 'lib/curry.rb', line 160 def spice @spice end |
#uncurried ⇒ Object (readonly)
The block (Proc
) for which arguments are curried.
163 164 165 |
# File 'lib/curry.rb', line 163 def uncurried @uncurried end |
Instance Method Details
#[](*args) ⇒ Object
Had some trouble with aliases and doc so it’s done this way
202 203 204 |
# File 'lib/curry.rb', line 202 def [](*args) # :nodoc: call(*args) end |
#call(*args, &blk) ⇒ Object
call-seq:
some_curry.call(*args) { |b| ... } -> result
some_curry[*args] { |b| ... } -> result
Call the curried proc, passing the supplied arguments. This method resolves all special spices and passes the resolved arguments to the block. If a block is passed to call
it will be passed on as a block argument to the curried method only if this curry was created from a Method
. Curries created from a block passed to Curry.new (or from Proc#curry) cannot have block arguments passed to them.
Unlike Perl’s Sub::Curry implementation, special spices may be passed in the call arguments, and are applied as with new. This means that whiteholes and antiholes can be passed in to make single-call modifications to the argument spice. This probably isn’t as great on performance but it’s more fun.
see also new
197 198 199 |
# File 'lib/curry.rb', line 197 def call(*args, &blk) @uncurried.call(*call_spice(args), &blk) end |
#new(*spice) ⇒ Object
call-seq:
some_curry.new(*spice) -> #<Curry...>
Create a new curried proc by applying the supplied spice to the current spice in this curried proc. This does not simply append the spices - Arguments in the supplied spice are applied to the curried spice arguments, with black/white hole and antiholes operating as documented.
See also call
.
216 217 218 |
# File 'lib/curry.rb', line 216 def new(*spice) Curry.new(*merge_spice(spice), &@uncurried) end |
#to_proc ⇒ Object
call-seq:
some_curry.to_proc -> #<Proc...>
Convert to a proc
224 225 226 227 |
# File 'lib/curry.rb', line 224 def to_proc # since we're immutable we can keep this @extern_proc ||= method(:call).to_proc end |