1

I am new to the perl programming language. I am trying to understand the webmin modules. I am not getting this code snippet:

sub update_dialer
{
    local $lref = &read_file_lines($config{'file'});
    splice(@$lref, $_[0]->{'line'}, $_[0]->{'eline'} - $_[0]->{'line'} + 1,
    &dialer_lines($_[0]));
    &flush_file_lines();
}

What is happening here? Where the values are storing? Please someone explain this code in detail.

serenesat
  • 4,611
  • 10
  • 37
  • 53
abhillier
  • 214
  • 2
  • 13
  • Bunch of poor practices, if you're not particularly interested in webmin take a look on some other perl code. To global `$lref` is assigned array reference, and `$_[0]` is hash reference passed to subroutine as a first parameter. – mpapec Jul 07 '15 at 06:23
  • $lref is declared as the local.the values which are passed to that will be stored in a array??please correct me if my understanding is wrong.. – abhillier Jul 07 '15 at 06:37
  • 1
    Please check http://stackoverflow.com/a/31235822/223226 and http://perldoc.perl.org/perlreftut.html – mpapec Jul 07 '15 at 06:40
  • 1
    that was helpful thanku.. – abhillier Jul 07 '15 at 06:51
  • Yeah, you should almost never see `local` in practice (except maybe `local $_`), and you shouldn't use `&` like that either. This code was written for Perl4. And then there's the three style decisions I wouldn't have made. – ikegami Jul 07 '15 at 13:27
  • @ikegami Indeed I have not, but I read [this](http://stackoverflow.com/questions/129607/what-is-the-difference-between-my-and-local-in-perl), and I start to wonder whether it's a way to have subroutines always compatible with existing code that does not `use strict` (code which my have a global $lref)? I just made two such subroutines, and I'm intrigued. – stevesliva Jul 07 '15 at 20:43
  • @stevesliva, No, the use of global variables in one sub does not require the use of them in another. It may use lexicals. – ikegami Jul 07 '15 at 21:13

1 Answers1

0

The short summary: "nasty perl code".

The longer answer:

sub update_dialer {

    # take a global variable $lref.
    # scope it locally it can be modified within the local subroutine
    # run the sub "read_file_lines" and pass it the contents of `$config{'file'}
    # assign the result to $lref
    local $lref = &read_file_lines( $config{'file'} );

   #removes elements from an array.
   #Number based on a hash reference passed in as the first argument in @_
   #but is also calling the dialer_lines subroutine as part of it.
    splice(
        @$lref, $_[0]->{'line'},
        $_[0]->{'eline'} - $_[0]->{'line'} + 1,
        &dialer_lines( $_[0] )
    );

    #run the sub 'flush_file_lines'.
    &flush_file_lines();
}

It's implementing a bunch of bad practices:

local

The manpage points out what's wrong with this:

You really probably want to be using my instead, because local isn't what most people think of as "local". See Private Variables via my() in perlsub for details.

local exists as a way to temporarily override global variables. It's useful - for example - if you want to change the input record separator $/. You might do:

{
    local $/ = "\n\n";
    my $first_record = <$filehandle>;
    print $first_record;
}

This means that once you exit your code block, $/ returns to it's original value, and doesn't screw up all the rest of the file IO in your code. There is no good reason to use it like this in this example.

& prefix on a subroutine

Difference between &function and function() in perl

Prefixing a sub with & does a few things that you almost never really want, because it messes around with prototyping and whatnot. You should therefore not do it generally.

splice

removes and replaces elements in an array. Not specifically wrong but the fact that it's doing it the way it is makes it really hard to tell what it's doing.

(But I think because it's localising $lref the value of it disappears at the end of this sub.

$_[0] -> {'line'}

When a sub is called, it's passed an array @_ with arguments to the function. You can use $_[0] to access the first element of this array - it's NOT the same a $_ though, for all the reasons $list[0] and $list aren't the same.

The way this is being used - $_[0] -> {'line'} tells us that this is a hash reference and it's being dereferenced to access certain variables.

But this isn't exactly creating nice and readable code.

You might instead do:

my ( $parameter_ref ) = @_; 

Or perhaps:

my $parameter_ref = shift;

A matter of taste here - by default, shift uses @_ in much the same way as a lot of other functions default to $_. I tend to prefer the former though.

But by naming your parameters, you make clear exactly what they are, and what they're doing.

Community
  • 1
  • 1
Sobrique
  • 52,974
  • 7
  • 60
  • 101