2

Holy cats man,

I'm maintaining some pretty awful legacy code and there is a part for adding some values to the database from a HTML form created by a loop and increments the names of the variables it submits to 14, I'm changing the loop to the amount of rows it selects before creating the HTML.

But the issue is with how it inserts the HTML form back into the database.

Here's an ad-hoc version of the way it handles the database inserts

while (my $count <= 14) {
  if ($count == 1) {
    $name = $name1;
    $email = $email1;
  }
  # ...
  if ($count == 14) {
    $name = $name14;
    $email = $email14;
  }

  my $sth = $dbh->prepare("INSERT INTO table SET name = ? AND email = ?");
  $sth->execute($name, $email);
  $count++;
}

While I'm probably just going to rewrite this entire section, I'm curious if you could add something like;

elsif ($count > 14) {
  # Say count is 15 and we want to assign
  # $name to $name15 using a string and the $count variable here.
  $name = "name".$count;

  $email = "email".$count;
}

Is that technically feasible?

1

1 Answer 1

5

What you're describing is called a "symbolic reference" in Perl lingo and it's generally frowned upon as a very, very, very... very bad practice because it only works with global variables (which are generally best avoided in their own right) and it's one of the easiest ways to create bugs which are nearly-impossible to find.

But it can be done. And, since you're asking for the sake of maintaining legacy code which is probably already just as bad, I'll show you how:

perl -e '$count14 = 42; $sref = "count14"; print $$sref . "\n"'

It's as simple as that.

But, really, don't do it if you can avoid it.

The general-case solution for avoiding symbolic references is to use a hash instead:

my %values = (name1 => 'Alice', name2 => 'Bob');
for my $count (1 .. 2) {
  my $name = $values{'name' . $count};
  print "$name\n";
}

In the specific case of a bunch of variables named foo1, foo2, etc., though, you probably want an array instead:

my @names = qw( . Alice Bob ); # '.' is a dummy to fill index 0 so the names start at 1
for my $count (1 .. 2) {
  my $name = $names[$count];
  print "$name\n";
}

I would strongly advise using one of these other techniques instead of symbolic references unless the existing code heavily depends on having $name1, $name2, etc. available. If you can afford the time to replace all of those with arrays and test that the array-based version still works, you'll have improved the quality of the code for future maintainers (which will probably include yourself).

Sign up to request clarification or add additional context in comments.

2 Comments

In your array example your indices are one off ... it should be for my $count (0 .. 1) {
Well-spotted, @dgw ! I added a dummy value to the array to fill the 0 spot rather than changing the loop because I want the indexes to match the OP's existing code (which starts with $name1, not $name0).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.