Dear Monks,
I am looking for a “true once” Boolean value, to test within a loop. I need something that will give me a TRUE value the first time, and FALSE the remaining times or vice-versa. I know that this need is shared by somebody else (Re: Being Popular) and I wonder if somebody has any idioms to offer.
Here is a practical example. I need to create a MySQL INSERT statement, exploiting the special syntax to have multiple values within the same instruction.
INSERT INTO tablename VALUES (value1, value2, value3), (value1, value2, value3), (value1,value2, value3);
To create such statement, I am parsing the raw data from an input file, and I have the problem of inserting commas after each set of values, except the last one (or we could say before each set, except the first one).
I came up with two solutions. The first one has a TRUE scalar that becomes FALSE upon being called:
my $should_print = 1; while (...) { print "'\n" if ($should_print? --$should_print : 1); # munging ... }
A little tricky, but it works. The first call will change the TRUE value to a FALSE one, thus preventing the print from happening. Each successive call will return 1 (TRUE) with the help of the ternary operator, unleashing the print.
The second solution will get over the TRUE-once need by means of grep and map, and although the result is exactly the same, it looks like something that I should send to an Obfuscated Code Contest.
(Thinking again, though, also the first solution, where a Boolean test returns the opposite of a scalar value, would be a good candidate for an OCC.)
The following program illustrates the two solutions. I would be glad to find out if there is anything easier to read or to implement.
Personally, I like the while loop, but I am keeping an open mind on alternatives. Any hints?
Thanks
gmax

#!/usr/bin/perl -w use strict; print <<MYSQL; CREATE DATABASE IF NOT EXISTS chess; USE chess; DROP TABLE IF EXISTS eco_class; # create table statement CREATE TABLE eco_class ( eco_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, eco CHAR(3) NOT NULL, opening VARCHAR(50) NOT NULL, variation VARCHAR(50), moves VARCHAR(200) NOT NULL, KEY eco(eco), KEY opening(opening), KEY variation (variation), KEY moves(moves)); # create the header for the insert statement INSERT INTO eco_class VALUES MYSQL my @line; # input fields my $should_print =1; # flag for first line with_while(); # comment to test the alternative #with_map(); # uncomment to test the alternative print ";\n"; sub with_while { while (<DATA>) { chomp; # removes trailing newline next if /^\s*$/; # skips blank lines # skips the first line print ",\n" if ($should_print? --$should_print : 1); @line = split /;/; # gets individual records print "(NULL, ", quotrim($line[0]), ", ", quotrim($line[1]), ", "; # the third field may be missing print scalar @line < 4 ? "NULL, " . quotrim($line[2]) : quotrim($line[2]) . ", " . quotrim($line[3]), ")"; } } sub with_map { print join ",\n" , grep { defined $_ } map { chomp; # removes trailing newline if (/^\s*$/ ) { # skips blank lines $_ = undef; } else { @line = split /;/; # gets individual records $_ = "(NULL, " . quotrim($line[0]) . ", " . quotrim($line[1]) . ", "; $_ .= scalar @line < 4 ? "NULL, " . quotrim($line[2]) : quotrim($line[2]) . ", " . quotrim($line[3]), ")"; $_ .= ")"; } } <DATA>; } sub quotrim { # quote and trim :-> $_[0] =~ s/\"/\\"/g; $_[0] =~ s/^\s+//; $_[0] =~ s/\s+$//; return '"' . $_[0] . '"'; } #sample data follows __DATA__ A00;Polish (Sokolsky) opening;1.b4 A00;Polish;Tuebingen Variation ;1.b4 Nh6 A00;Polish;Outflank Variation ;1.b4 c6 A00;Benko's Opening;1.g3 A00;Lasker simul special;1.g3 h5 A00;Benko's Opening;reversed Alekhine;1.g3 e5 2.Nf3 A00;Grob's attack;1.g4 A00;Grob;Spike attack;1.g4 d5 2.Bg2 c6 3.g5 A00;Grob;Fritz gambit;1.g4 d5 2.Bg2 Bxg4 3.c4 A00;Grob;Romford counter-gambit;1.g4 d5 2.Bg2 Bxg4 3.c4 d4 A00;Clemenz (Mead's, Basman's or de Klerk's) Opening;1.h3 A00;Global Opening;1.h3 e5 2.a3 A00;Amar (Paris) Opening;1.Nh3 A00;Amar gambit;1.Nh3 d5 2.g3 e5 3.f4 Bxh3 4.Bxh3 exf4

In reply to A TRUE-once variable by gmax

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.