Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
Interpolation(3)      User Contributed Perl Documentation     Interpolation(3)

NAME
       Interpolation - Arbitrary string	interpolation semantics	(using tie())

       Version 0.74

       Originaly by Mark-Jason Dominus (mjd-perl-interpolation@plover.com)
       Since version 0.66 maintained by	Jenda@Krynicky.cz

SYNOPSIS
	 use Interpolation name	=> \&function, ...;
	 print "la la la la $name{blah blah blah}";

	 # This	is like	doing:
	 $VAR =	&function(blah blah blah);
	 print "la la la la $VAR";

DESCRIPTION
       Beginners always	want to	write this:

	 print "The sum	of three and four is: 3+4";

       And they	want the "3+4" part to be evaluated, so	that it	prints this:

	 The sum of three and four is: 7

       Of course, it's a double-quoted string, so it's not evaluated.  The
       only things that	are evaluated in double-quoted strings are variable
       references.

       There are solutions to this, but	most of	them are ugly.	This module is
       less ugly. Well .... this module	IS ugly, but only inside. Your code
       may end up being	nice.

       The module also lets you	define arbitrary interpolation semantics.

       For example, you	can say

	  use Interpolation money => \&commify_with_dollar_sign,
			    E	  => 'eval',
			    placename => 'ucwords',
	      ;

       And then	you can	write these:

	  print	"3 + 4 = $E{3+4}";
	  # Prints  ``3	+ 4 = 7''

	  $SALARY = 57500;
	  print	"The salary is $money{$SALARY}";
	  # Prints  ``The salary is $57,500.00''

	  $PLACE1 = 'SAN BERNADINO HIGH	SCHOOL';
	  $PLACE2 = 'n.y. state';
	  print	"$placename{$PLACE1} is	not near $placename{$PLACE2}";
	  # Prints  ``San Bernadino High School	is not near N.Y. State";

DETAILS
       The arguments to	the "use" call should be name-function pairs.  If the
       pair is "($n, $f)", then	$n will	be the name for	the semantics provided
       by $f.  $f must either be a reference to	a function that	you supply, or
       it can be the name of one of the	built-in formatting functions provided
       by this package.	 "Interpolation" will take over	the %n hash or $n
       scalar in your package, and tie it so that acessing $n{X} calls f(X)
       and yields its return value.

       If for some reason you want to, you can add new semantics at run	time
       by using

	 import	Interpolation name => function,	...

       You can remove them again with

	 unimport Interpolation	'name',	...

       Interpolators created by	the import() or	use statements are always
       PACKAGE variables, not lexicals!	 If you	want a lexical interpolator
       you can create it like this:

	       my %name;
	       tie %name, 'Interpolation', sub { ...
	 or
	       my %name;
	       tie %name, 'Interpolation', '$$->$', sub	{ ...

   Built-ins
       "Interpolation" provides	a few useful built-in formatting functions;
       you can refer to	these by name in the "use" or "import" line.  They
       are:

	       eval		       - Evaluate the argument
	       null		       - Same as eval
	       identity		       - Also the same as eval

	       ucwords	       - Capitalize Input String Like This

	       commify	       - 1428571 => 1,428,571.00

	       reverse	       - reverse string

	       sprintf		       - makes "$S{'%.2f %03d'}{37.5,42}" turn into "37.50 042"
		       use Interpolation S => 'sprintf';
		       print "$S{'%.2f %03d'}{37.5, 42}\n";

	       sprintf1		       - makes "$S{'%.2f %03d',	37.5,42}" turn into "37.50 042".
		       use Interpolation S => 'sprintf1';
		       print "$S{'%.2f %03d', 37.5, 42}\n";

	       sprintfX		       - makes "$S{'%.2f %03d'}{37.5}{42}" turn	into "37.50 042".
		       use Interpolation 'S:$$*->$' => 'sprintfX';
		       print "$S{'%.2f %03d'}{37.5}{42}\n";

	       sqlescape	       - escapes single	quotes for use in SQL queries

	       round		       - rounds	the number
		       use Interpolation round => 'round'; print "The sum is: $round{$sum, 0.01}\n";
		       use Interpolation 'round:$$->$' => 'round'; print "The sum is: $round{$sum}{0.01}\n";

	       htmlescape      - escapes characters special to HTML
			       "<b>$htmlescape{$text}</b>
	       tagescape       - escapes characters special to HTML plus double	and single quotes
			       qq{<input type=text name=foo value="$tagescape{$value}">}
	       jsescape		       - escapes the text to be	used in	JavaScript
			       qq{<a href="JavaScript:foo( '$jsescape{$value}' )">}
		       (the last three require module HTML::Entities)

ADVANCED
       It is posible to	pass multiple (or no) arguments	to your	function.
       There are two alternate syntaxes:

	   $interpolator{param1,param2}
	   $interpolator{param1}{param2}

       The first syntax	will pass both arguments in $_[0] joined by $;,	so you
       have to split them:

	   use Interpolation add => sub{@_ = split /$;/o, $_[0]; $_[0] + $_[1]};
	   print "3 + 4	= $add{3,4}\n";

       The other syntax	(used for example by builtin 'sprintf')	requires quite
       some magic, so you probably wouldn't want to be forced to write it
       yourself.  (See the source of this module if you	want to	know how
       strange is the code. )

       The other problem is, that your interpolator might want to return an
       array.  In that case you	would anticipate to get	all the	items joined
       by $", but instead you would get	only the last item. You	have to	join
       the list	yourself:

	   use Interpolation foo => sub	{join $", &bar($_[0])};

       To make your life easier	this module provides a way to specify the
       "type" of the interpolator and then does	the necessary splits, joins or
       magic itself.

       The syntax is:

	   use Interpolation 'name:input->output' => sub { ...

       where the input is a list of '$'s, '@'s and '\@'s and the output	is
       either '$' or '@'.  The '$' means that the parameter/output should be
       left intact, while '@' forces a split/join on the parameter/output.
       Each character in the input list	specifies the type of one brace	in the
       call.

       In addition you may add an asterisk to the end of the input type
       specification. This will	allow for an arbitrary long list of
       parameters. Their type will be the last specified.

       In previous version you had to "close" the interpolator call by $;.
       That is you would write something like "xxx
       $foo{par1}{par2}...{parn}{$;} xxx".  While this is still	suported it is
       NOT required anymore.

       The default type	is $->$.

	Ex.:
	 'foo:$->$' - pass the argument	to function directly and evaluate it in	scalar context
		       $foo{param}
	 'foo:$->@' - pass the argument	to function directly, evaluate it in list context and join
		      the result by $" (by default space)
		       $foo{param}
	 'foo:@->$' - split the	first parameter	by $; and pass the resulting list to the function,
		      evaluate in scalar context
		       $foo{param1,param2,...}
	 'foo:@->@' - split the	first parameter	by $; and pass the resulting list to the function,
		      evaluate in list context and join
		       $foo{param1,param2,...}
	 'foo:$$->$' - ask for two parameters enclosed in braces
			$foo{param1}{param2}
	 'foo:$@->$' - ask for two parameters enclosed in braces and split the second one
		       the list	you get	from the split will be added to	@_ flatlist
			$foo{paramA}{paramB1,paramB2,...}
	 'foo:$\@->$' -	ask for	two parameters enclosed	in braces and split the	second one
			the list you get from the split	will be	passed as a reference to an array
			 $foo{paramA}{paramB1,paramB2,...}
	 'foo:$*->$   -	ask for	arbitrary number of scalar parameters
			 $foo{par1}{par2}{par3}{$;}
	 'foo:->$      - no parameters.	This creates a tied scalar.
			 $foo

	'foo:@->$' => &bar   IS	EQUAL TO   'foo' => sub	{&bar(split /$;/o, $_[0])}
	'foo:$->@' => &bar   IS	EQUAL TO   'foo' => sub	{join $", &bar($_[0])}
	'foo:@->@' => &bar   IS	EQUAL TO   'foo' => sub	{join $", &bar(split /$;/o, $_[0])}
	'foo:\@->$' => &bar  IS	EQUAL TO   'foo' => sub	{&bar([split /$;/o, $_[0] ])}

       The builtin function sprintf could be implemented as:
	   'sprintf:$@->$' => sub {sprintf shift,@_}

       Since version 0.69 it is	possible to assign to interpolators of type
       '$->$', '$->@' and '->$'.  The assigned value will be passed to the
       function	you specified as the last parameter:

	       use Interpolation 'count:->$' =>	sub {if	(@_) {$count = $_[0]} else {$count++}};
	       # print "Current	count is $count\n";
	       use Interpolation 'count:$->$' => sub {
		       if (@_ == 2) {
			       $count{$_[0]} = $_[1]
		       } else {
			       $count{$_[0]}++
		       }
	       };
	       # print "Current	count of A is $count{A}\n";

Cool examples
       SQL
	     use Interpolation "'" => sub {$_ =	$_[0]; s/'/''/g; "'".$_};
	     ...
	     $db->Sql("SELECT *	FROM People WHERE LastName = $'{$lastname}'");

	 When passing strings to SQL you have to escape	the apostrophes	(and
	 maybe some other characters) this crazy hack allows you do it quite
	 easily.

	 Instead of "... = '$variable'"	you write "... = $'{$variable}'" et
	 voila ;-) You may of course use this syntax for whatever string
	 escaping you like.

       IF
		 use Interpolation 'IF:$*->$' => sub {$_[0] ? $_[1] : $_[2]};
		 #or
		 use Interpolation '?:$*->$' =>	sub {$_[0] ? $_[1] : $_[2]};
		 #...
		 print <<"*END*"
		 Blah blah blah
		 There was $count $IF{$count > 1}{jobs}{job}.
		 There was $count $?{$count > 1}{jobs}{job}.
		 There was $count job$?{$count > 1}{s}.
		 *END*

Warnings
       It's easy to forget that	the index to a $hash{...} is an	arbitrary
       expression, unless it looks like	an identifier.	There are two gotchas
       here.

       Trap 1.
	     print "$X{localtime}";

	   Here	the "X"	formatter is used to format the	literal	string
	   "localtime";	the "localtime"	built-in function is not invoked.  If
	   you really want the current time, use one of	these:

	     print "$X{+localtime}";
	     print "$X{localtime()}";

       Trap 2.
	     print "$X{What ho?}";

	   This	won't compile---you get	`search	pattern	not terminated'.  Why?
	   Because Perl	sees the "?" and interprets it as the beginning	of a
	   pattern match operator, similar to "/".  (Ah, you forgot that "?"
	   could be a pattern match delimiter even without a leading "m",
	   didn't you?)	 You really need

	     print "$X{'What ho?'}";

       The rule	is simple: That	thing in the braces that looks like a hash key
       really is a hash	key, and so you	need to	put it in quotes under the
       same circumstances that you need	to put any other hash key in quotes.
       You probably wouldn't expect this to work either:

	 $V = $X{What ho?};

Author
       Originaly, Mark-Jason Dominus (C<mjd-perl-interpolation@plover.com>),
       Plover Systems co.  http://www.plover.com/~mjd/perl/Interpolation Now
       maintained by, C<Jenda@Krynicky.cz> .
       http://Jenda.Krynicky.cz/#Interpolation

perl v5.24.1			  2009-09-30		      Interpolation(3)

NAME | SYNOPSIS | DESCRIPTION | DETAILS | ADVANCED | Cool examples | Warnings | Author

Want to link to this manual page? Use this URL:
<https://www.freebsd.org/cgi/man.cgi?query=Interpolation&sektion=3&manpath=FreeBSD+12.1-RELEASE+and+Ports>

home | help