2
\$\begingroup\$

I've created a program for my own purposes in three different languages, Perl, Python, and Ruby. Each program will be posted in with their own tag but I will add links to them through on each post. The program itself is very simple, all it does is ask the user about three different languages which are saved into an array, it then prompts the user to choose a language that runs through an if statement, and if the user chooses the language they're writing in it then takes a random language from the array and outputs it.

See also Python

See also Ruby

use strict;
use warnings;

sub welcome {
    my @choices = qw( Perl Python Ruby );
    my $lang = 3;
    print("Welcome, to the test script, this will test what language you would like to learn.. In order to find out these choices, write this same definition in all three different languages\n");
    print("There are  $lang, languages to chose from please pick one:\n");
    print "@choices\n";
    my $choice = <STDIN>;
    chomp $choice;
    if ($choice eq "Ruby") {
        print("You have chosen Ruby!\n");
    } 
    elsif ($choice eq "Python") {
        print("You have chosen Python!\n");
    } 
    else {
        print("You're already writing in Perl!! Let me choose for you:\n");
        my $rand_elm = @choices[rand @choices];
        print "$rand_elm\n"
    }
}
welcome();

Perl took me the longest out of all the programs I wrote, this was my first ever Perl script. With all the ; and the random symbols I had to use to make variables and arrays, it was defiantly hard. However I really enjoyed writing this in Perl, it was something different. Perl maxed out as the longest program at a total of 30 lines. At one point I kept getting an NameError that was due to me missing a ; at the chomp function. All in all I think Perl is definitely a great language to learn.

I also have some questions about Perl:

  • Is there any better syntax that I should be using here in order to shorten the program?
  • Does Perl have an equivalent to Ruby's puts?
  • Why is it easier to use a sub instead of a function?

example:

 welcome(); 
 # instead of
 sub welcome();
\$\endgroup\$
  • 3
    \$\begingroup\$ perl equivalent to puts: I gave you that already: stackoverflow.com/a/33610494/7552 \$\endgroup\$ – glenn jackman Nov 10 '15 at 13:39
  • \$\begingroup\$ What is an "actual definition"? In Ruby, you use def to define a method; in Perl you use sub to define a subroutine. Same idea, different keyword. \$\endgroup\$ – glenn jackman Nov 10 '15 at 13:40
  • \$\begingroup\$ @glennjackman I know you did, posted it because I didn't have any other question. Also I guess that's where I was confused, I was unaware that they're the same concept. \$\endgroup\$ – 13aal Nov 10 '15 at 13:43
4
\$\begingroup\$

Here's my rewrite with some comments.

#! /usr/bin/perl
use warnings;
use strict;

sub welcome {
    my @choices = qw( Perl Python Ruby );
    my $count = @choices;  # Perl knows the number of the elements in an array.
    print << "__TEXT__";   # Print a "here" document.
Welcome to the test script, this will test what language you would
like to learn. In order to find out these choices, write this same
definition in all three different languages. There are $count languages
to chose from please pick one:
@choices
__TEXT__

    chomp(my $choice = <STDIN>);  # Read and chomp in one line.
    if (grep $_ eq $choice, qw( Ruby Python )) {  # No need to test separately.
        print "You have chosen $choice!\n";
    }
    else {
        print "You're already writing in Perl!! Let me choose for you:\n",
            "$choices[rand @choices]\n"; # To extract a single element, use the $, not @.
    }
}
welcome();
  • say is like print plus a newline.

  • sub defines a subroutine. What do you mean by "actual definition"?

Note that the program might choose Perl again.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ The only thing I'd add is $choice =~ s/^\s+|\s+$/g; to trim leading/trailing whitespace to give the eq operator a better chance. If this is used, chomp is not necessary. \$\endgroup\$ – glenn jackman Nov 10 '15 at 13:55
  • \$\begingroup\$ @choroba Your rewrite looks beautiful. I rewrote the question with an example \$\endgroup\$ – 13aal Nov 10 '15 at 14:19
  • 1
    \$\begingroup\$ @LostBam: welcome() is a call, sub welcome { is a definition. \$\endgroup\$ – choroba Nov 10 '15 at 18:46
5
\$\begingroup\$

What you did well

  • use strict;, use warnings;, and my scoping
  • qw(list of words) instead of ('list', 'of', 'words')
  • Generally straightforward, readable Perl.

Suggestions

  • There is a hard-coded correspondence between my $lang = 3 and the fact that there are three choices. My suggestion:

    my $choices = @choices;
    

    In Perl, $choices and @choices are different variables: the former is a scalar, and the latter is a list. The assignment above coerces the list into a scalar, and it does so by taking the number of elements in the list. (You used this technique in @choices[rand @choices].

  • Parentheses are optional for subroutine calls, and they are typically omitted for well-known functions such as print.
  • For maintainability, terminate the last print with a semicolon, even if you aren't required to.
  • As @glennjackman already told you, say would be better than print, as it also outputs a trailing newline.
  • Avoid super-long string literals by using a here document.

        print <<"INTRO";
    Welcome to the test script…
    There are $choices languages to choose from.
    @choices
    INTRO
    
  • Your logic is rather trusting: any input other than "Ruby" or "Python" is treated as if it were "Perl".

    A better way:

    use feature qw(say);
    …
    
    chomp(my $choice = <STDIN>);
    if ($choice eq 'Perl') {
        say "You're already writing in Perl!! Let me choose for you:";
        say @choices[rand @choices];
    } elsif (grep { $choice eq $_ } @choices) {
        say "You have chosen $choice!";
    }
    
  • A possible outcome is "You're already writing in Perl!! Let me choose… Perl". I consider that to be a logic bug.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ I had no idea you could use grep in Perl?? I understand where you're saying there's a logic bug in the script. But can I make it so that it will not choose Perl..? \$\endgroup\$ – 13aal Nov 10 '15 at 14:15
  • 1
    \$\begingroup\$ @LostBam grep in perl is function used to filter the contents of an array based on some user-defined criteria. It's not exactly like the /bin/grep command you're familiar with. Perl's grep is like Ruby's Array.select \$\endgroup\$ – glenn jackman Nov 10 '15 at 15:35
  • \$\begingroup\$ @glennjackman Awh that makes a whole lot more sense, that's very good to know, I'm going to rewrite all the programs with all the new ideas I've learned, thank you all! \$\endgroup\$ – 13aal Nov 10 '15 at 15:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.