Skip to content

Commit 8472cde

Browse files
committed
Document what "reify" means
- Can't think of a good section to write this in, so writing it in glossary - Fixes #1265
1 parent 3ba0c02 commit 8472cde

File tree

1 file changed

+113
-0
lines changed

1 file changed

+113
-0
lines changed

doc/Language/glossary.pod6

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,119 @@ the JVM. It is an abbreviation of C<Rakuda-do>, which, when translated
750750
from Japanese, means "The Way of the Camel". Also, in Japanese, "Rakudo"
751751
means "Paradise."
752752
753+
=head1 Reify
754+
X<|Reify>
755+
756+
In English language, L<reify means|http://www.dictionary.com/browse/reify> to
757+
"to convert into or regard as a concrete thing." Its meaning in Perl 6 is very
758+
similar, in that conceptual things, like "elements of an infinite list" get
759+
I<reified> when you try to operate on some of them:
760+
761+
# A list containing innfinite number of unreified Fibonacci numbers:
762+
my @fibonacci = 1, 1, * + * … ∞;
763+
764+
# We reify 10 of them, looking up the first 10 of them with array index:
765+
say @fibonacci[^10]; # OUTPUT: «(1 1 2 3 5 8 13 21 34 55)␤»
766+
767+
# We reify 5 more: 10 we already reified on previous line, and we need to
768+
# reify 5 more to get the 15th element at index 14. Even though we need only
769+
# the 15th element, the original Seq still has to reify all previous elements:
770+
say @fibonacci[14]; # OUTPUT: «987␤»
771+
772+
Above we were reifying a L<Seq> we created with the
773+
L<sequence operator|/language/operators#index-entry-%E2%80%A6_operators>, but
774+
other things use the concept as well. For example, an unreified L<Range> is just
775+
the two end points. In some languages, calculating the sum of a huge range is a
776+
lengthy and memory-consuming process, but Perl 6 calculates it instantly:
777+
778+
say sum 1 ..9_999_999_999_999; # OUTPUT: «49999999999995000000000000␤»
779+
780+
Why? Because the sum can be calculated I<without> reifying the Range; that is
781+
without figuring out all the elements it contains. This is why this feature
782+
exists. You can even make your own things you can reify-on-demand, using
783+
L«C<gather> and C<take>|/syntax/gather%20take»:
784+
785+
my $seq = gather {
786+
say "About to make 1st element"; take 1;
787+
say "About to make 2nd element"; take 2;
788+
}
789+
say "Let's reify an element!";
790+
say $seq[0];
791+
say "Let's reify more!";
792+
say $seq[1];
793+
say "Both are reified now!";
794+
say $seq[^2];
795+
796+
# OUTPUT:
797+
# Let's reify an element!
798+
# About to make 1st element
799+
# 1
800+
# Let's reify more!
801+
# About to make 2nd element
802+
# 2
803+
# Both are reified now!
804+
# (1 2)
805+
806+
Following the output above, you can see the print statements I<inside> the
807+
C<gather> got printed only when we reified the individual elements while looking
808+
up an element. Also note, the elements got reified just once. When we printed
809+
the same elements again on the last line of the example, the messages inside
810+
C<gather> we no longer printed. This is because the construct used
811+
already-reified elements from the L<Seq>'s cache.
812+
813+
Note that above we assigned the C<gather> to a L<Scalar> container (the C<$>
814+
sigil), not the L<Positional> one (the C<@> sigil). The reason is that the
815+
C<@>-sigiled variables are I<mostly lazy>. What this means is their
816+
I<reify the stuff assigned to them> right away I<most of the time>. The only
817+
time they don't do it is when the items are known to be
818+
L«C<is-lazy>|/routine/is-lazy», like our sequence generated with infinity as the
819+
end point. We we to assign the C<gather> to a C<@>-variable, the C<say> statements
820+
inside of it would've been printed right away.
821+
822+
Another way to fully-riefy a list, is by calling L«C<.elems>|/routine/elems» on
823+
it. This is the reason why checking whether a list contains any items is best
824+
done by using C<.Bool> method (or just using C<if @array { … }>), since you don't
825+
need to reify I<all> the elements to find out if there are C<any> of them.
826+
827+
There are times where you I<do> want to fully-reify a list before doing something.
828+
For example, the L«C<IO::Handle.lines>|/type/IO::Handle#method_lines» returns
829+
a L<Seq>. The following code contains a bug; keeping reification in mind, try to
830+
spot it:
831+
832+
=for code :skip-test
833+
my $fh = "/tmp/bar".IO.open;
834+
my $lines = $fh.lines;
835+
close $fh;
836+
say $lines[0];
837+
838+
We open a L<file handle|/type/IO::Handle>, then assign return of
839+
L«C<.lines>|/type/IO::Handle#method_lines» to a L<Scalar> variable, so the
840+
returned L<Seq> does not get reified right away. We then
841+
L«C<close>|/routine/close» the file handle, and try to print an element from
842+
C<$lines>.
843+
844+
The bug in the code is by the time we reify the C<$lines> L<Seq> on the last
845+
line, we've I<already closed> the file handle. When the C<Seq's> iterator tries
846+
to generate the item we've requested, it results in the error about attempting
847+
to read from a closed handle. So, to fix the bug we can either assign to
848+
a C<@>-sigiled variable or call L«C<.elems>|/routine/elems» on C<$lines> before
849+
closing the handle:
850+
851+
=for code :skip-test
852+
my $fh = "/tmp/bar".IO.open;
853+
my @lines = $fh.lines;
854+
close $fh;
855+
say @lines[0]; # no problem!
856+
857+
Also good:
858+
859+
=for code :skip-test
860+
my $fh = "/tmp/bar".IO.open;
861+
my $lines = $fh.lines;
862+
say "Read $lines.elems() lines"; #reifying before closing handle
863+
close $fh;
864+
say $lines[0]; # no problem!
865+
753866
=head1 Repository
754867
X<|Repository>
755868

0 commit comments

Comments
 (0)