1

I have a subroutine (in Perl) that needs to make a call to another one transfering its arguments and also adding a string. I have tried something like this (but I'm looking for THE answer, not just correcting this ...):

sub TestBase($)
{
    print @_;
    return 'hard processed string';
}

sub Test($)
{
    print @_;
    return TestBase(@_, 'Filename.txt');
}

This one fails with "Too many arguments for main::TestBase" (all these years and I still use cmd.com, no easy copy-paste in this case!).

Liviu
  • 1,859
  • 2
  • 22
  • 48
  • I don't know Perl, I'm with Python, given the time and the desire I would prefer to learn Ruby instead. That's it to say that I don't want an extensive Perl documentation. – Liviu Feb 27 '14 at 09:13
  • JavaScript is best suited for passing functions around. – Dan Dascalescu Feb 27 '14 at 09:14
  • @Dan Dascalescu I'm working in Perl because that's what they're using (and I don't want to upset THEM!). I can't change the language. – Liviu Feb 27 '14 at 09:16
  • 1
    See http://stackoverflow.com/questions/297034/why-are-perl-5s-function-prototypes-bad – Alnitak Feb 27 '14 at 09:18
  • 1
    It is easy to reconfigure cmd.com to allow cut and paste with right mouse. Alternatively send to a text file and open in a text editor of your choice. – justintime Feb 27 '14 at 09:19
  • @Alnitak I read that question and I understood nothing. I'm not using subroutines for my intimate pleasure, `TestBase` is already defined and I want to reuse code. Is this bad practice in Perl? – Liviu Feb 27 '14 at 09:27
  • I've answered your question below; re. prototypes, just [read this](http://stackoverflow.com/a/8129070/1269037). – Dan Dascalescu Feb 27 '14 at 09:50
  • I saw your answer below and it works, I even upvoted it when it was below 0, I'll wait for a while before choose it as the answer. – Liviu Feb 27 '14 at 09:55

2 Answers2

4

Perl best practice: don't define function prototypes unless you really know what you're doing.

#!/usr/bin/perl -w
use strict;

sub test_base {
    print @_;
}

sub test {
    print @_;
    return test_base(@_, 'Filename.txt');
}

test('foo', 'bar');
Community
  • 1
  • 1
Dan Dascalescu
  • 143,271
  • 52
  • 317
  • 404
  • 2
    see http://stackoverflow.com/questions/297034/why-are-perl-5s-function-prototypes-bad – Alnitak Feb 27 '14 at 09:19
  • I don't get it: somebody (this Alnitak?) downvoted you because ... you are using prototypes? Where? `sub TestBase($)` in the initial code does it. – Liviu Feb 27 '14 at 09:57
  • Well it wasn't mine either but you can make up for it (karma :) and accept the answer. I highly doubt there is a clearer solution. – Dan Dascalescu Feb 27 '14 at 10:42
  • I never forget to accept an answer, but I always wait for a while. Still, I can make an exception if you really needed it now. – Liviu Feb 27 '14 at 12:19
  • 1
    It is bad practice to use `-w` in the shebang line. It has long been superseded by `use warnings`. Also, why are you using `return` on the result of `test_base` when you don't on the result of `print`? – Borodin Feb 27 '14 at 14:09
  • @Borodin The initial code had a `return`, thanks, forgot about that. Now it's corrected. – Liviu Feb 27 '14 at 15:10
  • 1
    @Liviu: It is most common to see an explicit `return` only when a subroutine must exit at a point before the end. If the intention is just to specify a value to be returned, then most Perl programmers will simply define that value on the last line without a `return`. – Borodin Feb 27 '14 at 15:22
  • @Borodin Thank you, again! Dan will also update his code, I'm sure about that (also glad that I didn't yet accepted :D). `sub TestBase` is not my code, it seems that I have to take some risks and change some (other people) lines! – Liviu Feb 27 '14 at 15:28
1

To clarify and summarize my corrections to Dan's answer, this is what your code should look like.

I've removed the subroutine prototypes, put the open braces on the same line as the subroutine name (as preferred by perldoc perlstyle), changed the names to lower-case (upper case is generally reserved for global variables such as package names), and removed the return keyword.

Note that you would probably be best leaving the subroutine names as they are, especially if other people are writing code that depends on them. Following accepted practice is important, but not as important as keeping the interface to an existing code base static.

#!/usr/bin/perl

use strict;
use warnings;

sub test_base {
  print @_;
  'hard processed string';
}

sub test {
  print @_;
  test_base(@_, 'Filename.txt');
}

my $retval = test('A', 'B', 'C');
print "\n\n", $retval, "\n";

output

ABCABCFilename.txt

hard processed string
Borodin
  • 126,100
  • 9
  • 70
  • 144
  • I'm almost sure that the original subroutine's scope is its file. I intend some small additions (for the time being), but I'll include your recommandations and I expect this to last for a hour or two, next week. Then I will probably accept your answer, thank you for the effort! – Liviu Feb 28 '14 at 15:18
  • By the way, for the perl style, isn't out there a script to check it? My eyes are weak :p! – Liviu Feb 28 '14 at 15:20
  • @Liviu: If you mean the scope where the subroutine can be *called* then it is within the current *package*. If there has been no `package` statement within a compilation unit then global variables are put in the `main` package. Any subroutine from any package can be called if it is fully-qualified with its package name. – Borodin Feb 28 '14 at 17:00