Boulder::Stream(3pm)
π Boulder::Stream π
okay so bestie, welcome to Boulder::Stream(3pm) β straight out of the User Contributed Perl Documentation section, and honestly? it's giving stream-oriented icon. This is the page for reading and writing tag/value data from an input stream, and I'm gonna walk you through every single crumb of it, no cap. π«Ά
β¨ NAME β¨
Boulder::Stream β Read and write tag/value data from an input stream
π SYNOPSIS π
#!/bin/perl
# Read a series of People records from STDIN.
# Add an "Eligible" tag to all those whose
# Age >= 35 and Friends list includes "Fred"
use Boulder::Stream;
# filestream way:
my $stream = Boulder::Stream->newFh;
while ( my $record = <$stream> ) {
next unless $record->Age >= 35;
my @friends = $record->Friends;
next unless grep {$_ eq 'Fred'} @friends;
$record->insert(Eligible => 'yes');
print $stream $record;
}
# object oriented way:
my $stream = Boulder::Stream->new;
while (my $record = $stream->get ) {
next unless $record->Age >= 35;
my @friends = $record->Friends;
next unless grep {$_ eq 'Fred'} @friends;
$record->insert(Eligible => 'yes');
print $stream $record;
}
like, two whole vibes in one synopsis. pick your fighter. π
π¦ DESCRIPTION π¦
Boulder::Stream gives you stream-oriented access to Boulder IO hierarchical tag/value data. It can run in a magic tied filehandle mode (that's the one in the synopsis, bestie) or in object-oriented mode. When you're using tied filehandles, Stone objects get read from input with the standard <> operator. And Stone objects that you print to the tied filehandle? They show up on the output stream in Boulder format. slay. β¨
By default, data is read from the magic ARGV filehandle β that's STDIN, or a list of files handed to you on the command line β and written to STDOUT. But you can absolutely swap that out for the filehandles of your choice. main character energy, your call. π
π« Pass through behavior π«
So when you're using the object-oriented form of Boulder::Stream, any tags that aren't specifically requested by the get() method get passed through to output unchanged. This is the whole reason pipes of programs are so easy to build. Most programs are gonna want to put the tags back into the boulder stream once they're done, possibly adding their own on the way out. Of course some programs wanna do their own thing β like, a database query program will generate a boulderio stream but not read one, while a report generator will read the stream but not write it. different strokes. π
This convention is what lets you set up this exact type of pipe:
query_database | find_vector | find_dups | \
| blast_sequence | pick_primer | mail_report
If every program in the pipe follows the conventions, then you can interpose other programs β say, a repetitive element finder β right in the middle of the pipe without disturbing any of the other components. iconic behavior tbh. π
π§ SKELETON BOULDER PROGRAM π§
Here's a skeleton example, bestie. your starter pack.
#!/bin/perl
use Boulder::Stream;
my $stream = Boulder::Stream->newFh;
while ( my $record = <$stream> ) {
next unless $record->Age >= 35;
my @friends = $record->Friends;
next unless grep {$_ eq 'Fred'} @friends;
$record->insert(Eligible => 'yes');
print $stream $record;
}
okay so let's break it down. The code starts by creating a Boulder::Stream object to handle the I/O. It reads from the stream one record at a time, handing back a Stone object. We recover the Age and Friends tags, and we keep looping unless the Age is greater or equal to 35 and the list of Friends contains "Fred". If those criteria match, we insert a new tag named Eligible and print the record to the stream. The output may look like this:
Name=Janice
Age=36
Eligible=yes
Friends=Susan
Friends=Fred
Friends=Ralph
=
Name=Ralph
Age=42
Eligible=yes
Friends=Janice
Friends=Fred
=
Name=Susan
Age=35
Eligible=yes
Friends=Susan
Friends=Fred
=
Note that in this case, only the records that meet the criteria get echoed to standard output. π«Ά
Now the object-oriented version of the program looks like this:
#!/bin/perl
use Boulder::Stream;
my $stream = Boulder::Stream->new;
while ( my $record = $stream->get('Age','Friends') ) {
next unless $record->Age >= 35;
my @friends = $record->Friends;
next unless grep {$_ eq 'Fred'} @friends;
$record->insert(Eligible => 'yes');
$stream->put($record);
}
The get() method is what you use to fetch Stones containing one or more of the indicated tags. The put() method is what sends the result to standard output. And the pass-through behavior might produce a set of records like this one:
Name=Janice
Age=36
Eligible=yes
Friends=Susan
Friends=Fred
Friends=Ralph
=
Name=Phillip
Age=30
=
Name=Ralph
Age=42
Eligible=yes
Friends=Janice
Friends=Fred
=
Name=Barbara
Friends=Agatha
Friends=Janice
=
Name=Susan
Age=35
Eligible=yes
Friends=Susan
Friends=Fred
=
Notice that there are now two records ("Phillip" and "Barbara") that do not contain the Eligible tag. that's the pass-through doing its lil thing. π
π Boulder::Stream METHODS π
$stream = Boulder::Stream->new(*IN,*OUT)
$stream = Boulder::Stream->new(-in=>*IN,-out=>*OUT)
The new() method creates a new Boulder::Stream object. You can hand it input and output filehandles. If you leave one or both undefined, new() will default to standard input or standard output. You are free to use files, pipes, sockets, and other types of file handles β go off. You may provide the filehandle arguments as bare words, globs, or glob refs, and you're also free to use the named argument style shown in that second heading. β¨
$fh = Boulder::Stream->newFh(-in=>*IN, -out=>*OUT)
Returns a filehandle object tied to a Boulder::Stream object. Reads on the filehandle perform a get(). Writes invoke a put().
To retrieve the underlying Boulder::Stream object, call Perl's built-in tied() function:
$stream = tied $fh;
$stone = $stream->get(@taglist)
@stones = $stream->get(@taglist)
Every time get() is called, it returns a new Stone object. That Stone gets created from the input stream, using just the tags you provided in the argument list. Pass no tags and you receive whatever tags are present in the input stream. π
If none of the tags you specify are in the current boulder record, you'll get an empty Stone. And at the end of the input stream, you'll receive undef. (π she's done.)
If called in an array context, get() returns a list of all stones from the input stream that contain one or more of the specified tags.
$stone = $stream->read_record(@taglist)
Identical to get(>, but the name is longer. π
$stream->put($stone)
Write a Stone to the output filehandle.
$stream->write_record($stone)
Identical to put(), but the name is longer. π
β¨ Useful State Variables in a Boulder::Stream β¨
Every Boulder::Stream has several state variables that you can adjust. Fix them in this fashion:
$a = new Boulder::Stream;
$a->{delim}=':';
$a->{record_start}='[';
$a->{record_end}=']';
$a->{passthru}=undef;
delimβ This is the delimiter character between tags and values,"="by default.record_startβ This is the start of nested record character,"{"by default.record_endβ This is the end of nested record character,"}"by default.passthruβ This determines whether unrecognized tags should be passed through from the input stream to the output stream. This is'true'by default. Set it toundefto override this behavior.
π BUGS π
okay bestie, listen up, this part matters. Because the delim, record_start and record_end characters in the Boulder::Stream object are used in optimized (once-compiled) pattern matching, you cannot change these values once get() has once been called. To change the defaults, you must create the Boulder::Stream, set the characters, and only then begin reading from the input stream. For the same reason, different Boulder::Stream objects cannot use different delimiters. no cap, that's just how it is.
π¨ fr fr: set your characters FIRST. call get() first and those defaults are locked in, bestie. π
π AUTHOR π
Lincoln D. Stein <lstein@cshl.org>, Cold Spring Harbor Laboratory, Cold Spring Harbor, NY. This module can be used and distributed on the same terms as Perl itself.
πΈ SEE ALSO πΈ
Boulder, Boulder::Blast, Boulder::Genbank, Boulder::Medline, Boulder::Unigene, Boulder::Omim, Boulder::SwissProt
and that's the whole page, bestie!! π this one's from perl v5.34.0, dated 2022-06-08, and it's filed under Boulder::Stream(3pm) β now go build a pipe and make me proud. mwah π π
π¦ where this page comes from
- debian bookworm: libboulder-perl 1.30-6 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- debian trixie: libboulder-perl 1.30-6 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu noble: libboulder-perl 1.30-6 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu resolute: libboulder-perl 1.30-6 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu stonking: libboulder-perl 1.30-6 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms