our
@EXPORT
=
qw(purehash)
;
our
@EXPORT_OK
=
qw(hash_clone_to_purehash hash_to_purehash)
;
our
%EXPORT_TAGS
= (
all
=> [
@EXPORT
,
@EXPORT_OK
]);
our
$immutable
= 1;
sub
purehash {
__
'convert key/value pairs to an immutable hash; re-use of keys is an error'
;
die
"uneven number of arguments"
if
@_
& 1;
my
%out
;
for
(
my
$i
= 0;
$i
<
@_
;
$i
+= 2) {
my
$k
=
$_
[
$i
];
if
(
exists
$out
{
$k
}) {
die
"duplicate key: "
. show(
$k
);
}
$out
{
$k
} =
$_
[
$i
+ 1];
Internals::SvREADONLY
$out
{
$k
}, 1
if
$FP::PureHash::immutable
;
}
my
$res
=
bless
\
%out
,
"FP::_::PureHash"
;
Internals::SvREADONLY
%out
, 1
if
$FP::PureHash::immutable
;
$res
}
sub
hash_clone_to_purehash {
@_
== 1 or fp_croak_arity 1;
FP::_::PureHash->new_from_hash({ %{
$_
[0] } })
}
sub
hash_to_purehash {
@_
== 1 or fp_croak_arity 1;
FP::_::PureHash->new_from_hash(
$_
[0])
}
sub
is_purehash {
@_
== 1 or fp_croak_arity 1;
my
(
$v
) =
@_
;
my
$r
= blessed(
$v
) //
return
;
$v
->isa(
"FP::_::PureHash"
)
}
sub
FP_Show_show {
my
(
$s
,
$show
) =
@_
;
$s
->constructor_name .
"("
.
join
(
", "
,
map
{
&$show
(
$_
) .
" => "
.
&$show
(
$$s
{
$_
}) }
sort
keys
%$s
)
.
")"
}
sub
FP_Equal_equal {
my
(
$a
,
$b
) =
@_
;
keys
(
%$a
) ==
keys
(
%$b
) and
do
{
for
my
$key
(
keys
%$a
) {
exists
$$b
{
$key
} or
return
0;
equal(
$$a
{
$key
},
$$b
{
$key
}) or
return
0;
}
1
}
}
_END_
}
our
$AUTOLOAD
;
sub
AUTOLOAD {
my
$methodname
=
$AUTOLOAD
;
$methodname
=~ s/.*:://;
my
$v
= FP::_::PureHash->new_from_hash(
$_
[0]);
if
(
my
$m
=
$v
->can(
$methodname
)) {
goto
$m
}
else
{
die
"no method '$methodname' found for object: $v"
;
}
}
}
sub
new_from_hash {
@_
== 2 or fp_croak_arity 2;
my
(
$class
,
$out
) =
@_
;
if
(
$FP::PureHash::immutable
) {
for
my
$k
(
keys
%$out
) {
Internals::SvREADONLY
$out
->{
$k
}, 1
}
}
my
$res
=
bless
$out
,
"FP::_::PureHash"
;
Internals::SvREADONLY
%$out
, 1
if
$FP::PureHash::immutable
;
$res
}
sub
constructor_name {
"purehash"
}
sub
ref
{
@_
== 2 or fp_croak_arity 2;
my
(
$s
,
$key
) =
@_
;
$$s
{
$key
}
}
sub
perhaps_ref {
@_
== 2 or fp_croak_arity 2;
my
(
$s
,
$key
) =
@_
;
exists
$$s
{
$key
} ?
$$s
{
$key
} : ()
}
sub
set {
@_
== 3 or fp_croak_arity 3;
my
(
$s
,
$key
,
$val
) =
@_
;
my
%out
=
%$s
;
$out
{
$key
} =
$val
;
if
(
$FP::PureHash::immutable
) {
for
my
$k
(
keys
%out
) {
Internals::SvREADONLY
$out
{
$k
}, 1
}
}
my
$res
=
bless
\
%out
,
"FP::_::PureHash"
;
Internals::SvREADONLY
%out
, 1
if
$FP::PureHash::immutable
;
$res
}
sub
key_value_pairs {
@_
== 1 or fp_croak_arity 1;
my
(
$h
) =
@_
;
map
{ [
$_
,
$h
->{
$_
}] }
sort
keys
%$h
}
sub
array {
@_
== 1 or fp_croak_arity 1;
my
(
$h
) =
@_
;
[
$h
->key_value_pairs]
}
sub
purearray {
@_
== 1 or fp_croak_arity 1;
my
(
$h
) =
@_
;
FP::_::PureArray->new_from_array(
$h
->array)
}
sub
list {
@_
== 1 or fp_croak_arity 1;
my
(
$h
) =
@_
;
FP::List::array_to_list(
$h
->array)
}
sub
sequence {
@_
== 1 or fp_croak_arity 1;
my
(
$h
) =
@_
;
$h
->purearray
}
FP::Interfaces::implemented
qw(
FP::Abstract::Pure
FP::Abstract::Map
FP::Abstract::Equal
FP::Abstract::Show)
;
_END_
}
1