Commit | Line | Data |
11d28ce0 |
1 | package curry; |
2 | |
387705c8 |
3 | our $VERSION = '2.000000'; |
11d28ce0 |
4 | $VERSION = eval $VERSION; |
5 | |
b1b97495 |
6 | our $curry = sub { |
7 | my ($invocant, $code) = splice @_, 0, 2; |
8 | my @args = @_; |
9 | sub { $invocant->$code(@args => @_) } |
10 | }; |
11 | |
51f11f71 |
12 | sub curry::_ { &$curry } |
13 | |
11d28ce0 |
14 | sub AUTOLOAD { |
15 | my $invocant = shift; |
16 | my ($method) = our $AUTOLOAD =~ /^curry::(.+)$/; |
17 | my @args = @_; |
18 | return sub { |
19 | $invocant->$method(@args => @_); |
20 | } |
21 | } |
22 | |
23 | package curry::weak; |
24 | |
25 | use Scalar::Util (); |
26 | |
b1b97495 |
27 | $curry::weak = sub { |
28 | my ($invocant, $code) = splice @_, 0, 2; |
0f8925b5 |
29 | Scalar::Util::weaken($invocant) if length ref $invocant; |
b1b97495 |
30 | my @args = @_; |
31 | sub { |
132d8b36 |
32 | return unless defined $invocant; |
b1b97495 |
33 | $invocant->$code(@args => @_) |
34 | } |
35 | }; |
36 | |
51f11f71 |
37 | sub curry::_ { &$curry::weak } |
38 | |
11d28ce0 |
39 | sub AUTOLOAD { |
40 | my $invocant = shift; |
0f8925b5 |
41 | Scalar::Util::weaken($invocant) if length ref $invocant; |
ee6aa763 |
42 | my ($method) = our $AUTOLOAD =~ /^curry::weak::(.+)$/; |
11d28ce0 |
43 | my @args = @_; |
44 | return sub { |
132d8b36 |
45 | return unless defined $invocant; |
11d28ce0 |
46 | $invocant->$method(@args => @_); |
47 | } |
48 | } |
49 | |
50 | 1; |
51 | |
52 | =head1 NAME |
53 | |
54 | curry - Create automatic curried method call closures for any class or object |
55 | |
56 | =head1 SYNOPSIS |
57 | |
58 | use curry; |
59 | |
60 | my $code = $obj->curry::frobnicate('foo'); |
61 | |
62 | is equivalent to: |
63 | |
64 | my $code = sub { $obj->frobnicate(foo => @_) }; |
65 | |
51f11f71 |
66 | If you have a method name (or a coderef), you can call (as of version 2): |
67 | |
68 | my $code = $obj->curry::_($method => 'foo'); |
69 | |
11d28ce0 |
70 | Additionally, |
71 | |
72 | use curry::weak; |
73 | |
74 | my $code = $obj->curry::weak::frobnicate('foo'); |
75 | |
76 | is equivalent to: |
77 | |
78 | my $code = do { |
79 | Scalar::Util::weaken(my $weak_obj = $obj); |
cfc04a37 |
80 | sub { |
81 | return unless $weak_obj; # in case it already went away |
82 | $weak_obj->frobnicate(foo => @_) |
83 | }; |
11d28ce0 |
84 | }; |
85 | |
51f11f71 |
86 | Similarly, given a method name or coderef (as of version 2): |
b1b97495 |
87 | |
51f11f71 |
88 | my $code = $obj->curry::weak::_($method => 'foo'); |
b1b97495 |
89 | |
51f11f71 |
90 | There are also C<$curry::curry> and C<$curry::weak> globals that work |
91 | equivalently to C<curry::_> and C<curry::weak::_> respectively - you'll |
92 | quite possibly see them in existing code because they were provided in |
93 | pre-2.0 versions but they're unlikely to be the best option for new code. |
b1b97495 |
94 | |
11d28ce0 |
95 | =head1 RATIONALE |
96 | |
97 | How many times have you written |
98 | |
99 | sub { $obj->something($some, $args, @_) } |
100 | |
101 | or worse still needed to weaken it and had to check and re-check your code |
102 | to be sure you weren't closing over things the wrong way? |
103 | |
104 | Right. That's why I wrote this. |
105 | |
106 | =head1 AUTHOR |
107 | |
108 | mst - Matt S. Trout (cpan:MSTROUT) <mst@shadowcat.co.uk> |
109 | |
110 | =head1 CONTRIBUTORS |
111 | |
112 | None yet - maybe this software is perfect! (ahahahahahahahahaha) |
113 | |
114 | =head1 COPYRIGHT |
115 | |
bec94f83 |
116 | Copyright (c) 2012 the curry L</AUTHOR> and L</CONTRIBUTORS> |
11d28ce0 |
117 | as listed above. |
118 | |
119 | =head1 LICENSE |
120 | |
121 | This library is free software and may be distributed under the same terms |
122 | as perl itself. |