26

What is the exact difference between :: and -> in Perl?

-> sometimes works where :: does not.

1
  • 5
    -> is used for dereferencing; :: is used for referring to other packages. Can you provide of an example of the ambiguity?
    – fenway
    Commented Oct 27, 2013 at 18:31

3 Answers 3

57

:: has two uses.

  1. It's the namespace separator in package names

     use Foo::Bar;    # Load Foo/Bar.pm
     $Foo::Bar::var   # $var in namespace Foo::Bar
    
  2. Appended to a bareword, it creates a string literal[1].

    The following is the same as 'hello' except it warns if the package hello doesn't exist:

     hello::
    

-> has two uses.

  1. It's used to dereference.

     $array_ref->[$i]
     $hash_ref->{$k}
     $code_ref->(@args)
    
  2. It's used in method calls to denote the invocant.

     CGI->new()        # Static method call
     $cgi->param()     # Object method call
    

You're probably asking what's the difference between

Foo::Bar::mysub()

and

Foo::Bar->mysub()

The former is a function call. The latter is a method call. A method call is like a function call with two differences:

  1. Method calls use inheritance.

  2. Method calls pass the invocant (what's left of the ->) to the sub as its first argument.

{
   package Foo::Baz;
   sub new {
      my ($class, $arg) = @_;
      my $self = bless({}, $class);
      $self->{arg} = $arg;
      return $self;
   }

   sub mysub1 {
      my ($self) = @_;
      print($self->{arg}, "\n");
   }
}

{
   package Foo::Bar;
   our @ISA = 'Foo::Baz'; 
   sub mysub2 {
      my ($self) = @_;
      print(uc($self->{arg}), "\n");
   }
}

my $o = Foo::Bar->new('hi');  # Same as: my $o = Foo::Baz::new('Foo::Bar', 'hi');
$o->mysub1();                 # Same as: Foo::Baz::mysub1($o);
$o->mysub2();                 # Same as: Foo::Bar::mysub2($o);

Notes

  1. Foo->method deceptively calls the sub named Foo if it exists (using its the value it returns as the invocant). Foo::->method, meaning 'Foo'->method, doesn't. More on this here.
2
  • It's worth noting that calling Foo::Bar->f() passes implicit argument 'Foo::Bar' in $_[0], whereas Foo::Bar::f() does not. Commented Oct 27, 2013 at 19:01
  • 2
    @el.pescado, It was both noted ("Method calls pass the invocant (what's left of the ->) to the sub as its first argument.") and demonstrated.
    – ikegami
    Commented Oct 27, 2013 at 19:05
7

When the right hand side is a function -> passes its left hand side as the first argument to the function. So the following examples are equivalent if $foo is an object blessed to package Foo and Bar is in package Foo. -> will resolve inherited methods making it cleaner and more useful for objects.

$foo->Bar();

Foo::Bar($foo);

-> can also take a package name

Foo->Bar();

Foo::Bar('Foo');

This means that -> is generally used in instance methods so that the object is passed its self and constructors so the constructors know which package to bless with. This is usually a parameter so it can be inherited.

1
  • @ikegami Clarified behavior in inheritance Commented Oct 27, 2013 at 18:48
-7

Lots of explanations here, but here is the very simplistic answer for new developers:

FOO::BAR();  # is calling the class's (aka. package's) default object
$FOO->BAR(); # is calling an initiated object

An object typically has properties that are often set, where as an uninitiated object uses the default object properties only.

Say FOO has a property called 'Age' that has a default value of 1 that we can change via a set command earlier in our program. Then we decide to call the package again both ways for fun we could see:

use FOO;
$FOO = new FOO(); #new instance of foo 
$FOO->SetAge(21);

# more code here

print $FOO->GetAge(); # prints 21
print FOO::GetAge(); # prints 1

What about packages without any stored variables? In many cases there may be no difference at all, but this ultimately depends on how the class is written. In the end it is more complex than that.. and this isn't truly the exact answer, but it is what I believe you are looking for based on your question.

Just to prevent confusion generally I do not use the classes/packages name when creating an object. If for some reason I don't know what to call it I prefix it with an 'o' so it is clear it is an object and not a class, which is a good practice for any programing language.

i.e. use

$oFOO = new FOO(); // new object instance of foo

Hope that helps.

2
  • 4
    // is not a comment in Perl. It is use FOO, not using FOO.
    – TLP
    Commented Oct 28, 2013 at 10:04
  • Que is about Perl not Java
    – jkshah
    Commented Oct 29, 2013 at 18:57

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