Skip to content

Commit d7fff10

Browse files
authored
more detail for variable declarators and scope (#4768)
Closes #4319
1 parent 41d9fd2 commit d7fff10

File tree

1 file changed

+78
-1
lines changed

1 file changed

+78
-1
lines changed

doc/Language/variables.rakudoc

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,35 @@ scope.
606606
C<my> is the default scope for subroutines, so C<my sub x() {}> and
607607
C<sub x() {}> do exactly the same thing.
608608

609+
This makes it easy for the compiler take care of several things
610+
before runtime, including:
611+
612+
=item binding subroutine names as read-only (similar to C<constant>)
613+
=item reporting undeclared subroutines
614+
=item argument checking
615+
=item resolving multiple dispatch
616+
=item more detailed error messages
617+
=item optimizations
618+
619+
In general, when an item's visibility is directly associated with
620+
its location in the code, this makes it easier to understand and
621+
reason about the program, which enables not only a more helpful
622+
compiler but also other tools, such as IDEs and debuggers.
623+
624+
Also note that although declarations of constants, enumerations,
625+
modules, and types of various kinds (classes, subsets, grammars,
626+
roles) all default to package scoping (see C<our> below), you can
627+
prefix such a declaration with C<my> to keep it from being exposed
628+
in the API, which frees you to modify it in future revisions without
629+
breaking dependents. For example:
630+
631+
class Foo { # visible in GLOBAL
632+
my class ImplementationDetail { # hidden from users of Foo
633+
# ...
634+
}
635+
# ...
636+
}
637+
609638
=head2 The C<our> declarator
610639

611640
C<our> variables are created in the scope of the surrounding package. They also create
@@ -618,15 +647,63 @@ an alias in the lexical scope, therefore they can be used like C<my> variables a
618647

619648
# Available as $M::Var here.
620649

650+
Although lexical scoping with C<my> has many advantages, sometimes
651+
we need to share more widely than within a given lexical scope,
652+
and using the C<is export> trait can lead to namespace conflicts.
653+
Package scoping with C<our> assigns symbols to distinct namespaces,
654+
avoiding conflicts. For example, to use the Cro clients for both
655+
HTTP and WebSockets in the same code, just refer to them as
656+
C<Cro::HTTP::Client> and C<Cro::WebSocket::Client> respectively.
657+
658+
Packages are introduced by package declarators, such as C<class>,
659+
C<module>, C<grammar>, and (with caveats) C<role>. An C<our> declaration
660+
will make an installation in the enclosing package construct. Then
661+
users of your code (literally, with C<use>) can refer to C<our>-scoped
662+
entities in your package by providing the full package-qualified
663+
name of the entity.
664+
665+
All packages exist within a top-level package named C<GLOBAL> and
666+
thus are globally visible, so declaring an C<our>-scoped variable
667+
is declaring a global variable, even with namespace control.
668+
Anything that ends up visible via C<GLOBAL> is effectively part of
669+
your API, so consider accordingly.
670+
671+
The kind of elements that are most likely to be shared default to
672+
package (C<our>) scope, namely:
673+
=item type declarations, including C<class>, C<role>, C<grammar>, and C<subset>
674+
=item constants
675+
=item enumerations
676+
=item C<module> declarations
677+
678+
Items that do I<not> default to package scope:
679+
=item subroutines default to lexical (C<my>) scope, as discussed above
680+
=item methods are scoped with C<has> (only visible through a method dispatch)
681+
=item variables have no default scope (although the most common choice here, C<my>, is also the shortest to type)
682+
621683
In order to create more than one variable with package scope,
622684
at the same time, surround the variables with parentheses:
623685

624686
our ( $foo, $bar );
625687

626688
see also L<the section on declaring a list of variables with lexical or package scope|/language/variables#index-entry-declaring_a_list_of_variables>.
627689

690+
=head3 Scoping tips: C<my> vs C<our>
691+
692+
It can be a good idea to make an element I<less visible> than the default (for example, C<my> on constants for internal use or classes used to structure
693+
implementation details). Whenever you need to expose something in the API, remember there are at least three ways:
694+
=item an C<our> scoped element, with access controlled by the package namespacing
695+
=item a C<sub> (visible with the C<is export> trait), and potential access control through C<sub EXPORT>
696+
=item a C<method> (visible through its package-scoped C<class>)
697+
698+
In summary:
699+
=item Use C<my> scope for everything that's an implementation detail
700+
=item Also use C<my> scope for things that you plan to C<export>, but remember that exporting puts symbols into the single lexical scope of the consumer and
701+
risks name clashes, so be thoughtful about exporting particularly generic names
702+
=item Use C<our> for things that are there to be shared, and when it's desired to use namespacing to avoid clashes
703+
=item The elements we'd most want to share default to C<our> scope anyway, so explicitly writing C<our> should give pause for thought
704+
628705
X<|Language,declaring a list of variables>
629-
=head2 Declaring a list of variables with lexical (C<my>) or package (C<our>) scope
706+
=head3 Declaring a list of variables with lexical (C<my>) or package (C<our>) scope
630707

631708
It is possible to scope more than one variable at a time, but both C<my>
632709
and C<our> require variables to be placed into parentheses:

0 commit comments

Comments
 (0)