This involves system programming, so it’s more than a basic question. As written, your main program doesn’t require full-duplex interaction with the external program. Dataflow travels in one direction, namely

string → external program → main program

Creating this pipeline is straightforward. Perl’s open has a useful mode explained in the “Safe pipe opens” section of the perlipc documentation.

Another interesting approach to interprocess communication is making your single program go multiprocess and communicate between—or even amongst—yourselves. The open function will accept a file argument of either "-|" or "|-" to do a very interesting thing: it forks a child connected to the filehandle you’ve opened. The child is running the same program as the parent. This is useful for safely opening a file when running under an assumed UID or GID, for example. If you open a pipe to minus, you can write to the filehandle you opened and your kid will find it in his STDIN . If you open a pipe from minus, you can read from the filehandle you opened whatever your kid writes to his STDOUT .

This is an open that involves a pipe, which gives nuance to the return value. The perlfunc documentation on open explains.

If you open a pipe on the command - (that is, specify either |- or -| with the one- or two-argument forms of open ), an implicit fork is done, so open returns twice: in the parent process it returns the pid of the child process, and in the child process it returns (a defined) 0 . Use defined($pid) or // to determine whether the open was successful.

To create the scaffolding, we work in right-to-left order using open to fork a new process at each step.

Your main program is already running. Next, fork a process that will eventually become the external program. Inside the process from step 2 First fork the string-printing process so as to make its output arrive on our STDIN . Then exec the external program to perform its transformation. Have the string-printer do its work and then exit , which kicks up to the next level. Back in the main program, read the transformed result.

With all of that set up, all you have to do is implant your suggestion at the bottom, Mr. Cobb.

#! /usr/bin/env perl use 5.10.0; # for defined-or and given/when use strict; use warnings; my @transform = qw( tr [A-Za-z] [N-ZA-Mn-za-m] ); # rot13 my @inception = ( "V xabj, Qnq. Lbh jrer qvfnccbvagrq gung V pbhyqa'g or lbh.", "V jnf qvfnccbvagrq gung lbh gevrq.", ); sub snow_fortress { print map "$_

", @inception } sub hotel { given (open(STDIN, "-|") // die "$0: fork: $!") { # / StackOverflow hiliter snow_fortress when 0; exec @transform or die "$0: exec: $!"; } } given (open(my $fh, "-|") // die "$0: fork: $!") { hotel when 0; print while <$fh>; close $fh or warn "$0: close: $!"; }

Thanks for the opportunity to write such a fun program!