Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it a design flaw that Perl subs aren't lexically scoped?

Tags:

scope

perl

raku

{
  sub a {
    print 1;
  }
}
a;

A bug,is it?

a should not be available from outside.

Does it work in Perl 6*?

* Sorry I don't have installed it yet.

like image 229
new_perl Avatar asked Sep 23 '11 02:09

new_perl


People also ask

Is scheme lexically scoped?

Scheme uses a lexical scope rule. (We can also say that Scheme is statically scoped, rather than dynamically scoped, like some old Lisps.) When you see a variable name in the code, you can tell what variable it refers just to by looking at the source code for the program.

Is Python lexically scoped?

JavaScript and other languages such as the C family and Python use lexical scope , also called static scope , which means that scope nests according to where functions and variables are declared.

What is difference between my and our?

In other words, our has the same scoping rules as my, but does not necessarily create a variable. Save this answer. Show activity on this post. my is used for local variables, whereas our is used for global variables.

What does our mean in Perl?

In Perl the our keyword is used to declare one or more package variables. More exactly it creates lexical alias to a packaga variable, but for our practical purposes our means we are allowed to use the package variable without giving the fully qualified name and without violating the rules of use strict.


6 Answers

Named subroutines in Perl are created as global names. Other answers have shown how to create a lexical subroutines by assigning an anonymous sub to a lexical variable. Another option is to use a local variable to create a dynamically scoped sub.

The primary differences between the two are call style and visibility. The dynamically scoped sub can be called like a named sub, and it will also be globally visible until the block it is defined in is left.

use strict;
use warnings;
sub test_sub {
    print "in test_sub\n";
    temp_sub();
}

{
    local *temp_sub = sub {
        print "in temp_sub\n";
    };
    temp_sub();
    test_sub();
}
test_sub();

This should print

in temp_sub
in test_sub
in temp_sub
in test_sub
Undefined subroutine &main::temp_sub called at ...
like image 190
Ven'Tatsu Avatar answered Oct 07 '22 20:10

Ven'Tatsu


At the risk of another scolding by @tchrist, I am adding another answer for completeness. The as yet to be released Perl 5.18 is expected to include lexical subroutines as an experimental feature.

Here is a link to the relevant documentation. Again, this is very experimental, it should not be used for production code for two reasons:

  1. It might not be well implemented yet
  2. It might be removed without notice

So play with this new toy if you want, but you have been warned!

like image 36
Joel Berger Avatar answered Oct 07 '22 22:10

Joel Berger


In Perl 6, subs are indeed lexically scoped, which is why the code throws an error (as several people have pointed out already).

This has several interesting implications:

  • nested named subs work as proper closures (see also: the "will not stay shared" warning in perl 5)
  • importing of subs from modules works into lexical scopes
  • built-in functions are provided in an outer lexical scope (the "setting") around the program, so overriding is as easy as declaring or importing a function of the same name
  • since lexpads are immutable at run time, the compiler can detect calls to unknown routines at compile time (niecza does that already, Rakudo only in the "optimizer" branch).
like image 23
moritz Avatar answered Oct 07 '22 20:10

moritz


Subroutines are package scoped, not block scoped.

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

package A;
sub a {
    print 1, "\n";
}
a();
1;

package B;
sub a {
    print 2, "\n";
}
a();
1;
like image 42
Bill Ruppert Avatar answered Oct 07 '22 20:10

Bill Ruppert


If you see the code compile, run and print "1", then you are not experiencing a bug.

You seem to be expecting subroutines to only be callable inside the lexical scope in which they are defined. That would be bad, because that would mean that one wouldn't be able to call subroutines defined in other files. Maybe you didn't realise that each file is evaluated in its own lexical scope? That allows the likes of

my $x = ...;
sub f { $x }
like image 40
ikegami Avatar answered Oct 07 '22 21:10

ikegami


Yes, I think it is a design flaw - more specifically, the initial choice of using dynamic scoping rather than lexical scoping made in Perl, which naturally leads to this behavior. But not all language designers and users would agree. So the question you ask doesn't have a clear answer.

Lexical scoping was added in Perl 5, but as an optional feature, you always need to indicate it specifically. With that design choice I fully agree: backward compatibility is important.

like image 39
reinierpost Avatar answered Oct 07 '22 20:10

reinierpost