Professional Web Applications Themes

Help with putting a subroutine into a variable? - PERL Beginners

Hi all, I have this: ----------------- #!/usr/bin/perl use warnings; use strict; my pics = <*.jpg>; my $website = 'http://www.website.com/uploads'; sub links { foreach (pics) { print "<a href=\"$website/$_\">$website/$_</a>\n"; } } ----------------- I would normally call the subroutine like &links; but I want to put the result into a variable in order to stick it into an e-mail. I have been trying all day reading all my perl books and it's time to ask for help. Thanks. -- Just getting into the best language ever... Fancy a me.uk? Just ask!!!...

  1. #1

    Default Help with putting a subroutine into a variable?

    Hi all,

    I have this:

    -----------------
    #!/usr/bin/perl

    use warnings;
    use strict;

    my pics = <*.jpg>;
    my $website = 'http://www.website.com/uploads';

    sub links {
    foreach (pics) {
    print "<a href=\"$website/$_\">$website/$_</a>\n";
    }
    }
    -----------------

    I would normally call the subroutine like &links; but I want to put the
    result into a variable in order to stick it into an e-mail. I have been
    trying all day reading all my perl books and it's time to ask for help.

    Thanks.

    --
    Just getting into the best language ever...
    Fancy a me.uk? Just ask!!!
    Gavin Guest

  2. #2

    Default Re: Help with putting a subroutine into a variable?

    > Hi all, 

    Good start.
     

    Your sub breaks encapsulation because it relies on the fact that pics
    and $website are available in the sub but have not been passed into it.
    Generally we want our subs to take arguments and return values. If you
    were to move this sub to the top of the file or to another file (such as
    a library/module) it would break. So the first thing you should correct
    is the encapsulation by making your sub accept its arguments and return
    a value.

    sub links {
    my ($base_url, list) = _;
    foreach my $element (list) {
    print .....
    }
    return;
    }
     

    Note that we don't want to call C<&links> that is better written as
    C<links()>.

    What is the result? In your case you are printing the links, so there
    is no real result. You need to decide what the return value of the sub
    will be, maybe the list of urls? a bool? undef for positive or an
    exception for failure? In the case of the list you should be C<push>ing
    the values to list and then returning the list. In this last case we
    can call the sub such as,

    my ahrefs = links($website, pics);

    foreach my $link (ahrefs) {
    print "$link<br />\n";
    }

    For instance.
     

    Give it a shot, see if this helps, if not come back and ask more.

    http://danconia.org

    Wiggins Guest

  3. #3

    Default Re: Help with putting a subroutine into a variable?

    > Your sub breaks encapsulation because it relies on the fact that pics 

    I have the Perl V3.0 CD Bookshelf (Much better than V4.0 IMHO) and this
    makes sense now. Found this bit:

    ------------------------

    4.6. Private Variables in Subroutines

    But if Perl can give us a new _ for every invocation, can't it give us
    variables for our own use as well? Of course it can.

    By default, all variables in Perl are global variables; that is, they are
    accessable from every part of the program. But you can create private
    variables called lexical variables at any time with the my operator:

    sub max {
    my($a, $b); # new, private variables for this block
    ($a, $b) = _; # give names to the parameters
    if ($a > $b) { $a } else { $b }
    }

    These variables are private (or scoped) to the enclosing block; any other
    $a or $b is totally unaffected by these two. And that goes the other way,
    too -- no other code can access or modify these private variables, by
    accident or design.[108] So, we could drop this subroutine into any Perl
    program in the world and know that we wouldn't mess up that program's $a
    and $b (if any).[109]

    -------------------------

    --
    Just getting into the best language ever...
    Fancy a me.uk? Just ask!!!
    Gavin Guest

  4. #4

    Default Re: Help with putting a subroutine into a variable?

    Wiggins d Anconia said: 
    >
    > Good start.[/ref]

    Courtesy of the Lama :-)
     
    >
    > Your sub breaks encapsulation because it relies on the fact that pics[/ref]
    and $website are available in the sub but have not been passed into it.
    Generally we want our subs to take arguments and return values. If you
    were to move this sub to the top of the file or to another file (such as
    a library/module) it would break. So the first thing you should correct
    is the encapsulation by making your sub accept its arguments and return
    a value. 

    Doesn't this still get the scalar and array from what I defined at the top?

    Also, why do you assign them to _, can't we use that when iterating list?

    Why wouldn't it accept it's arguments?
     [/ref]
    result into a variable in order to stick it into an e-mail. I have been
    trying all day reading all my perl books and it's time to ask for help. 
    >
    > Note that we don't want to call C<&links> that is better written as[/ref]
    C<links()>. 
    is no real result.

    That is what I want, but I can't figure how to but the list into the
    e-mail message.
     

    A list of urls.
     
    the values to list and then returning the list. In this last case we
    can call the sub such as, 

    I get this part.
     

    Isn't the above the same as my subroutine?
     
    >
    > Give it a shot, see if this helps, if not come back and ask more.[/ref]

    Much appreciated. I will be re-reading Ch2-4 of the Lama tonight.



    --
    Just getting into the best language ever...
    Fancy a me.uk? Just ask!!!


    Gavin Guest

  5. #5

    Default Re: Help with putting a subroutine into a variable?

    > Wiggins d Anconia said:

    <snip>
     
    >
    > Doesn't this still get the scalar and array from what I defined at the[/ref]
    top? 

    No, note that I have changed the names (on purpose) so that they are
    defined specifically to the sub (as your other email mentioned). Since
    I have given them new names they are essentially copies of the original
    data, but since the variables are within the scope of the sub I can now
    take the sub and drop it into a library and it will still work, though
    the calling syntax has to be different (see summary below).
     
    list? 

    I am not assigning them *to* _, but *from* _. In other words, when the
    subroutine is called it automatically stuffs the arguments given to it
    in _. Then within the subroutine I want to pull those arguments back
    out of _ and use them to do something (you don't really have to give
    them new names, but accessing into _ as $_[0], $_[1], etc. gets
    annoying). Of course that is where hashes come into play :-)...
     

    In your case you were not using the _ values so it was not expecting
    (or using) the arguments, and your calling syntax of C<links()>
    indicates that no arguments are being passed.
     [/ref]
    > result into a variable in order to stick it into an e-mail. I have been
    > trying all day reading all my perl books and it's time to ask for help. 
    > >
    > > Note that we don't want to call C<&links> that is better written as[/ref]
    > C<links()>. 
    > is no real result.
    >
    > That is what I want, but I can't figure how to but the list into the
    > e-mail message.[/ref]

    See summary below...

     
    >
    > A list of urls.[/ref]

    Ok.
     
    > the values to list and then returning the list. In this last case we
    > can call the sub such as, 
    >
    > I get this part.

    >
    > Isn't the above the same as my subroutine?
    >[/ref]

    Sort of, except I have broken the different functional components apart
    and can now reuse C<links()> as a sub to build a list rather than to
    *print* a list. But in some cases I want to print a list, so I just
    print it afterwards.
     
    > >
    > > Give it a shot, see if this helps, if not come back and ask more.[/ref]
    >
    > Much appreciated. I will be re-reading Ch2-4 of the Lama tonight.
    >[/ref]

    The llama is excellent.

    Ok so for the summary,

    Starting over with your sub that breaks encapsulation by not accepting
    arguments, and not returning a value, and has the less portable benefit
    of always printing the values (despite the fact that sometimes we might
    want them returned to us).

    my pics = (list);
    my $website = 'url';
    links();

    sub links {
    foreach (pics) {
    print "<a href=\"$website/$_\">$website/$_</a>\n";
    }
    }

    So in the above your sub *assumes* pics and $website exist. We want to
    switch it so that the sub assumes nothing and accepts all of the info it
    needs as arguments. So we get,

    my pics = (list);
    my $website = 'url';
    links($website, pics);

    sub links {
    my ($url, list) = _;
    foreach my $element (list) {
    print "<a href=\"$url/$_\">$url/$_</a>\n";
    }
    }

    Notice that the call to the sub changed, and that it now doesn't use
    either of pics, or $website, which means that it could be a list of
    anything and the $website is really just a base url. But we are still
    stuck with it just printing to STDOUT, so lets make it return a value
    instead making it more useful for other things...

    my pics = (list);
    my $website = 'url';
    my piclinks = links($website, pics);

    # now piclinks is just a list that we could put in an email instead
    print for piclinks;

    sub links {
    my ($url, list) = _;
    my return;
    foreach my $element (list) {
    push return, "<a href=\"$url/$_\">$url/$_</a>\n";
    }
    return return;
    }

    So again I changed the call to now catch what the sub returns, and
    stopped the sub from printing the links. Inside of the sub I built a
    temporary list and returned it so that the caller could catch it and use
    it. (I have specifically left out the syntactic sugar of editing the
    elements in place, etc. for clarity since we are discussing subs not
    shortening of code.)

    So why is this better, still does the same thing? Mostly because it is
    reusable now. For instance,

    my piclist1 = (list);
    my piclist2 = (a different list);
    my $website = 'url';

    my email_list = links($website, piclist1);
    my db_list = links($website, piclist2);

    # send an email with email_list

    # store to a database with db_list

    Now your sub is generic, it doesn't rely on the specific names, pics
    and $website, and doesn't cause data to be printed when you might not
    want it to. Obviously this is a contrived example but as things get
    more complex it becomes absolutely critical.

    HTH,

    http://danconia.org
    Wiggins Guest

  6. #6

    Default Re: Help with putting a subroutine into a variable?

    > # send an email with email_list 

    Thanks. This is one of the most complete answers I have ever had and I really
    appreciate it.

    I will let you know how I get on.

    Gavin.

    --
    Just getting into the best language ever...
    Fancy a me.uk? Just ask!!!
    Gavin Guest

Similar Threads

  1. putting a variable into a querystring?
    By paulmmalone in forum Dreamweaver AppDev
    Replies: 3
    Last Post: July 27th, 04:16 PM
  2. plPerl subroutine
    By FERREIRA in forum PostgreSQL / PGSQL
    Replies: 3
    Last Post: March 16th, 03:37 PM
  3. JavaScript? Putting a variable in the midst of a Regular Expression.
    By Garrett_Cobarr@adobeforums.com in forum Adobe Acrobat Macintosh
    Replies: 2
    Last Post: August 8th, 09:39 PM
  4. putting a variable into getURL in flash
    By dubland webforumsuser@macromedia.com in forum Macromedia Flash Actionscript
    Replies: 4
    Last Post: February 9th, 10:34 PM
  5. How do you Call a Perl subroutine with a variable name?
    By Gunnar Hjalmarsson in forum PERL Miscellaneous
    Replies: 27
    Last Post: July 30th, 04:30 PM

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139