4 Replies - 2367 Views - Last Post: 23 May 2012 - 07:35 AM

#1 Crockeo  Icon User is offline

  • D.I.C Head

Reputation: 44
  • View blog
  • Posts: 247
  • Joined: 21-June 11

A Couple Perl Questions

Posted 21 May 2012 - 12:13 PM

I've gotten into Perl recently, and I've had a couple of general (and not so general) questions pertaining to it.


1) How should I handle unintended input to functions?
If I have a function like so, should I handle unintended input within the function, or depend on the end user to provide the correct input?

sub foo
{
    $x = $_[0];

    return $x + 10;
}



2) How does one use modules from another folder?
Since I'm from a C++/Java background I (generally speaking) like to organize all of my source code within different folders. How would one lets say have a file tree like so and access all of the modules from Master.pl (how could I use the use command to import the Foo and Bar modules?):
Master.pl
Foo
|
 \Foo.pm
Bar
|
 \Bar.pm




3) Abstraction in classes.
One of the things I need to, but haven't learned yet; how does one create abstraction in classes. I know in Java one defines it as abstract, but I can't seem to figure it out in Perl.


Anyways, thank you for all of your help!
~Crockeo

Is This A Good Question/Topic? 0
  • +

Replies To: A Couple Perl Questions

#2 dsherohman  Icon User is offline

  • Perl Parson
  • member icon

Reputation: 226
  • View blog
  • Posts: 654
  • Joined: 29-March 09

Re: A Couple Perl Questions

Posted 22 May 2012 - 02:12 AM

View PostCrockeo, on 21 May 2012 - 08:13 PM, said:

I've gotten into Perl recently, and I've had a couple of general (and not so general) questions pertaining to it.


Welcome!

View PostCrockeo, on 21 May 2012 - 08:13 PM, said:

1) How should I handle unintended input to functions?
If I have a function like so, should I handle unintended input within the function, or depend on the end user to provide the correct input?

sub foo
{
    $x = $_[0];

    return $x + 10;
}



First piece of advice: Always use strict; use warnings; at the start of your programs and keep them in effect at all times unless you a: know exactly what they do, b: can clearly express a reason why you need them to not do that in a specific section of code, and c: know how to turn off only the part you don't want and how to turn it off only for the section where you don't want it. I mention this here because that sub wouldn't compile under strict unless $x is declared elsewhere and used as a global. :D

To answer the actual question, my preference is to check the validity of data as soon as possible ("fail fast") and re-check it at the last moment before invalid data would cause a problem (just in case something got there by an unexpected route without having been checked previously), so I would, in this case, have one check when the user enters the data and another in the sub itself.

As for what to do when invalid data is encountered, that's very situational... Where practical, I tend to prefer to die when an error is encountered. While this normally will kill the program, it also serves as Perl's version of throwing an exception, with eval {...} taking the place of try {...}, although there are modules such as Try::Tiny which provide a more C++/Java-like syntax (and a little more reliability in Perl versions prior to 5.14).

But there are also other cases where treating it as an exception isn't entirely practical and it may be simpler to just use something like while (not_valid($data)) { $data = get_data } or whatever. Going back to my "validate twice" theory, I suppose the immediate check when input is received is more likely to be a "loop until you get good data" case, while the last-minute recheck deep in some sub or other will almost always be "throw an exception".

View PostCrockeo, on 21 May 2012 - 08:13 PM, said:

2) How does one use modules from another folder?
Since I'm from a C++/Java background I (generally speaking) like to organize all of my source code within different folders. How would one lets say have a file tree like so and access all of the modules from Master.pl (how could I use the use command to import the Foo and Bar modules?):
Master.pl
Foo
|
 \Foo.pm
Bar
|
 \Bar.pm



You can add directories to the module search path with the use lib pragma. Also, normal practice is to put modules into a lib subdirectory. So, assuming the structure
Master.pl
lib
  - Foo
    - Foo.pm
  - Bar
    - Bar.pm

you could access the project's modules with:
use lib 'lib';
# Note: The above line will only work properly if you first cd into
# the directory where Master.pl is located before running it.  To be
# able to run it from anywhere, use the two lines below instead:
# use FindBin '$RealBin';
# use lib "$RealBin/lib";

use Foo::Foo;
use Bar::Bar;



View PostCrockeo, on 21 May 2012 - 08:13 PM, said:

3) Abstraction in classes.
One of the things I need to, but haven't learned yet; how does one create abstraction in classes. I know in Java one defines it as abstract, but I can't seem to figure it out in Perl.


Perl doesn't really support the notion of an abstract class - if a class exists, you can instantiate it. The closest you can get is to do something like
package MyAbstractClass;

sub new {
  die "MyAbstractClass is abstract."
}


There may also be a more Perlish way of approaching whatever you're trying to do. Can you explain in more detail the goal that you "need to" use an abstract class for?
Was This Post Helpful? 3
  • +
  • -

#3 Crockeo  Icon User is offline

  • D.I.C Head

Reputation: 44
  • View blog
  • Posts: 247
  • Joined: 21-June 11

Re: A Couple Perl Questions

Posted 22 May 2012 - 10:22 AM

Thank you yet again for your fantastically thorough and long response.

To give you some more information, since I've done quite a large amount of game development in other languages, whenever I go to a new language I 'port it over' if you will. While I generally never end up using it, I find it good OOP, and general language practice.

It's like manually translating a book to help you with whatever language you're learning.

The reason why I wanted abstraction is to make sure a subclass has its own definition of a function. (Or sub, as I should start calling it). While I can leave it up to the user to make sure to override the tick() function, I wanted to make sure that whoever is using my library MUST override it.


The more I type it out, though, the more it sounds like me thinking in C++/Java terms rather than Perl.


Thanks for your help!
Was This Post Helpful? 0
  • +
  • -

#4 dsherohman  Icon User is offline

  • Perl Parson
  • member icon

Reputation: 226
  • View blog
  • Posts: 654
  • Joined: 29-March 09

Re: A Couple Perl Questions

Posted 23 May 2012 - 05:07 AM

View PostCrockeo, on 22 May 2012 - 06:22 PM, said:

Thank you yet again for your fantastically thorough and long response.


It's what I do here. :D

View PostCrockeo, on 22 May 2012 - 06:22 PM, said:

The reason why I wanted abstraction is to make sure a subclass has its own definition of a function. (Or sub, as I should start calling it). While I can leave it up to the user to make sure to override the tick() function, I wanted to make sure that whoever is using my library MUST override it.

The more I type it out, though, the more it sounds like me thinking in C++/Java terms rather than Perl.


Yes, it does. That happens quite a bit. I mostly see it in the form of for (my $i = 1 ; $i <= 10 ; $i++)[1], but trying to use Java/C++ OO patterns is common, too.

In this case, adapting the example from my previous post sounds like the way to go. Maybe adjusting it a little to something more like
sub tick {
  die "tick() not implemented by $_[0]";
}
so that the error message will also tell you which class forgot to implement the method.

Another option would be to not define a tick sub at all in the base class, but I tend to prefer including one that will just die if called, since that documents that the method should exist.

Yet another possibility would be to look into Moose. Personally, I don't like Moose much[2], but the Perl community at large loves it and a lot of people consider it to be The Right Way to do objects in Perl 5. In the Moose model, you would define a Role which requires 'tick' and the classes which are subclasses in your other versions of the code would instead does that Role, which in turn would require them to define a tick method (or else they'll fail to compile).


[1] The Perlish way is to use for my $i (1 .. 10) instead, or for my $element (@array) if you're only going to use $i as an array index.

[2] Moose provides a declarative OO syntax which gives a lot of automatic type-checking for parameters, avoids having to explicitly unroll @_, etc. However, all the things it "saves" you from having to do are things that I don't mind doing (I kind of like operating on that lower level, actually...), plus there's a noticeable performance cost (especially at app startup) for everything it provides and it produces a lot of atrocious error messages, so I prefer not to use it. But the Moose team does acknowledge the issues with performance and error reporting and those are always high priorities for them to improve, so I may yet change my mind someday. Roles are pretty nice, after all...
Was This Post Helpful? 1
  • +
  • -

#5 Crockeo  Icon User is offline

  • D.I.C Head

Reputation: 44
  • View blog
  • Posts: 247
  • Joined: 21-June 11

Re: A Couple Perl Questions

Posted 23 May 2012 - 07:35 AM

Thank you for all of your help. After you originally posted about using die I looked it up on the Perl documentation.

Hopefully soon I'll be able to take some of the load off of your shoulders with supporting the community and the such.



Thank you again!
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1