Acme-Lvalue

 view release on metacpan or  search on metacpan

lib/Acme/Lvalue.pm  view on Meta::CPAN

package Acme::Lvalue;

use warnings;
use strict;

use v5.16.0;  # earliest release with #51408 fixed

*VERSION = \'0.03';

{
	package Acme::Lvalue::Proxy;

	sub TIESCALAR {
		my ($class, $ref, $func, $cnuf) = @_;
		bless [$ref, $func, $cnuf], $class
	}

	sub FETCH {
		my ($self) = @_;
		$self->[1]->(${$self->[0]})
	}

	sub STORE {
		my ($self, $val) = @_;
		my $ref = $self->[0];
		$$ref = $self->[2]->($val, $$ref);
	}

	sub UNTIE {}
	sub DESTROY {}
}

use Math::Trig;
use Carp qw(croak);

sub _export {
	my ($where, $what, $how, $woh) = @_;
	my $fun = sub ($) :lvalue {
		tie my $proxy, 'Acme::Lvalue::Proxy', \$_[0], $how, $woh;
		$proxy
	};
	no strict 'refs';
	*{$where . '::' . $what} = $fun;
}

our %builtins = map +($_->[0] => [eval "sub {scalar $_->[0] \$_[0]}", $_->[1]]),
	[chr       => sub { ord $_[0] }],
	[cos       => sub { acos $_[0] }],
	[defined   =>
		sub {
			$_[0]
				? defined $_[1]
					? $_[1]
					: 1
				: undef
		}
	],
	[exp       => sub { log $_[0] }],
	[hex       => sub { sprintf '%x', $_[0] }],
	[length    =>
		sub {
			my ($n, $x) = @_;
			my $l = length $x;
			$n <= $l
				? substr $x, 0, $n
				: $x . "\0" x ($n - $l)
		}
	],
	[log       => sub { exp $_[0] }],
	[oct       => sub { sprintf '%o', $_[0] }],
	[ord       => sub { chr $_[0] }],
	[quotemeta => sub { $_[0] =~ s/\\(.)/$1/sgr }],
	[reverse   => sub { scalar reverse $_[0] }],
	[sin       => sub { asin $_[0] }],
	[sqrt      => sub { my $x = shift; $x * $x }],
;

sub import {
	my $class = shift;
	my $caller = caller;

	for my $item (@_) {
		if (ref $item) {
			_export $caller, @$item;
		} elsif ($item eq ':builtins') {
			for my $f (keys %builtins) {
				_export $caller, $f, @{$builtins{$f}};
			}
		} elsif ($builtins{$item}) {
			_export $caller, $item, @{$builtins{$item}};
		} else {
			croak qq{"$item" is not exported by the $class module};
		}
	}
}

'ok'
__END__

=head1 NAME

Acme::Lvalue - Generalized lvalue subroutines

=head1 SYNOPSIS

  use Acme::Lvalue qw(:builtins)



( run in 0.504 second using v1.01-cache-2.11-cpan-39bf76dae61 )