3 See the NOTICE file distributed with
this work
for additional information
4 regarding copyright ownership.
6 Licensed under the Apache License, Version 2.0 (the
"License");
7 you may not use
this file except in compliance with the License.
8 You may obtain a copy of the License at
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an
"AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License
for the specific language governing permissions and
16 limitations under the License.
20 package Bio::EnsEMBL::Utils::Scalar;
27 Please email comments or questions to the
public Ensembl
28 developers list at <http:
30 Questions may also be sent to the Ensembl help desk at
43 use
Bio::EnsEMBL::Utils::Scalar qw(check_ref assert_ref wrap_array check_ref_can assert_ref_can assert_numeric assert_integer scope_guard);
45 check_ref([],
'ARRAY'); # Will
return true
46 check_ref({},
'ARRAY'); # Will
return false
47 check_ref($dba,
'Bio::EnsEMBL::DBSQL::DBAdaptor'); #Returns
true if $dba is a DBAdaptor
49 # Returns true if all array contents are of the given type
50 check_array_contents([$dba],
'Bio::EnsEMBL::DBSQL::DBAdaptor');
52 assert_ref([],
'ARRAY'); #Returns
true
53 assert_ref({},
'ARRAY'); #
throws an exception
54 assert_ref($dba,
'Bio::EnsEMBL::Gene'); #
throws an exception
if $dba is not a Gene
56 # Throws an exception if all array contents are not of the given type
57 assert_array_contents([$dba],
'Bio::EnsEMBL::Gene'); #
throws an exception
if $dba is not a Gene
59 wrap_array([]); #Returns the same reference
60 wrap_array($a); #Returns [$a]
if $a was not an array
61 wrap_array(undef); #Returns [] since incoming was undefined
62 wrap_array(); #Returns [] since incoming was empty (therefore undefined)
64 check_ref_can([],
'dbID'); #returns
false as ArrayRef is not blessed
65 check_ref_can($gene,
'dbID'); #returns
true as Gene should implement dbID()
66 check_ref_can(undef);
#Throws an exception as we gave no method to test
68 assert_ref_can([],
'dbID'); #
throws an exception since ArrayRef is not blessed
69 assert_ref_can($gene,
'dbID'); #returns
true if gene implements dbID()
70 assert_ref_can(undef);
#Throws an exception as we gave no method to test
72 asssert_integer(1,
'dbID'); #Passes
73 asssert_integer(1.1,
'dbID'); #Fails
74 asssert_numeric(1E-11,
'dbID'); #Passes
75 asssert_numeric({},
'dbID'); #Fails
80 #Build a guard to reset $v to wibble
81 my $guard = scope_guard(sub { $v =
'wibble'});
83 warn $v; # prints wobble
85 # $guard is out of scope; sub is triggered and $v is reset
86 warn $v; # prints wibble
88 #Tags are also available for exporting
96 A collection of subroutines aimed to helping Scalar based operations
116 # Interface with some of the module function XS reimplementation
118 # If Bio::EnsEMBL::XS is installed, assign the function glob to
119 # the XS counterpart, otherwise assign to the original function
123 if (eval { require Bio::EnsEMBL::XS; 1 }) {
124 *check_ref = \&Bio::EnsEMBL::XS::Utils::Scalar::check_ref;
125 *assert_ref = \&Bio::EnsEMBL::XS::Utils::Scalar::assert_ref;
126 # *assert_numeric = \&Bio::EnsEMBL::XS::Utils::Scalar::assert_numeric;
127 # *assert_integer = \&Bio::EnsEMBL::XS::Utils::Scalar::assert_integer;
129 *check_ref = \&check_ref_pp;
130 *assert_ref = \&assert_ref_pp;
131 # *assert_numeric = \&assert_numeric_pp;
132 # *assert_integer = \&assert_integer_pp;
136 *assert_numeric = \&assert_numeric_pp;
137 *assert_integer = \&assert_integer_pp;
141 use base qw(Exporter);
147 check_ref check_ref_can check_array_contents check_hash_contents
148 assert_ref assert_ref_can assert_numeric assert_integer assert_boolean assert_strand assert_file_handle assert_array_contents assert_hash_contents
154 assert => [qw(assert_ref assert_ref_can assert_integer assert_numeric assert_boolean assert_strand assert_file_handle assert_array_contents assert_hash_contents)],
155 check => [qw(check_ref check_ref_can check_array_contents check_hash_contents)],
156 array => [qw/wrap_array split_array/],
161 use Scalar::Util qw(blessed looks_like_number openhandle);
165 =head2 check_ref_pp()
167 Arg [1] : The reference to check
168 Arg [2] : The type we expect
169 Description : A subroutine which checks to see if the given
object/ref is
170 what you expect. If you give it a blessed reference then it
171 will perform an isa() call on the
object after the defined
172 tests. If it is a plain reference then it will use ref().
174 An undefined value will return a false.
175 Returntype : Boolean indicating if the reference was the type we
177 Example : my $ok = check_ref([], 'ARRAY');
178 Exceptions : If the expected type was not set
184 my ($ref, $expected) = @_;
185 throw(
'No expected type given')
if ! defined $expected;
188 return 1
if $ref->isa($expected);
191 my $ref_ref_type = ref($ref);
192 return 1
if defined $ref_ref_type && $ref_ref_type eq $expected;
198 =head2 assert_ref_pp()
200 Arg [1] : The reference to check
201 Arg [2] : The type we expect
202 Arg [3] : The attribute name you are asserting; not required but allows
203 for more useful error messages to be generated. Defaults to
205 Description : A subroutine which checks to see if the given
object/ref is
206 what you expect. This behaves in an identical manner as
207 C<check_ref()> does except this will raise exceptions when
208 the values do not match rather than returning a
boolean
209 indicating the situation.
211 Undefs cause exception circumstances.
213 You can turn assertions off by using the global variable
214 $Bio::
EnsEMBL::Utils::Scalar::ASSERTIONS = 0
215 Returntype : Boolean; true if we managed to get to the return
216 Example : assert_ref([], 'ARRAY');
217 Exceptions : If the expected type was not set and if the given reference
218 was not assignable to the expected value
224 my ($ref, $expected, $attribute_name) = @_;
225 return 1 unless $ASSERTIONS;
226 $attribute_name ||=
'-Unknown-';
227 throw(
'No expected type given')
if ! defined $expected;
228 my $class = ref($ref);
229 throw(
"The given reference for attribute $attribute_name was undef. Expected '$expected'") unless defined $ref;
230 throw(
"Asking for the type of the attribute $attribute_name produced no type; check it is a reference. Expected '$expected'") unless $class;
232 throw(
"${attribute_name}'s type '${class}' is not an ISA of '${expected}'")
if ! $ref->isa($expected);
235 throw(
"$attribute_name was expected to be '${expected}' but was '${class}'")
if $expected ne $class;
240 =head2 assert_array_contents
242 Arg [1] : ArrayRef references to check
243 Arg [2] : The type we expect
244 Arg [3] : The attribute name you are asserting; not required but allows
245 for more useful error messages to be generated. Defaults to
247 Description : A subroutine which checks to see
if the given objects/refs are
248 what you expect. This behaves in an identical manner as
249 C<assert_ref> does works on an array ref of references
251 You can turn assertions off by
using the global variable
252 $Bio::EnsEMBL::Utils::Scalar::ASSERTIONS = 0
253 Returntype : Boolean;
true if we managed to get to the
return
254 Example : assert_array_contents([[],[],[]],
'ARRAY');
255 Exceptions : Throws is references argument is not an ArrayRef, also
256 if the expected type was not set and
if the given reference
257 was not assignable to the expected value.
262 sub assert_array_contents {
263 my ($array, $expected, $attribute_name) = @_;
264 return 1 unless $ASSERTIONS;
265 throw(
'No expected type given')
if ! defined $expected;
266 $attribute_name ||=
'-Unknown-';
267 assert_ref($array,
'ARRAY', $attribute_name);
268 my $count = scalar(@{$array});
269 for(my $i = 0; $i<$count; $i++) {
270 my $ref = $array->[$i];
271 my $class = ref($ref);
272 throw(
"The given reference for attribute $attribute_name was undef (at position ${i}). Expected '$expected'") unless defined $ref;
273 throw(
"Asking for the type of the attribute $attribute_name produced no type; check it is a reference (at position ${i}). Expected '$expected'") unless $class;
275 throw(
"${attribute_name}'s type '${class}' is not an ISA of '${expected}' (at position ${i})")
if ! $ref->isa($expected);
278 throw(
"$attribute_name was expected to be '${expected}' but was '${class}' (at position ${i})")
if $expected ne $class;
284 =head2 check_array_contents
286 Arg [1] : ArrayRef references to check
287 Arg [2] : The type we expect
288 Arg [3] : The attribute name you are asserting; not required but allows
289 for more useful error messages to be generated. Defaults to
291 Description : A subroutine which checks to see
if the given objects/refs are
293 Returntype : Boolean;
true if all contents were as expected
294 Example : check_array_contents([[],[],[]],
'ARRAY');
295 Exceptions : Thrown
if no type was given
300 sub check_array_contents {
301 my ($array, $expected, $attribute_name) = @_;
302 return 0
if ! check_ref($array,
'ARRAY');
303 throw(
'No expected type given')
if ! defined $expected;
305 my $count = scalar(@{$array});
306 for(my $i = 0; $i<$count; $i++) {
307 my $ref = $array->[$i];
312 my $class = ref($ref);
318 if(! $ref->isa($expected)) {
323 elsif($expected ne $class) {
331 =head2 assert_hash_contents
333 Arg [1] : HashRef references to check
334 Arg [2] : The type we expect
335 Arg [3] : The attribute name you are asserting; not required but allows
336 for more useful error messages to be generated. Defaults to
338 Description : A subroutine which checks to see
if the given objects/refs are
339 what you expect. This behaves in an identical manner as
340 C<assert_ref> does works on a HashRef of references. Hash keys
341 are always Strings so
do not need asserting.
343 You can turn assertions off by
using the global variable
344 $Bio::EnsEMBL::Utils::Scalar::ASSERTIONS = 0
345 Returntype : Boolean;
true if we managed to get to the
return
346 Example : assert_hash_contents({a => [], b => []},
'ARRAY');
347 Exceptions : Throws is references argument is not an ArrayRef, also
348 if the expected type was not set and
if the given reference
349 was not assignable to the expected value.
354 sub assert_hash_contents {
355 my ($hash, $expected, $attribute_name) = @_;
356 return 1 unless $ASSERTIONS;
357 throw(
'No expected type given')
if ! defined $expected;
358 $attribute_name ||=
'-Unknown-';
359 assert_ref($hash,
'HASH', $attribute_name);
360 my @keys = keys %{$hash};
361 while(my $key = shift @keys) {
362 my $ref = $hash->{$key};
363 my $class = ref($ref);
364 throw(
"The given reference for attribute $attribute_name was undef (with key ${key}). Expected '$expected'") unless defined $ref;
365 throw(
"Asking for the type of the attribute $attribute_name produced no type; check it is a reference (with key ${key}). Expected '$expected'") unless $class;
367 throw(
"${attribute_name}'s type '${class}' is not an ISA of '${expected}' (with key ${key})")
if ! $ref->isa($expected);
370 throw(
"$attribute_name was expected to be '${expected}' but was '${class}' (with key ${key})")
if $expected ne $class;
376 =head2 check_hash_contents
378 Arg [1] : HashRef references to check
379 Arg [2] : The type we expect
380 Arg [3] : The attribute name you are asserting; not required but allows
381 for more useful error messages to be generated. Defaults to
383 Description : A subroutine which checks to see
if the given objects/refs are
385 Returntype : Boolean;
true if all contents were as expected
386 Example : check_hash_contents({a => [], b => []},
'ARRAY');
387 Exceptions : Thrown
if no type was given
392 sub check_hash_contents {
393 my ($hash, $expected, $attribute_name) = @_;
394 throw(
'No expected type given')
if ! defined $expected;
395 return 0
if ! check_ref($hash,
'HASH');
397 my @keys = keys %{$hash};
398 while(my $key = shift @keys) {
399 my $ref = $hash->{$key};
404 my $class = ref($ref);
410 if(! $ref->isa($expected)) {
415 elsif($expected ne $class) {
425 Arg : The reference we want to wrap in an array
426 Description : Takes in a reference and returns either the reference if it
427 was already an array, the reference wrapped in an array or
428 an empty array (if the given value was undefined).
429 Returntype : Array Reference
430 Example : my $a = wrap_array($input);
437 my ($incoming_reference) = @_;
438 if(defined $incoming_reference) {
439 if(check_ref($incoming_reference,
'ARRAY')) {
440 return $incoming_reference;
443 return [$incoming_reference];
451 Arg [1] : The reference to check
452 Arg [2] : The method we expect to
run
453 Description : A subroutine which checks to see
if the given
object/ref is
454 implements the given method. This is very similar to the
455 functionality given by C<UNIVERSAL::can()> but works
456 by executing C<can()> on the
object meaning we consult the
457 object's potentially overriden version rather than Perl's
460 Example : check_ref_can($gene,
'dbID');
461 Exceptions : If the expected type was not set.
467 my ($ref, $method) = @_;
468 throw(
'No method given')
if ! defined $method;
469 return unless defined $ref && blessed($ref);
470 return $ref->can($method);
473 =head2 assert_ref_can
475 Arg [1] : The reference to check
476 Arg [2] : The method we expect to
run
477 Arg [3] : The attribute name you are asserting; not required but allows
478 for more useful error messages to be generated. Defaults to
480 Description : A subroutine which checks to see
if the given
object/ref is
481 implements the given method. Will
throw exceptions.
483 You can turn assertions off by
using the global variable
484 $Bio::EnsEMBL::Utils::Scalar::ASSERTIONS = 0
485 Returntype : Boolean;
true if we managed to get to the
return
486 Example : assert_ref_can($gene,
'dbID');
487 Exceptions : If the reference is not defined,
if the
object does not
488 implement the given method and
if no method was given to check
494 my ($ref, $method, $attribute_name) = @_;
495 return 1 unless $ASSERTIONS;
496 $attribute_name ||=
'-Unknown-';
497 throw(
'No method given')
if ! defined $method;
498 throw "The given reference $attribute_name is not defined. Expected method '$method'" unless defined $ref;
499 throw "The given reference $attribute_name is not blessed. Expected method '$method'" unless blessed($ref);
500 if(! $ref->can($method)) {
501 my $str_ref = ref($ref);
502 throw sprintf(q{The given blessed reference
'%s' for attribute
'%s' does not implement the method
'%s'}, $str_ref, $attribute_name, $method);
507 =head2 assert_numeric_pp
509 Arg [1] : The Scalar to check
510 Arg [2] : The attribute name you are asserting; not required but allows
511 for more useful error messages to be generated. Defaults to
513 Description : A subroutine which checks to see
if the given scalar is
514 number or not. If not then we
raise exceptions detailing why
516 You can turn assertions off by
using the global variable
517 $Bio::EnsEMBL::Utils::Scalar::ASSERTIONS = 0
518 Returntype : Boolean;
true if we had a numeric otherwise we signal failure
520 Example : assert_numeric(1,
'dbID');
521 Exceptions : If the Scalar is not defined,
if the Scalar was blessed and
522 if the value was not a number
527 sub assert_numeric_pp {
528 my ($integer, $attribute_name) = @_;
529 return 1 unless $ASSERTIONS;
530 $attribute_name ||=
'-Unknown-';
531 throw "$attribute_name attribute is undefined. Expected a number" if ! defined $integer;
532 throw "The given attribute $attribute_name is blessed; cannot work with blessed values. Expected a number" if blessed($integer);
533 if(! looks_like_number($integer)) {
534 throw "Attribute $attribute_name was not a number";
539 =head2 assert_integer_pp
541 Arg [1] : The Scalar to check
542 Arg [2] : The attribute name you are asserting; not required but allows
543 for more useful error messages to be generated. Defaults to
545 Description : A subroutine which checks to see
if the given scalar is
546 a whole integer; we delegate to L<assert_numeric>
for number
549 You can turn assertions off by
using the global variable
550 $Bio::EnsEMBL::Utils::Scalar::ASSERTIONS = 0
551 Returntype : Boolean;
true if we had a numeric otherwise we signal failure
553 Example : assert_integer(1,
'dbID');
554 Exceptions : See L<assert_numeric> and we
raise exceptions
if the value
555 was not a whole integer
560 sub assert_integer_pp {
561 my ($integer, $attribute_name) = @_;
562 return 1 unless $ASSERTIONS;
563 $attribute_name ||=
'-Unknown-';
564 throw "$attribute_name attribute is undefined. Expected an Integer" if ! defined $integer;
565 throw "The given attribute $attribute_name is blessed; cannot work with blessed values. Expected an Integer" if blessed($integer);
566 if(! looks_like_number($integer)) {
567 throw "Attribute $attribute_name was not a number. Expected an Integer";
569 if($integer !=
int($integer)) {
570 throw "Attribute $attribute_name was a number but not an Integer";
575 =head2 assert_boolean
577 Arg [1] : The Scalar to check
578 Arg [2] : The attribute name you are asserting; not required but allows
579 for more useful error messages to be generated. Defaults to
581 Description : A subroutine which checks to see
if the given scalar is
582 a
boolean i.e. value is set to C<1> or C<0>
584 You can turn assertions off by
using the global variable
585 $Bio::EnsEMBL::Utils::Scalar::ASSERTIONS = 0
586 Returntype : Boolean;
true if we were given a
boolean otherwise we signal
587 failure via exceptions
588 Example : assert_boolean(1,
'is_circular');
589 Exceptions : See L<assert_integer> and we
raise exceptions
if the value
590 was not equal to the 2 valid states
596 my ($boolean, $attribute_name) = @_;
597 return 1 unless $ASSERTIONS;
598 $attribute_name ||=
'-Unknown-';
599 throw "$attribute_name attribute is undefined. Expected a boolean" if ! defined $boolean;
600 throw "The given attribute $attribute_name is blessed; cannot work with blessed values. Expected an Integer" if blessed($boolean);
601 if(! looks_like_number($boolean)) {
602 throw "Attribute $attribute_name was not a number. Expected a boolean";
604 if($boolean != 0 && $boolean != 1) {
605 throw "Attribute $attribute_name was an invalid boolean. Expected: 1 or 0. Got: $boolean";
612 Arg [1] : The Scalar to check
613 Arg [2] : The attribute name you are asserting; not required but allows
614 for more useful error messages to be generated. Defaults to
616 Description : A subroutine which checks to see
if the given scalar is
617 a whole integer and
if the value is set to C<1>, C<0> or C<-1>
619 You can turn assertions off by
using the global variable
620 $Bio::EnsEMBL::Utils::Scalar::ASSERTIONS = 0
621 Returntype : Boolean;
true if we had a strand integer otherwise we signal
622 failure via exceptions
623 Example : assert_strand(1,
'strand');
624 Exceptions : See L<assert_integer> and we
raise exceptions
if the value
625 was not equal to the 3 valid states
631 my ($strand, $attribute_name) = @_;
632 return 1 unless $ASSERTIONS;
633 $attribute_name ||=
'-Unknown-';
634 throw "$attribute_name attribute is undefined. Expected: 1, 0 or -1" if ! defined $strand;
635 throw "The given attribute $attribute_name is blessed; cannot work with blessed values. Expected: 1, 0 or -1" if blessed($strand);
636 if(! looks_like_number($strand)) {
637 throw "Attribute $attribute_name was not a number. Expected: 1, 0 or -1";
639 if($strand != -1 && $strand != 0 && $strand ne 1) {
640 throw "Attribute $attribute_name was an invalid strand. Expected: 1, 0 or -1. Got: $strand";
646 =head2 assert_file_handle
648 Arg [1] : The Scalar to check
649 Arg [2] : The attribute name you are asserting; not required but allows
650 for more useful error messages to be generated. Defaults to
652 Description : A subroutine which checks to see
if the given scalar is
653 actually a file handle. This will handle those which are Glob
654 references and those which inherit from C<IO::Handle>. It will
655 also cope with a blessed Glob reference.
657 You can turn assertions off by
using the global variable
658 $Bio::EnsEMBL::Utils::Scalar::ASSERTIONS = 0
659 Returntype : Boolean;
660 Example : assert_file_handle($fh,
'-FILE_HANDLE');
661 Exceptions : Raised
if not defined, not a reference and was not a
662 GLOB or did not inherit from IO::Handle
667 sub assert_file_handle {
668 my ($file_handle, $attribute_name) = @_;
669 return 1 unless $ASSERTIONS;
670 $attribute_name ||=
'-Unknown-';
671 throw "Attribute $attribute_name was undefined. Expected a FileHandle" if ! defined $file_handle;
672 my $ref = ref($file_handle);
673 throw "Attribute $attribute_name was not a reference. Got: $file_handle. Expected a FileHandle" if ! $ref;
674 if(!openhandle($file_handle)) {
675 if(blessed($file_handle)) {
676 if(! $file_handle->isa(
'IO::Handle')) {
677 throw "Attribute $attribute_name was blessed but did not inherit from IO::Handle. Ref was: $ref";
681 throw "Attribute $attribute_name was not a file handle. Ref was: $ref";
689 Arg [1] : Integer Maximum size of an array produced
690 Arg [2] : ArrayRef The array to split
691 Description : Takes an array of values and splits the array into multiple
692 arrays where the maximum size of each array is as specified
693 Example : my $split_arrays = split_array($large_array, 10);
694 Returntype : ArrayRef of ArrayRefs where each element is a split list
698 my ($amount, $array) = @_;
699 assert_ref($array,
'ARRAY',
'array');
703 foreach my $e (@$array) {
704 if($counter == $amount) {
708 push(@{$split[$index]}, $e);
716 Arg [1] : CodeRef The block of code to exit once it escapes out of scope
717 Description : Simple subroutine which blesses your given code reference into
718 a L<Bio::EnsEMBL::Utils::Scalar::ScopeGuard>
object. This has
719 a DESTROY implemented which will cause the code reference
720 to execute once the
object goes out of scope and its reference
722 Returntype : Bio::EnsEMBL::Utils::Scalar::ScopeGuard
723 Example : my $v =
'wibble';
725 #Build a guard to reset $v to wibble
726 my $guard = scope_guard(sub { $v =
'wibble'});
730 # $guard is out of scope; sub is triggered and $v is reset
732 Exceptions : Raised
if argument was not a CodeRef
739 assert_ref($callback,
'CODE',
'callback');
740 return bless($callback,
'Bio::EnsEMBL::Utils::Scalar::ScopeGuard');
745 #### SUPER SECRET PACKAGE. IGNORE ME
746 package Bio::EnsEMBL::Utils::Scalar::ScopeGuard;