File Coverage

blib/lib/Data/Variant.pm
Criterion Covered Total %
statement 110 137 80.2
branch 32 62 51.6
condition 1 3 33.3
subroutine 16 16 100.0
pod 5 6 83.3
total 164 224 73.2


line stmt bran cond sub pod time code
1             # Data::Variant.pm -- Algebraic datatypes for Perl
2             #
3             # Copyright (c) 2004-2013 Viktor Leijon (leijon@ludd.ltu.se) All rights reserved.
4             # This program is free software; you can redistribute it and/or modify
5             # it under the same terms as Perl itself.
6             #
7              
8             =head1 NAME
9              
10             Data::Variant - Variant datatypes for perl.
11              
12             =head1 SYNOPSIS
13              
14             use Data::Variant;
15             use vars qw(&Empty &Leaf &Node);
16              
17             register_variant("Tree","Empty","Leaf ","Node Tree Tree");
18             my $tree = Node((Node ((Leaf 3), (Leaf 4))), Leaf 5);
19              
20             sub printTree {
21             my $tree = shift;
22             my ($data, $left, $right);
23              
24             print "Data $data\n"
25             if (match $tree,"Leaf", $data);
26             printTree($left), printTree($right)
27             if (match $tree,"Node",$left,$right);
28             }
29              
30             =head1 DESCRIPTION
31              
32             This module offers a Haskell/O'Caml-style for variant data types. You
33             can register data types and then both construct them using the
34             constructors give, and match against them as conditionals. The best
35             way to understand what the module does is probably to look at the
36             included examples. Pattern matching together with variants is (in the
37             author's opinion) one of the very most useful features in Haskell and
38             while this implementation is very informal it serves the same
39             practical purpose.
40              
41             There is some (very limited) typechecking available to make sure that
42             you use your data structure as intended (well, as declared really but
43             if you are wise these two coincide).
44              
45             For the programmer unused to pattern matching, looking at the
46             synoposis or the examples is probably the easiest way to get an idea
47             of how to use the module.
48              
49             =head1 FUNCTIONS
50              
51             =over 4
52              
53             =cut
54              
55             package Data::Variant;
56              
57             # Requires perl 5.8.0
58 1     1   25740 use 5.8.0;
  1         3  
  1         48  
59 1     1   5 use warnings;
  1         2  
  1         26  
60 1     1   5 use strict;
  1         7  
  1         41  
61 1     1   5 use Carp;
  1         2  
  1         75  
62 1     1   7 use Exporter;
  1         2  
  1         45  
63 1     1   1063 use Data::Dumper;
  1         11830  
  1         76  
64 1     1   1081 use Switch;
  1         43911  
  1         6  
65              
66             our $VERSION = "0.05";
67              
68             our @ISA = qw(Exporter);
69             our @EXPORT = qw(register_variant match set_match mkpat);
70             our $DEBUG = 0;
71              
72             sub constructor;
73              
74             # Keep track of all existing datatypes.
75             our %dataTypes;
76             # This is a back-mapping from constructors to variant datatypes.
77             # Do we need both this and dataTypes? Yes, it is handy.
78             our %constructors;
79             # This is the object pre-set for following calls to match
80             our $matchObject;
81              
82             =item register_variant(NAME [, CONSTRUCTORS])
83              
84             This function registers a variant with the module. The C should
85             be a string uniquely naming the variant.
86              
87             Next should come a list of constructors. A constructor can come in one
88             of two forms:
89              
90             =over 8
91              
92             =item * A list reference
93              
94             The first element of the list should be a string, containing the name
95             of the constructor. This name will be the name of the constructor
96             function that will be used to construct new instances of this
97             variant. By convention constructors start with a capital letter.
98              
99             The other elements should be strings indicating the type of the
100             variable stored in this position.
101              
102             We are allowed the following types in this version:
103              
104             =over 12
105              
106             =item * C<< >> - Numbers
107              
108             =item * C<< >> - Strings
109              
110             =item * C<< >> - References
111              
112             =item * C<< * >> - wildcard, allow any type for this field
113              
114             =item * I< Type > - allow only other variants of I.
115              
116             =back
117              
118             This information is later used for some basic typechecking, see
119             L.
120              
121             =item * A single string
122              
123             The string should just be a space separated list, basically containing
124             the same as if it was list reference instead.
125              
126              
127             =back
128              
129             B The constructor has to be globally unique within your program.
130              
131             Examples:
132            
133             # Registers the variant Tree with the constructors:
134             # Empty, Leaf and Node.
135             # The Empty node carries no data, the leaf node carries an int
136             # and an internal node carries two subtrees.
137             register_variant("Tree","Empty","Leaf ","Node Tree Tree");
138              
139             # Essentially the same, but using list reference form.
140             register_variant("Tree2", ["Empty2"],["Leaf2",""],["Node2", "Tree2","Tree2"]);
141              
142             # The Maybe type from Haskell, often called an "optional value".
143             register_variant("Maybe", "Nothing", "Just *");
144              
145             =cut
146              
147             sub register_variant {
148 1     1 1 849 my $dt = shift;
149              
150 1 50       7 if (exists $dataTypes{$dt}) {
151 0         0 carp "Registering datatype $dt twice";
152             }
153              
154 1         4 my %altHash;
155 1         6 while($_ = shift) {
156 3         3 my ($con,@fields);
157              
158             # The function can be called either with space separated strings
159             # or with array references.
160 3 50       9 if (ref $_) {
161 0         0 ($con, @fields) = @{$_};
  0         0  
162             } else {
163 3         11 ($con, @fields) = split;
164             }
165              
166 3 50       9 carp "The constructor $con is repeated. in $dt\n"
167             if exists $altHash{$con};
168              
169 3         6 $altHash{$con} = \@fields;
170 3         13 $constructors{$con} = $dt;
171             }
172            
173              
174 1         3 $dataTypes{$dt} = \%altHash;
175 1 50       7 print Dumper(\%dataTypes) if $DEBUG;
176              
177             # Last, export this variant to the caller so he gets the constructors.
178 1         8 export_variant($dt,caller());
179              
180 1         5 return 1;
181             }
182              
183             =item export_variant(VARIANT)
184              
185             =item $val->export_variant
186              
187             As a function, this function exports the variant named by the argument
188             C to the calling module, making the constructors available in
189             the module.
190              
191             As a method call, on an object that is a variant value, it exports the
192             constructors for the variant that the object is an instance of.
193              
194             =cut
195              
196             sub export_variant {
197 1     1 1 5 my ($dt,$module) = @_;
198              
199             # This function is also called by register_variant.
200 1 50       4 $module = defined $module ? $module : caller;
201            
202 1 50       15 $dt = $dt->{Type} if $dt->isa("Data::Variant");
203              
204             # We need to export all symbols to the caller so we can use them to
205             # construct new instances of the variant.
206 1         3 foreach my $cons (keys %{$dataTypes{$dt}}) {
  1         6  
207 1     1   99220 no strict;
  1         4  
  1         1263  
208 3     4   13 *{"$module\::$cons"} = sub { constructor($cons, @_) };
  3         26  
  4         15  
209             }
210              
211 1         3 1;
212             }
213              
214             =item Constructor([VARLIST])
215              
216             The constructors that you gave C will be exported as
217             functions to the calling package, and are used to create new instances
218             of the variant. It is during this instantiation phase that type
219             checking is performed.
220              
221             Note that if you want to use the functions without paranteses, or if
222             you have warnings turned on (and you probably should) you will have to
223             predeclare your constructors somehow, either by C
224             or by C.
225              
226             B The constructor will return an object with the appropriate data.
227              
228             Examples:
229              
230             # Creation of some simple trees
231             my $left = Node ((Leaf 1), (Leaf 4));
232             my $right = Node ((Leaf 3), Empty);
233             my $tree = Node $left, $right;
234              
235             # A few maybe variants
236             my $nth = Nothing
237             my $sth = Just "A string";
238              
239              
240              
241             =cut
242              
243             sub constructor {
244 4     4 0 7 my $cons = shift;
245            
246 4 50       13 croak "Tried to use non-existing constructor $cons"
247             unless (exists $constructors{$cons});
248              
249 4         7 my $type = $constructors{$cons};
250              
251             # This is the actual data object
252 4         13 my $object = { Type => $type, Cons => $cons };
253              
254             # Assign all the fields.
255 4         6 my @fields = @{$dataTypes{$type}->{$cons}};
  4         13  
256 4         8 my @vals;
257 4         26 foreach my $index (0..$#fields) {
258 6         10 my $var = $fields[$index];
259 6         9 my $val = shift;
260 6 50       13 carp "Missing argument $var for constructor $cons"
261             unless (defined $val);
262              
263 6 50       16 print "Setting $val = $var (cons: $cons)\n"
264             if ($DEBUG);
265              
266             # Simple run time typechecking.
267 6         7 my $badtype = 0;
268 6         29 switch ($var) {
  6         9  
  6         19  
  4         9  
269             # Tests "borrowed" from Switch.pm
270 6 50       104 case "" { $badtype = 1 unless ((~$val&$val) eq 0) }
  2 100       36  
  2         9  
  2         15  
  0         0  
  0         0  
  0         0  
271 4 0       55 case "" { $badtype = 1 unless (ref $val eq "") }
  0 50       0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
272 4 0       50 case "" { $badtype = 1 unless ref $val }
  0 50       0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
273 4 50       47 case "*" { $badtype = 0 }
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
274             else { # Variant type!
275 4 50 33     86 $badtype = 1 unless (($val->isa("Data::Variant")) &&
276             $val->{Type} eq $var);
277             }
278             }
279            
280              
281 6 50       14 carp "Bad type, expected $var in position ".($index+1)." for $cons"
282             if $badtype;
283              
284 6         20 push @vals, $val;
285             }
286              
287 4         11 $object->{VALS} = \@vals;
288              
289 4 50       10 croak "Too many arguments for constructor $cons"
290             if (@_ > 0);
291              
292 4         6 bless $object;
293              
294 4 50       9 print Dumper(\$object)
295             if $DEBUG;
296              
297 4         16 return $object;
298             }
299              
300             =item match([OBJ], CONS, [VARLIST])
301              
302             =item $obj->match(CONS,[VARLIST]
303              
304             =item match(OBJ)
305              
306             In its first two forms C checks is C is constructed using
307             the constructor C given. If it matches the variables in
308             C are filled with the values of the fields of the object.
309              
310             The number of elements in C must match the number of values
311             in the object.
312              
313             The first argument C can be left out if it has been pre-set using
314             C.
315              
316             It its second form, with only an object as parameter, it returns a
317             function reference that is useful in a C statement. The
318             contents of each C must then be created using C.
319              
320             =cut
321              
322             sub match {
323 19     19 1 930 my $obj;
324              
325 19 100       51 if (@_ == 1) {
326 7 50       29 croak "A lone argument has to be a variant reference"
327             unless $_[0]->isa("Data::Variant");
328 7         10 my $obj = $_[0];
329             # Create a closure and return it.
330             return sub {
331 7     7   87 match($obj,@_)
332 7         41 };
333             }
334              
335             # Find out which object to use.
336 12 50       31 if (ref $_[0] ne "") {
337 12         18 $obj = shift;
338             } else {
339 0 0       0 croak "No object pre-set" unless defined $matchObject;
340 0         0 $obj = $matchObject;
341             }
342              
343 12 50       50 croak "I need a valid object for match"
344             unless $obj->isa("Data::Variant");
345              
346 12         16 my $constr = shift;
347              
348 12         22 my $reqtype = $constructors{$constr};
349            
350 12 50       34 if ($reqtype ne $obj->{Type}) {
351 0         0 carp "Non matching datatype. Has $obj->{Type} expected $reqtype";
352             # You know, if this was Haskell this would have been a
353             # static type error to begin with.
354             }
355            
356 12 100       26 if ($obj->{Cons} ne $constr) {
357             # Not a match
358 4         19 return 0;
359             } else {
360             # A match.
361              
362             # 1) Bind all variables
363             # YYY: Can we detect unbindables??
364 8         12 my $valsize = $#{$obj->{VALS}} + 1;
  8         18  
365 8 50       19 carp "Wrong number of parameters to $constr matching"
366             if ($valsize != @_);
367              
368 8         18 foreach my $v (0..$valsize) {
369 18 100       39 if (ref $_[$v]) {
370 5         10 ${$_[$v]} = $obj->{VALS}->[$v];
  5         20  
371             } else {
372 13         39 $_[$v] = $obj->{VALS}->[$v];
373             }
374             }
375              
376             # 2) return true
377 8         50 return 1;
378             }
379              
380             }
381              
382             =item mkpat(CONS, [VARLIST])
383              
384             This creates a reference to an array containing what would normally be
385             the input to match. This is mainly useful when working with C
386             statements.
387              
388             =cut
389              
390             sub mkpat {
391 7     7 1 9 my @rv;
392            
393 7 50       43 croak "mkpat needs at least one argument"
394             unless defined $_[0];
395            
396 7         16 push @rv, $_[0];
397            
398 7         19 foreach my $i (1..$#_) {
399 7         20 push @rv,\$_[$i];
400             }
401 7         26 return \@rv;
402             }
403              
404              
405             =item set_match(OBJ)
406              
407             =item $object->set_match
408              
409             Presets an object to match against so that the first parameter of
410             C can be left out in subsequent calls.
411              
412             =cut
413              
414             sub set_match {
415 1     1 1 3 $matchObject = shift;
416 1 50       6 warn "Parameter to set_match not a Data::Variant"
417             unless ($matchObject->isa("Data::Variant"));
418             }
419              
420              
421             1;
422              
423             __END__