diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 000000000..84c64d1d2 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,21 @@ +name: test +on: + push: + branches: [ master ] + paths: + - 'doc/**' + pull_request: + branches: [ master ] + paths: + - 'doc/**' + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Run tests + run: ./util/github-action-test.sh t + env: + TEST_IMAGE: docker.io/jjmerelo/perl6-doccer:latest diff --git a/.gitignore b/.gitignore index 8ba89c386..f89df947d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ *.swp -index.data *~ html/*.html html/css/app.css @@ -14,7 +13,7 @@ html/images/type-graph* html/js/search.js html/js/app.js .precomp -precompiled +.pod-precomp assets/assetpack.db assets/cache .sass-cache/ @@ -35,3 +34,4 @@ package-lock.json .idea *.iml .cache-doc +precompiled/ diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index c13876618..000000000 --- a/.travis.yml +++ /dev/null @@ -1,40 +0,0 @@ -language: - - minimal - -os: - - linux - -dist: bionic - -cache: - directories: - - precompiled - - html - - highlights/node_modules - - $HOME/.rakudobrew - - -services: - - docker - -fast_finish: true - -branches: - except: - - gh-pages - -before_install: - - nvm install 7.2.1 - - nvm use 7.2.1 - -install: - - util/travis-build.sh - -script: - - export CXX=$(command -v g++-4.8 >/dev/null 2>&1; if [ $? -eq 1 ]; then printf "g++"; else printf "g++-4.8"; fi) - - $CXX --version - - util/travis-test.sh - -matrix: - include: - - env: BUILDENV=docker diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4ebe9e460..4017be942 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -93,9 +93,9 @@ questions come up in the process feel free to ask in [#raku IRC channel](https://raku.org/community/irc). If the documentation for a type does not exist, create the skeleton of the doc -with the helper tool `util/new-type.p6`. Say you want to create `MyFunnyRole`: +with the helper tool `util/new-type.raku`. Say you want to create `MyFunnyRole`: - $ perl6 util/new-type.p6 --kind=role MyFunnyRole + $ raku util/new-type.raku --kind=role MyFunnyRole Fill the documentation file `doc/Type/MyFunnyRole.pod6` like this: @@ -163,7 +163,7 @@ See [Writing and Testing Examples](writing-docs/EXAMPLES.md) ## Testing method completeness To get a list of methods that are found via introspection but not found in any -Pod6 file under `doc/Type/`, use `util/list-missing-methods.p6`. It takes a +Pod6 file under `doc/Type/`, use `util/list-missing-methods.raku`. It takes a directory or filepath as argument and limits the listing to the given file or any Pod6 files found. All methods listed in `util/ignored-methods.txt` are ignored. diff --git a/CREDITS b/CREDITS index 96872553e..5773f3379 100644 --- a/CREDITS +++ b/CREDITS @@ -299,6 +299,10 @@ E: sgeoster@gmail.com N: ShimmerFairy E: rnddim@gmail.com +N: Sizhe Zhao +E: prc.zhao@outlook.com +U: Prince213 + N: skids E: bri@abrij.org diff --git a/META6.json b/META6.json index a22001f2a..718d0a235 100644 --- a/META6.json +++ b/META6.json @@ -1,6 +1,6 @@ { "name": "p6doc", - "description": "Raku documentation (tools and docs)", + "description": "Raku™ documentation (tools and docs)", "version": "1.006d", "perl": "6.*", "authors": [ @@ -10,16 +10,14 @@ "test-depends": [ "File::Temp", "Test::META", - "Perl6::TypeGraph" + "Doc::TypeGraph", + "Pod::To::HTML" ], "build-depends": [ - "File::Find:ver<0.1.1+>" + "File::Find:ver<0.1.1+>", + "Pod::To::BigPage" ], - "provides": { - "Pod::Cache": "lib/Pod/Cache.pm6", - "Pod::Convenience": "lib/Pod/Convenience.pm6", - "Test-Files": "lib/Test-Files.pm6" - }, + "provides": {}, "support": { "source": "git://github.com/Raku/doc.git" }, diff --git a/Makefile b/Makefile index 3d135537f..6740d60ee 100644 --- a/Makefile +++ b/Makefile @@ -69,7 +69,7 @@ xtest: # Content tests ctest: - prove --exec raku -r t/07-tabs.t xt/perl-nbsp.t xt/trailing-whitespace.t + prove --exec raku -r t/05-tabs.t xt/perl-nbsp.t xt/trailing-whitespace.t start: run diff --git a/README.md b/README.md index 12dafe659..0d5ac60d5 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ -# Official Documentation of Raku +# Official Documentation of Raku™ -[![Build Status](https://travis-ci.org/Raku/doc.svg?branch=master)](https://travis-ci.org/Raku/doc) [![artistic](https://img.shields.io/badge/license-Artistic%202.0-blue.svg?style=flat)](https://opensource.org/licenses/Artistic-2.0) [![Run Status](https://api.shippable.com/projects/591e99923f2f790700098a30/badge?branch=master)](https://app.shippable.com/github/Raku/doc) [![CircleCI](https://circleci.com/gh/Raku/doc.svg?style=shield)](https://circleci.com/gh/Raku/doc/tree/master) +[![artistic](https://img.shields.io/badge/license-Artistic%202.0-blue.svg?style=flat)](https://opensource.org/licenses/Artistic-2.0) +[![CircleCI](https://circleci.com/gh/Raku/doc/tree/master.svg?style=svg)](https://circleci.com/gh/Raku/doc/tree/master) +[![test](https://github.com/Raku/doc/actions/workflows/test.yml/badge.svg)](https://github.com/Raku/doc/actions/workflows/test.yml) An HTML version of this documentation can be found at [https://docs.raku.org/](https://docs.raku.org/) and also @@ -8,10 +10,6 @@ at [`rakudocs.github.io`](https://rakudocs.github.io) (which is actually updated more frequently). This is currently the recommended way to consume the documentation. -This documentation is updated frequently to a GitHub mirror -https://rakudocs.github.io but that might be out of sync with the -official one. - ## Docker container This documentation is also published as @@ -27,11 +25,11 @@ or docker run --rm -it -p 31415:3000 jjmerelo/perl6-doc in case you want it published somewhere else. You can direct your -browser to http://localhost:3000 (or 31415, as the case may be). +browser to `http://localhost:3000` (or 31415, as the case may be). ## README in other languages -* [中文(Chinese)](resources/i18n/zh/README.zh.md) +* [README in Chinese](resources/i18n/zh/README.zh.md) * [README in Dutch](resources/i18n/nl/README.nl.md) * [README in French](resources/i18n/fr/README.fr.md) * [README in German](resources/i18n/de/README.de.md) @@ -42,13 +40,13 @@ browser to http://localhost:3000 (or 31415, as the case may be). ## Install rakudoc -Please see https://github.com/raku/rakudoc for the -command line tool for viewing the documentation +Please see https://github.com/Raku/rakudoc for the +command line tool for viewing the documentation. ## Building the HTML documentation Note: If you just want a copy of the build HTML site and don't want to deal -with the build yourself, you can clone it from here: https://github.com/rakudocs/rakudocs.github.io +with the build yourself, you can clone it from here: https://github.com/rakudocs/rakudocs.github.io. The documentation can be rendered to static HTML pages and/or served in a local web site. This process involves creating a cache of precompiled @@ -56,18 +54,18 @@ documents, so that generation after the first time is sped up. These are the prerequisites you need to install to generate documentation. -* perl 5.20 or later +* perl 5.20 or later. * node 10 or later. * graphviz. * [Documentable](https://github.com/Raku/Documentable). -Please follow these instructions (in Ubuntu) to install them +Please follow these instructions (in Ubuntu) to install them: sudo apt install perl graphviz # perl not installed by default in 18.04 curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash - sudo apt-get install -y nodejs cpanm --installdeps . - zef install Documentable + zef install --deps-only . ; # from inside this checkout > You can install perl and node any way you want, including version managers, as > long as they're available to run from the command line. @@ -104,8 +102,8 @@ examples) are not (yet) available in these formats. These are the prerequisites you need to install: -* Pod::To::BigPage 0.5.2 or later -* Pandoc (EPUB only) +* Pod::To::BigPage 0.5.2 or later. +* Pandoc (EPUB only). You can follow these instructions to install them on Ubuntu or Debian: @@ -167,7 +165,7 @@ explains briefly how to get started contributing documentation. ## Some notes: -**Q:** Why aren't you embedding the docs in the CORE sources?
+**Q:** Why aren't you embedding the docs in the CORE sources?
**A:** Several reasons: 1. This documentation is intended to be universal with @@ -179,7 +177,7 @@ explains briefly how to get started contributing documentation. 3. A separate repo in the Raku Github account invites more potential contributors and editors. -**Q:** Should I include methods from superclasses or roles?
+**Q:** Should I include methods from superclasses or roles?
**A:** No. The HTML version already includes methods from superclasses and roles. @@ -219,6 +217,6 @@ files indicate the copyright and license terms at the top of the file. Currently * [jQuery Cookie plugin](https://github.com/js-cookie/js-cookie): Copyright 2006, 2015 Klaus Hartl & Fagner Brack; [MIT License](http://creativecommons.org/licenses/MIT) -* Examples from Stack Overflow [MIT License](http://creativecommons.org/licenses/MIT); ([ref #1](http://stackoverflow.com/a/43669837/215487) for [1f7cc4e](https://github.com/Raku/doc/commit/1f7cc4efa0da38b5a9bf544c9b13cc335f87f7f6)) -* Table sorter plugin from https://github.com/christianbach/tablesorter ; +* Examples from Stack Overflow; [MIT License](http://creativecommons.org/licenses/MIT) ([ref #1](http://stackoverflow.com/a/43669837/215487) for [1f7cc4e](https://github.com/Raku/doc/commit/1f7cc4efa0da38b5a9bf544c9b13cc335f87f7f6)) +* Table sorter plugin from https://github.com/christianbach/tablesorter; [MIT License](http://creativecommons.org/licenses/MIT) diff --git a/assets/documentable.json b/assets/documentable.json index a724302d4..6834ebaba 100644 --- a/assets/documentable.json +++ b/assets/documentable.json @@ -1,7 +1,7 @@ { - "title-page": "Raku Documentation", + "title-page": "Raku™ Documentation", "pod-root-path": "https://github.com/Raku/doc/blob/master/doc", - "irc-link": "https://webchat.freenode.net/?channels=#raku", + "irc-link": "https://web.libera.chat/?channel=#raku", "kinds": [ { "kind": "language", diff --git a/assets/js/main.js b/assets/js/main.js index 7ad034ffa..e660f1023 100644 --- a/assets/js/main.js +++ b/assets/js/main.js @@ -108,7 +108,7 @@ function setup_debug_mode(){ console.info("checking for dead links"); function report_broken_link(url) { - $('html').find('#search').after('
Broken link: ' + url + ' found. Please report at irc.freenode.net#raku
'); + $('html').find('#search').after('
Broken link: ' + url + ' found. Please report at irc.libera.chat#raku
'); } var seen_link = []; diff --git a/doc/HomePage.pod6 b/doc/HomePage.pod6 index 5cc6c58ff..272d03eb3 100644 --- a/doc/HomePage.pod6 +++ b/doc/HomePage.pod6 @@ -1,11 +1,8 @@ =begin Html -Welcome to the official documentation of the Raku -programming language! -Besides online browsing and searching, you can also -view everything in one file or -contribute -by reporting issues or sending patches. +Welcome to the official documentation of the Raku™ +programming language! Browse the sections below or use the search in the top +navigation.
@@ -47,6 +44,7 @@ by reporting issues or sending patches.
Information about the Raku development community, email lists, IRC and IRC bots, and blogs
+
diff --git a/doc/Language/101-basics.pod6 b/doc/Language/101-basics.pod6 index d8f86efc9..da1b79a4b 100644 --- a/doc/Language/101-basics.pod6 +++ b/doc/Language/101-basics.pod6 @@ -1,6 +1,6 @@ =begin pod :kind("Language") :subkind("Language") :category("beginning") -=TITLE Raku by example 101 +=TITLE Raku™ by example 101 =SUBTITLE A basic introductory example of a Raku program @@ -344,8 +344,8 @@ tournament. When two array items have the same value, C leaves them in the same order as it found them. Computer scientists call this a I. The program takes advantage of this property of Raku's C to achieve the goal by -sorting twice: first by the number of sets won (the primary criterion), then -by the number of matches won (the secondary criterion). +sorting twice: first by the number of sets won (the secondary criterion), then +by the number of matches won (the primary criterion). After the first sorting step, the names are in the order C. After the second sorting step, it's still the same, because no one has @@ -428,7 +428,7 @@ my @people = ; say "The synoptics are: {@people}"; # OUTPUT: «The synoptics are: Luke Matthew Mark␤» -say "{%sets}␤"; +say "{%sets}"; # OUTPUT (From the table tennis tournament): # Charlie 4 @@ -439,7 +439,7 @@ say "{%sets}␤"; When array and hash variables appear directly in a double-quoted string (and not inside curly braces), they are only interpolated if their name is -followed by a postcircumfix E a bracketing pair that follows a +followed by a postcircumfix operator E a bracketing pair that follows a statement. It's also ok to have a method call between the variable name and the postcircumfix. @@ -466,12 +466,13 @@ say "we have @flavors.sort.join(', ')"; B<1.> The input format of the example program is redundant: the first line containing the name of all players is not necessary, because you can find out which players participated in the tournament by looking at their names in the -subsequent rows. +subsequent rows, so in principle we could safely remove it. How can you make the program run if you do not use the C<@names> variable? Hint: C<%hash.keys> returns a list of all keys stored in C<%hash>. -B Remove the line C, and change: +B After removing the first line in C, remove the line C (which would read it), and change: =begin code :preamble my @sorted = @names.sort({ %sets{$_} }).sort({ %matches{$_} }).reverse; diff --git a/doc/Language/5to6-nutshell.pod6 b/doc/Language/5to6-nutshell.pod6 index bdaa85acd..58cae01a4 100644 --- a/doc/Language/5to6-nutshell.pod6 +++ b/doc/Language/5to6-nutshell.pod6 @@ -398,6 +398,13 @@ operator rather than a special syntactic form, and thus L and L is done with adverbs. +An array's biggest index is now available with the C<.end> method: + +=for code :lang +say $#item; # Perl +=for code :preamble +say @item.end; # Raku + =head2 {} Hash indexing/slicing Index and slice operations on hashes no longer inflect the variable's @@ -626,7 +633,7 @@ of a list, or in passing arguments to a sub that expects a flat list of C, then continuing to use C«=>» may break your code. The easiest workaround is to change that I to a regular comma, and manually add quotes to its left-hand side. Or, you can change the sub's API -to L. +to L. A better long-term solution is to change the sub's API to expect Ls; however, this requires you to change all sub calls at once. @@ -1138,7 +1145,7 @@ For lookaround assertions: =item C«(?» -For more info see L«lookahead assertions|/language/regexes#Lookahead_assertions_». +For more info see L«lookahead assertions|/language/regexes#Lookahead_assertions». (Unrelated to <> syntax, the "lookaround" C becomes C«/foo <( bar )> /» @@ -1533,39 +1540,27 @@ shell injection vulnerabilities with such code. =head2 Perl module library path -In Perl one of the environment variables to specify extra search paths for -Perl modules is C. - -=for code :lang -$ PERL5LIB="/some/module/lib" perl program.pl +Perl use C and C to specify extra search paths for modules +and Both of them are ignored by Raku. Instead, you need to use X|RAKULIB>. +The directory separator also changed from ':' to ','. -In Raku this is similar, one merely needs to change a number! As you -probably guessed, you just need to use X|PERL6LIB>: - -=for code :lang -$ PERL6LIB="/some/module/lib" raku program.p6 - -In Perl one uses the ':' (colon) as a directory separator for C, but -in Raku one uses the ',' (comma). For example: +So the equivalent of =for code :lang $ export PERL5LIB=/module/dir1:/module/dir2; -but +is =for code :lang -$ export PERL6LIB=/module/dir1,/module/dir2; - -(Raku does not recognize either the C or the older Perl environment -variable C.) +$ export RAKULIB=/module/dir1,/module/dir2; -As with Perl, if you don't specify C, you need to specify the +As with Perl, if you don't specify C, you need to specify the library path within the program via the C pragma: =for code :lang use lib '/some/module/lib' -Note that C is more of a developer convenience in Raku (as +Note that C is more of a developer convenience in Raku (as opposed to the equivalent usage of C in Perl) and shouldn't be used by module consumers as it could be removed in the future. This is because Raku's module loading isn't directly compatible with operating diff --git a/doc/Language/5to6-perlfunc.pod6 b/doc/Language/5to6-perlfunc.pod6 index c64323d2f..fd6a27fed 100644 --- a/doc/Language/5to6-perlfunc.pod6 +++ b/doc/Language/5to6-perlfunc.pod6 @@ -1391,7 +1391,7 @@ X<| printf - perlfunc> =item printf Raku version is similar; see -L for details +L for details on acceptable format directives. To print to a filehandle other than STDOUT, use the L«C<.printf>|/routine/printf» method on that filehandle. @@ -1441,7 +1441,7 @@ These survive the transition to Raku. Some notes: =for code :lang q/.../; # is still equivalent to using single quotes. qq/.../; # is still equivalent to using double quotes. -qw/.../; # is more commonly rendered as C<< <...> >> in Raku. +qw/.../; # is more commonly written as <...> in Raku. There are some added quoting constructs and equivalents, as explained at L. @@ -1619,7 +1619,7 @@ X<| rewinddir - perlfunc> Not supported in Raku. -The Raku ecosystem has a module L|https://modules.raku.org/dist/P5rewinddir> +The Raku ecosystem has a module L|https://modules.raku.org/dist/P5opendir> which exports a C function that mimics the original Perl behavior as much as possible. @@ -1935,8 +1935,10 @@ also now works as a method: C<"a;b;c".split(';')> =item split -The zero argument version must now be called with an explicit empty string, as -described above. +C now requires a pattern. For the equivalent of Perl's behaviour +of splitting on whitespace when no pattern is specified, use +L (or use C with C as the pattern +and C<:skip-empty> as a named argument). X<| sprintf - perlfunc> =head2 sprintf @@ -2185,12 +2187,13 @@ X<| tie - perlfunc> The Raku alternative to tying a scalar, is the C container. For example: - sub lval() { - Proxy.new( - FETCH => method () { ...}, - STORE => method ($new) { ... } - ) - } +=for code :method +sub lval() { + Proxy.new( + FETCH => method () { ...}, + STORE => method ($new) { ... } + ) +} This makes C a left-value sub. Whenever the value is requested, the C method is called. And whenever it is used in an assignment, the @@ -2265,11 +2268,15 @@ X<| ucfirst - perlfunc> =item ucfirst Raku has done away with C. The title case function -L|/routine/tc> probably does what you need. +L|/routine/tc> or L|/routine/tclc> +probably does what you need; in the first case, it does "title case", which +might correspond to different characters in different alphabets; it defaults +to upper case if there's no title case mapping. On the other hand, C +applies C and then puts the rest of the characters in lower case. -The Raku ecosystem has a module L|https://modules.raku.org/dist/P5lcfirst> -which exports a C function that mimics the original Perl behavior -as much as possible. +The Raku ecosystem has a module +L|https://modules.raku.org/dist/P5lcfirst> which exports a +C function that mimics the original Perl behavior as much as possible. X<| undef - perlfunc> =head2 undef @@ -2330,7 +2337,7 @@ X<| unshift - perlfunc> Works as in Perl, as well as being available as a method: C<@a.unshift("foo");>. I the flattening behavior is different in Raku: C<@b.unshift: @a> will unshift C<@a> into C<@b> as a single element. See also the -L. +L. Also note that C in Raku returns the array to which was pushed, contrary to Perl where it returns the new number of elements. diff --git a/doc/Language/5to6-perlvar.pod6 b/doc/Language/5to6-perlvar.pod6 index a9796250c..333377025 100644 --- a/doc/Language/5to6-perlvar.pod6 +++ b/doc/Language/5to6-perlvar.pod6 @@ -125,7 +125,7 @@ for 1..9 { say $^c, $^a, $^b; last } =end code For more on placeholder variables, see -L +L =head3 %ENV diff --git a/doc/Language/about.pod6 b/doc/Language/about.pod6 index eda36a635..c2598cf49 100644 --- a/doc/Language/about.pod6 +++ b/doc/Language/about.pod6 @@ -13,18 +13,18 @@ An HTML version of the documentation is located online at L. The official source for this documentation is located at -L. +L. This particular document is a quick overview of the process described in more detail in -L. +L. This document also provides a short introduction to writing Raku Pod files, which can be rendered into HTML and other formats. =head1 Structure All of the documentation is written in Raku Pod and kept in the C -directory, and the C and C sub-directories. +directory, and the C and C subdirectories. These files are processed as collections of definitions or "documentables", which are then post-processed and linked together. diff --git a/doc/Language/classtut.pod6 b/doc/Language/classtut.pod6 index 5adf16519..4895955c1 100644 --- a/doc/Language/classtut.pod6 +++ b/doc/Language/classtut.pod6 @@ -483,13 +483,74 @@ X<|FQN> =head2 Private methods Just like attributes, methods can also be private. Private methods are declared -with a prefixed exclamation mark. They are called with C -followed by the method's name. To call a private method of another class the -calling class has to be trusted by the called class. A trust relationship is -declared with C and the class to be trusted must already be declared. -Calling a private method of another class requires an instance of that class -and the fully qualified name (FQN) of the method. Trust also allows access to -private attributes. +with a prefixed exclamation mark. They are called with C followed by the +method's name. In the following implementation of a C class to +extract L metadata from an mp3 file, +methods C, C, and C are private +methods while the remaining ones are public methods: + +=begin code +class MP3TagData { + has $.filename where { .IO ~~ :e }; + + has Str $.title is built(False); + has Str $.artist is built(False); + has Str $.album is built(False); + has Str $.year is built(False); + has Str $.comment is built(False); + has Int $.genre is built(False); + has Int $.track is built(False); + has Str $.version is built(False); + has Str $.type is built(False) = 'ID3'; + + submethod TWEAK { + with $!filename.IO.open(:r, :bin) -> $fh { + $fh.seek(-128, SeekFromEnd); + my $tagdata = $fh.read(128); + self!parse-data: $tagdata; + $fh.close; + } + else { + warn "Failed to open file." + } + } + + method !parse-data($data) { + if self!can-read-format($data) { + my $offset = $data.bytes - 128; + + $!title = self!trim-nulls: $data.subbuf($offset + 3, 30); + $!artist = self!trim-nulls: $data.subbuf($offset + 33, 30); + $!album = self!trim-nulls: $data.subbuf($offset + 63, 30); + $!year = self!trim-nulls: $data.subbuf($offset + 93, 4); + + my Int $track-flag = $data.subbuf($offset + 97 + 28, 1).Int; + $!track = $data.subbuf($offset + 97 + 29, 1).Int; + + ($!version, $!comment) = $track-flag == 0 && $!track != 0 + ?? ('1.1', self!trim-nulls: $data.subbuf($offset + 97, 28)) + !! ('1.0', self!trim-nulls: $data.subbuf($offset + 97, 30)); + + $!genre = $data.subbuf($offset + 97 + 30, 1).Int; + } + } + + method !can-read-format(Buf $data --> Bool) { + self!trim-nulls($data.subbuf(0..2)) eq 'TAG' + } + + method !trim-nulls(Buf $data --> Str) { + $data.decode('utf-8').subst(/\x[0000]+/, '') + } +} +=end code + +To call a private method of another class, the caller has to be trusted by the +callee. A trust relationship is declared with +L|/language/typesystem#trait_trusts> and the class to be trusted must +already be declared. Calling a private method of another class requires an +instance of that class and the fully qualified name (FQN) of the method. A trust +relationship also allows access to private attributes. =begin code class B {...} @@ -667,13 +728,13 @@ defined in the Employee class as though they were from the Programmer class. =begin code :preamble my $programmer = Programmer.new( salary => 100_000, - known_languages => , + known_languages => , favorite_editor => 'vim' ); say $programmer.code_to_solve('halting problem'), " will get \$ {$programmer.salary()}"; -# OUTPUT: «Solving halting problem using vim in Perl will get $100000␤» +# OUTPUT: «Solving halting problem using vim in Raku will get $100000␤» =end code =head2 Overriding inherited methods @@ -753,7 +814,7 @@ my $geek = GeekCook.new( books => 'Learning Raku', utensils => ('stainless steel pot', 'knife', 'calibrated oven'), favorite_editor => 'MacVim', - known_languages => + known_languages => ); $geek.cook('pizza'); @@ -823,11 +884,11 @@ code_to_solve, known_languages, favorite_editor =end code The first two tests each smartmatch against a class name. If the object is -of that class, or of an inheriting class, it returns true. So the object in +of that class, or of an inheriting class, it returns C. So the object in question is of class C or one that inherits from it, but not C. -The call C<$o.^name> tells us the type of C<$o>: in this case C. +The call C<$o.^name> tells us the type of C<$o>; in this case C. C<$o.raku> returns a string that can be executed as Raku code, and reproduces the original object C<$o>. While this does not work perfectly in @@ -836,10 +897,6 @@ N at some point.> -X<|^methods> -C<$o.^methods(:local)> produces a list of Ls that can be -called on C<$o>. The C<:local> named argument limits the returned methods to -those defined in the C class and excludes the inherited methods. The syntax of calling a method with C<.^> instead of a single dot means that it is actually a method call on its I, which is a class managing @@ -853,6 +910,46 @@ say $o.^parents.map({ $_.^name }).join(', '); Finally C<$o.^name> calls the C method on the metaobject, which unsurprisingly returns the class name. +Given an object C<$mp3> and the Cclass definition from the section +L, we can inquire about its +public methods with C<.^methods>: + +=begin code :skip-test +my $mp3 = MP3TagData.new(filename => 'football-head.mp3'); +say $mp3.^methods(:local); +# OUTPUT: (TWEAK filename title artist album year comment genre track version +# type Submethod+{is-hidden-from-backtrace}.new) +=end code + +X<|^methods> +C<$mp3.^methods(:local)> produces a list of Ls that can be +called on C<$mp3>. The C<:local> named argument limits the returned methods to +those defined in the C class and excludes the inherited methods; +C inherits from no class, so providing C<:local> makes no difference. + +X<|classes,find_method> +To check if a type object (or an instance object) implements a certain public +method, use the L|/routine/find_method> metamethod, which +returns the method object if it exists. Otherwise, it returns L|/type/Mu>. + +=begin code :skip-test +say $mp3.^find_method('name'); # OUTPUT: «(Mu)␤» +say $mp3.^find_method('artist'); # OUTPUT: «artist␤» +=end code + +X<|classes,private_methods> +X<|classes,find_private_methods> +Type objects can also be introspected for its private methods. However, public +and private methods don't use the same APIs, and thus different metamethods +must be used: L|/routine/private_methods> and +L|/routine/find_private_method>. + +=begin code :skip-test +say $mp3.^private_methods; # OUTPUT: «(parse-data can-read-format trim-nulls)␤» +say $mp3.^find_private_method('parse-data'); # OUTPUT: «parse-data␤» +say $mp3.^find_private_method('remove-nulls'); # OUTPUT: «(Mu)» +=end code + Introspection is very useful for debugging and for learning the language and new libraries. When a function or method returns an object you don't know about, by finding its type with C<.^name>, seeing a construction recipe diff --git a/doc/Language/community.pod6 b/doc/Language/community.pod6 index eecb56eac..abc8e6843 100644 --- a/doc/Language/community.pod6 +++ b/doc/Language/community.pod6 @@ -20,13 +20,23 @@ No, they pour new wine into new wineskins, and both are preserved.'" - Larry Wal =head2 Online communities -The C<#raku> channel was created in October 2019, and will become more active as it becomes the default channel. Eventually, connections -to the C<#perl6> will be redirected to C<#raku>, but the historical logs will remain on the C<#perl6> channel. -The L|https://raku.org/community/irc> channel on C has always had a large presence with many developers, - who are happy to provide support and answer questions, or just use it as a friendly place to hang out. -Check out this L resource for the abbreviations frequently used there. -L is also a great resource for asking questions and helping others with their Raku problems and challenges. -More resources can be found in the L. +Online interaction takes place mainly on the Internet Relay Chat, +L. + +The C<#raku> channel was created in October 2019, and will become more active as +it becomes the default channel. Eventually, connections to the C<#perl6> will be +redirected to C<#raku>, but the historical logs will remain on the C<#perl6> +channel. The L|https://raku.org/community/irc> channel on +C has a large presence with many developers, who are happy to +provide support and answer questions, or just use it as a friendly place to hang +out. Check out this +L resource for the +abbreviations frequently used there. + +L is also a great +resource for asking questions and helping others with their Raku problems and +challenges. More resources can be found in the +L. =head2 IRC bots @@ -227,13 +237,6 @@ An IRC bot for passing messages to users who are currently offline. You can also use it to see when was the last time somebody talked. =end item -=begin item -B (L) - -Very similar to SourceBaby, except points to -L indicating stress test coverage of code. -=end item - =begin item B (L) @@ -255,7 +258,7 @@ B (L) An IRC bot for testing builds of Rakudo on OpenBSD. It can be addressed by its full name ('PufferBot'). Talks only in -L<#raku-dev|https://webchat.freenode.net/?channels=#raku-dev>. +L<#raku-dev|https://web.libera.chat/?channel=#raku-dev>. =end item =begin item @@ -263,13 +266,16 @@ B (L) An IRC bot for testing builds of Rakudo on FreeBSD. It can be addressed by its full name ('BeastieBot'). Talks only in -L<#raku-dev|https://webchat.freenode.net/?channels=#raku-dev>. +L<#raku-dev|https://web.libera.chat/?channel=#raku-dev>. =end item =head2 Offline communities -Raku is also a common topic at L and L and L. +Raku is also a common topic at +L and +L and +L. If you prefer in-person meetings, these are warmly recommended! =head2 Other resources @@ -287,12 +293,12 @@ L. =head1 Raku Advent calendar The Raku community publishes every December an -L, with Raku tutorials -every day until Christmas. -Previous calendars (pre name change) are L and relevant. +L, with Raku tutorials every day until +Christmas. Previous calendars (pre name change) are +L and relevant. Organization and assignment of days is done through the different Raku channels and the -L repository. If you want to +L repository. If you want to participate, its organization starts by the end of October, so check out the channels above to keep up to date. diff --git a/doc/Language/compilation.pod6 b/doc/Language/compilation.pod6 index 6cc6dc223..96aa46a26 100644 --- a/doc/Language/compilation.pod6 +++ b/doc/Language/compilation.pod6 @@ -46,7 +46,7 @@ So it is not possible simply to have only one version of a module with a single C enables all of these possibilities, allowing for multiple versions, multiple authorities, and multiple APIs to be present, installed, and available locally. The way classes and modules can be accessed with specific attributes -is explained L. This tutorial is about how C handles these +is explained L. This tutorial is about how C handles these possibilities. =head1 Introduction diff --git a/doc/Language/concurrency.pod6 b/doc/Language/concurrency.pod6 index 638daa652..2bc80c363 100644 --- a/doc/Language/concurrency.pod6 +++ b/doc/Language/concurrency.pod6 @@ -487,8 +487,7 @@ and returns it, blocking until a new item is sent if the queue is empty: If the channel has been closed with the L then any C will cause the exception L to be thrown, and a C -will throw a L if there are no more items -on the queue. +will throw a L. The L returns all the items on the L and will block until further items are queued unless the diff --git a/doc/Language/containers.pod6 b/doc/Language/containers.pod6 index 2cfd88186..b67d68661 100644 --- a/doc/Language/containers.pod6 +++ b/doc/Language/containers.pod6 @@ -4,11 +4,11 @@ =SUBTITLE A low-level explanation of Raku containers -This section explains the levels of indirection involved in dealing with -variables and container elements. The different types of containers used in -Raku are explained and the actions applicable to them like assigning, binding -and flattening. More advanced topics like self-referential data, type -constraints and custom containers are discussed at the end. +This section explains how raw data, variables and containers relate to each +other in Raku. The different types of containers used in Raku are explained and +the actions applicable to them like assigning, binding and flattening. More +advanced topics like self-referential data, type constraints and custom +containers are discussed at the end. For a deeper discussion of the various kinds of I containers in Raku, see the overview of L; for @@ -19,7 +19,7 @@ I containers, see L. Some people like to say "everything is an object", but in fact a variable is not a user-exposed object in Raku. -When the compiler encounters a variable declaration like C, it +When the compiler encounters a variable scope declaration like C, it registers it in some internal symbol table. This internal symbol table is used to detect undeclared variables and to tie the code generation for the variable to the correct scope. diff --git a/doc/Language/control.pod6 b/doc/Language/control.pod6 index f1119cc48..c88b51817 100644 --- a/doc/Language/control.pod6 +++ b/doc/Language/control.pod6 @@ -1238,7 +1238,7 @@ while ($i < 10) { # OUTPUT: «1 is odd.␤3 is odd.␤5 is odd.␤7 is odd.␤9 is odd.␤» =end code -In a L +In a L block, C immediately exits the block for the current value: react { diff --git a/doc/Language/create-cli.pod6 b/doc/Language/create-cli.pod6 index d49bf992d..cbbcd0d6a 100644 --- a/doc/Language/create-cli.pod6 +++ b/doc/Language/create-cli.pod6 @@ -100,6 +100,19 @@ Another way to do this is to make C a C: Which would give the same output as the examples above. Whether you should use either method to achieve the desired goal is entirely up to you. +If you want to pass an indeterminate number of parameters to be dealt within +C, you can use L: + + # inside file 'hello-all.raku' + sub MAIN(*@all) { @all.map: -> $name { say "Hello, " ~ $name } } + +=begin code :lang +$ raku hello-all.raku peter paul mary +Hello, peter +Hello, paul +Hello, mary +=end code + A more complicated example using a single positional and multiple named parameters, and also showing that C clauses can also be applied to C
arguments: @@ -171,6 +184,76 @@ Usage: --verbose required verbosity =end code +From release 2021.03, values to single named arguments can be separated by +spaces too. Consider a C program with the following source: + + subset name of Any where Str|True; + subset port of Str; + multi MAIN( + $file, + name :$profile, #= Write profile information to a file + port :$debug-port, #= Listen for debugger connections on the specified port + Bool :v($verbose), #= Display verbose output + + ) {} + multi MAIN("--process-files", *@images) {} + +This program generates the following usage message: + +=begin code :lang +Usage: + demo [--profile[=name]] [--debug-port=] [-v] + demo --process-files [ ...] + + --profile[=name] Write profile information to a file + --debug-port= Listen for debugger connections on the specified port + -v Display verbose output +=end code + +The following are valid ways to call C: + +=for code :lang +demo --profile ~/foo +demo --profile=/tmp/bar ~/foo +demo --debug-port 4242 ~/foo +demo --debug-port=4242 ~/foo +demo -v ~/foo +demo --process-files *.jpg + +These, however, are not valid + +=for code :lang +demo --profile /tmp/bar ~/foo +demo --debug-port ~/foo + +The first is invalid because C and C<~/foo> are both parsed as +positional arguments, which means C was called with too many +positional arguments. The second is invalid because C<~/foo> is parsed +as an argument to C<--debug-port>, and thus C lacks the required +positional argument. + +Here's how it works; with Raku distinguishing between three types of options: + +=item Boolean options (like C<-v>), which I take an argument; they + are ether present or absent. +=item Options with a mandatory argument (like C<--debug-port>), which + always take an argument. If you give them an argument with C<=>, + they will use that; if not, they'll take the following argument. +=item Options with an optional argument (like C<--profile>), which are + valid both with and without an argument. You can I give these + arguments an option with the C<=> syntax; if there is a space after + the option, that means it was called without an argument. + +And here's the signature that produces each type of argument: + +=item Boolean options: A L|/type/Bool> type constraint. += Options with a mandatory argument: A type that does not L|/routine/ACCEPTS> a C. +=item Options with an optional argument: A type that C<.ACCEPTS> a + C (because passing an option without an argument is equivalent + to passing C) + + As any other subroutine, C
can define L for its named parameters. diff --git a/doc/Language/exceptions.pod6 b/doc/Language/exceptions.pod6 index 5e6497efb..ae42e85d1 100644 --- a/doc/Language/exceptions.pod6 +++ b/doc/Language/exceptions.pod6 @@ -45,6 +45,7 @@ Note how the object has provided the backtrace with information about what went wrong. A user of the code can now more easily find and correct the problem. +X<|CATCH> =head1 Catching exceptions It's possible to handle exceptional circumstances by supplying a C block: @@ -63,12 +64,14 @@ which is what C<$*ERR.say> does, getting displayed on whatever constitutes the standard error device in that moment, which will probably be the console by default. -A X|CATCH> block uses smartmatching similar to how C +A C block uses smartmatching similar to how C smartmatches on options, thus it's possible to catch and handle various -categories of exceptions inside a C block. +categories of exceptions inside a C block. And it does so because, +within the block, C<$_> is set to the exception that has been raised. To handle all exceptions, use a C statement. This example prints out -almost the same information as the normal backtrace printer. +almost the same information as the normal backtrace printer; the I +methods apply to C<$_>, which holds the C within the C block. CATCH { default { @@ -125,7 +128,7 @@ X<|try blocks> =head1 C blocks A C block is a normal block which implicitly turns on the -L pragma|/language/pragmas#index-entry-fatal-fatal> and +L pragma|/language/pragmas#fatal> and includes an implicit C block that drops the exception, which means you can use it to contain them. Caught exceptions are stored inside the C<$!> variable, which holds a value of type C. diff --git a/doc/Language/faq.pod6 b/doc/Language/faq.pod6 index d722b657b..1154163b0 100644 --- a/doc/Language/faq.pod6 +++ b/doc/Language/faq.pod6 @@ -2,7 +2,7 @@ =TITLE FAQ -=SUBTITLE Frequently asked questions about Raku +=SUBTITLE Frequently asked questions about Raku™ =head1 General @@ -113,7 +113,7 @@ Anything published before December, 2015 likely describes a pre-release version of Raku. You can always -L +L or L to find previous conversations and discussions. @@ -123,7 +123,7 @@ X<|Books> Here are some available books, in alphabetical order: -=item L, by brian d foy +=item L, by brian d foy =item L, by JJ Merelo @@ -135,7 +135,7 @@ by Ken Youens-Clark =item L, by Andrew Shitov -=item L, +=item L, by Moritz Lenz =item L, by Andrew Shitov @@ -250,8 +250,8 @@ X<|Core standard library (FAQ)> X<|Rakudo Star distribution and compiler-only release (FAQ)> =head2 Does Rakudo have a core standard library? -L does come -with L. +L does come +with L. Rakudo compiler-only release includes L. @@ -301,7 +301,7 @@ classes into the same compilation unit. =head1 Common operations -=head2 String: How can I parse and get a L from a L +=head2 String: How can I parse and get a L from a L? Use the L<+ prefix|/language/operators#prefix_+>: @@ -314,7 +314,7 @@ This example of L can numify any string yo L routine converts it to L. L routine converts one unicode codepoint. -=head2 String: How can I check if a string contains a substring and if so, how can I get indices of matches +=head2 String: How can I check if a string contains a substring and if so, how can I get indices of matches? Use L<.contains|/type/Str#method_contains> or L<.indices|/type/Str#method_indices>: @@ -323,13 +323,13 @@ Use L<.contains|/type/Str#method_contains> or L<.indices|/type/Str#method_indice "az and az and az again".indices("az"); # OUTPUT: «(0 7 14)␤» =end code -=head2 String: How can I get the hexadecimal representation of a string +=head2 String: How can I get the hexadecimal representation of a string? To get a hexadecimal list of each byte of a string (i.e. hex encoder), first convert the string to a L with L<.encode|/routine/encode>. =begin code -say "I ❤ 🦋".encode>>.base(16); OUTPUT: «(49 20 E2 9D A4 20 F0 9F A6 8B)␤» +say "I ❤ 🦋".encode>>.base(16); # OUTPUT: «(49 20 E2 9D A4 20 F0 9F A6 8B)␤» =end code Note that L<.gist|/routine/gist> or L<.raku|/routine/raku> methods can be useful for variable introspection: @@ -339,9 +339,9 @@ say "I ❤ 🦋".encode.raku; # OUTPUT: «utf8.new(73,32,226,157,164,32,240,159 say "I ❤ 🦋".encode.gist; # OUTPUT: «utf8:0x<49 20 E2 9D A4 20 F0 9F A6 8B>␤» =end code -=head2 String: How can I remove from a string some characters by index +=head2 String: How can I remove from a string some characters by index? -Use L<.comb|/routine/comb> to transform it to a L, then the L<(-) infix|/language/operators#infix_(-),_infix_\\> to remove the unwanted indices: +Use L<.comb|/routine/comb> to transform it to a L, then the L<(-) infix|/language/operators#infix_-> to remove the unwanted indices: =begin code say '0123456789'.comb[(^* (-) (1..3, 8).flat).keys.sort].join; # OUTPUT: «045679␤» @@ -361,7 +361,7 @@ multi postcircumfix:<[- ]> (Str:D $str is copy, +@indices) { say '0123456789'[- 1..3, 8 ]; # OUTPUT: «045679␤» =end code -=head2 String: How can I split a string in equal parts +=head2 String: How can I split a string in equal parts? L<.comb|/routine/comb> is accepting an optional L: @@ -383,7 +383,7 @@ available since the Rakudo 2019.11 release) that typically returns an object's representation in L-able code. If you're using the L implementation, you can use -the L«rakudo-specific C
routine|/programs/01-debugging#Dumper_function_dd» +the L«rakudo-specific C
routine|/programs/01-debugging#Dumper_function_(dd)» for dumping, whose output is similar to L, but with more information. @@ -456,7 +456,7 @@ L«C, C, and C|/syntax/with orwith without» statements, L«C|/routine/$SOLIDUS$SOLIDUS», L, L, and L operators, as well as -L. +L. =head2 What is C? @@ -748,7 +748,7 @@ about the object deemed unimportant to understanding the essence of the object. Or phrased differently, C<$obj.Str> gives a string representation, C<$obj.gist> provides a short summary of that object suitable for -fast recognition by a human, and C<$obj.perl> (C<$obj.raku>) gives a Raku-ish +fast recognition by a human, and C<$obj.raku> gives a Raku-ish representation from which the object could be re-created. For example, when the C method is invoked on a type object, also known @@ -764,8 +764,8 @@ say $x; # OUTPUT: «(Date)␤» =end code If you'd like to show a debugging version of an object, it is probably better -to use the L«rakudo-specific C
routine|/programs/01-debugging#Dumper_function_dd». -It essentially does a C<$obj.perl> (C<$obj.raku>) and shows that on STDERR rather than +to use the L«rakudo-specific C
routine|/programs/01-debugging#Dumper_function_(dd)». +It essentially does a C<$obj.raku> and shows that on STDERR rather than STDOUT, so it won't interfere with any "normal" output of your program. In short, C is optimized for casual human interpretation, C
is optimized @@ -877,7 +877,7 @@ X<|Rakudo Star release cycle (FAQ)> =head2 When will the next version of Rakudo Star be released? A Rakudo Star release is typically produced quarterly, with release -announcements L. +announcements L. =head1 Metaquestions and advocacy @@ -938,15 +938,15 @@ seen as an object). Inheritance. Subtyping. Code-reuse. =item Introspection into objects and metaobjects (turtles all the way down). =item MetaObject Protocol allowing for metaprogramming without needing to -generate / parse code. +generate or parse code. =item Subroutine and method signatures for easy unpacking of positional and named parameters. -=item Multi dispatch for identically named subroutines/methods with different +=item Multi-dispatch for identically named subroutines/methods with different signatures, based on arity, types and optional additional code. -=item Compile time error reporting on unknown subroutines / impossible dispatch. +=item Compile time error reporting on unknown subroutines or impossible dispatch. =item Optional gradual type-checking at no additional runtime cost. With optional type annotations. @@ -979,19 +979,19 @@ interactive, event driven applications. This means, for example, lazy lists, and even infinite lazy lists, like the Fibonacci sequence, or all prime numbers. -=item Native data types for faster, closer to the metal, processing. +=item Native data types for faster, closer-to-the-metal, processing. -=item Interfacing to external libraries in C / C++ is fairly easy with +=item Interfacing to external libraries in C and C++ is fairly easy with L. -=item Interfacing with Perl (CPAN) / Python modules is fairly easy with +=item Interfacing with Perl (CPAN) and Python modules is fairly easy with L and L =item Can have multiple versions of a module installed and loaded simultaneously. -=item System administration simplified due to simpler update/upgrade policies. +=item System administration simplified due to simpler update and upgrade policies. =item Simple numeric computation without precision loss because of Ls (rational numbers). @@ -1005,7 +1005,7 @@ traits and data-types, which modify the parser for you). =item Large selection of data-types, plus the possibility to create your own types. -=item Multi-dimensional shaped and/or native arrays with proper bounds checking. +=item Multi-dimensional shaped or native arrays with proper bounds checking. =item Execute code at any time during parsing of a grammar, or when a certain match occurred. @@ -1016,14 +1016,14 @@ subroutine. =item Automatic generation of hyper-operators on any operator (system or custom added). -=item Runs on a variety of back-ends. Currently MoarVM & JVM, JavaScript in +=item Runs on a variety of back-ends. Currently MoarVM and JVM, JavaScript in development, more may follow. =item Runtime optimization of hot code paths during execution (JIT). =item Runs on small (e.g., Raspberry Pi) and large multi-processor hardware. -=item Garbage collection based: no timely destruction, so no ref-counting +=item Garbage collection based: no timely destruction, so no reference-counting necessary. Use phasers for timely actions. =item Methods can be mixed into any instantiated object at runtime; e.g., to @@ -1061,7 +1061,7 @@ The following crude benchmarks, with all the usual caveats about such things, show that Raku can be faster than Perl for similar tasks if the big weaponry is included, that is, if Raku features are used to its full extent; at the same time, Perl can be faster if only the bare bones are included. Similar -situation can be observed when comparing Raku to other languages. +situations can be observed when comparing Raku to other languages. Try it on your system. You may be pleasantly surprised! @@ -1069,8 +1069,6 @@ Examples: =begin code :solo # Raku version -use v6.c; - class Foo { has $.i is rw }; for 1..1_000_000 -> $i { diff --git a/doc/Language/functions.pod6 b/doc/Language/functions.pod6 index 2467bf587..d4045b382 100644 --- a/doc/Language/functions.pod6 +++ b/doc/Language/functions.pod6 @@ -270,8 +270,9 @@ signatures. When the routine is called by name, the runtime environment determines the proper I and invokes it. Each candidate is declared with the C keyword. Dispatch happens -depending on the number (L), type -and name of arguments. Consider the following example: +depending on the parameter L (number), type and +name; and under some circumstances the order of the multi +declarations. Consider the following example: =begin code # version 1 @@ -345,7 +346,9 @@ for the L class. say as-json( 10.3 ); # OUTPUT: «10.3␤» say as-json( [ True, 10.3, False, 24 ] ); # OUTPUT: «[true, 10.3, false, 24]␤» - +For some signature differences (notably when using a where clause or a subset) +the order of definition of the multi methods or subs is used, evaluating +each possibility in turn. See L below for examples. C without any specific routine type always defaults to a C, but you can use it on methods as well. The candidates are all the multi methods of the @@ -426,7 +429,7 @@ arguments given: # attempts to notify someone -- False if unsuccessful proto notify(Str $user, Str $msg) { my \hour = DateTime.now.hour; - if hour > 8 or hour < 22 { + if 8 < hour < 22 { return {*}; } else { # we can't notify someone when they might be sleeping @@ -509,7 +512,7 @@ $x.handle('Claire', 'John'); # with more than one value # after value is 「Claire is looking askance at John」 -=head2 X +=head3 X The C keyword preceding C or C indicates that it will be the only function with that name that inhabits a given namespace. @@ -540,6 +543,74 @@ at /tmp/only-redeclaration.p6:3 Anonymous sub cannot be declared C. C will throw an error of type, surprisingly, C. + +=head3 multi resolution by order of definition + +When the breakdown by parameter type is not enough to find an unambiguous +match, there are some different tie breakers that may be evaluated in order +of declaration of the methods or subs: these include where clauses and +subsets, named parameters, and signature unpacks. + +In this code example, two multi subs are distinguished only by where clauses +where there's one ambiguous case that might pass either of them, the value 4. +In this case, which ever multi sub is defined first wins: + +=begin code +{ + multi sub check_range ( Int $n where {$_ > 3} ) { + return "over 3"; + }; + multi sub check_range ( Int $n where {$_ < 5} ) { + return "under 5"; + }; + say check_range(4); # OUTPUT: over 3 +} +{ + multi sub check_range ( Int $n where {$_ < 5} ) { + return "under 5"; + }; + multi sub check_range ( Int $n where {$_ > 3} ) { + return "over 3"; + }; + say check_range(4); # OUTPUT: under 5 +} +=end code + +In the following example, three subsets are used to restrict strings to +certain allowed values, where there are overlaps between all three: + +=begin code +subset Monster of Str where { $_ eq any( ) }; +subset Hero of Str where { $_ eq any( ) }; +subset Knockoff of Str where { $_ eq any( ) }; + +{ + multi sub speak (Monster $name) { + say "The monster, $name roars!"; + } + multi sub speak (Hero $name) { + say "The hero, $name shouts!"; + } + multi sub speak (Knockoff $name) { + say "The knockoff, $name, slinks away..."; + } + speak('godzilla'); # OUTPUT: The monster, godzilla roars! + speak('gammera'); # OUTPUT: The monster, gammera roars! + speak('inframan'); # OUTPUT: The hero, inframan shouts! +} +=end code + +Note that here 'godzilla' is treated as Monster, not as Hero, because the +Monster multi comes first; and neither 'gammera' or 'inframan' are treated +as Knockoff, because that multi comes last. + +It should be noted that the order of definition is the order in which Raku +sees them, which might not be easy to discern if, for example, the multi +subs were imported from different modules. As the organization of a code +base becomes more complex, object classes may scale better than using +subsets as types, as in this example. + + =head1 Conventions and idioms While the dispatch system described above provides a lot of flexibility, @@ -563,7 +634,8 @@ two nuances: =item Ls created with a L|/routine/,> at the top level only count as one L. -This can be achieved by using a slurpy with a C<+> or C<+@> instead of C<**>: +This can be achieved by using a slurpy with a +L|/type/Signature#index-entry-trait__is_raw> or C<+@> instead of C<**@>: sub grab(+@a) { "grab $_".say for @a } @@ -605,6 +677,9 @@ grab($b); # OUTPUT: «grab 1␤grab 2␤» my \c = (1, 2); # Sigilless variables always bind, even with '=' grab(c); # OUTPUT: «grab 1␤grab 2␤» +See the L«documentation of the C subroutine|/type/List#routine_list» for +more examples of how to use a routine that adheres to the single argument rule. + =head1 Functions are first-class objects Functions and other code objects can be passed around as values, just like any @@ -1086,18 +1161,18 @@ a 1; # OUTPUT: «Int 1␤Any 2␤» X<|dispatch,samewith> -C calls current candidate again with arguments provided by users -and returns the return value of the new instance of current candidate. +C calls the multi again with arguments provided at the call site +and returns the value provided by the call. This can be used for self-recursion. =begin code -proto a(|) {*} +proto factorial(|) {*} -multi a(Int $x) { - return 1 unless $x > 1; - return $x * samewith($x-1); +multi factorial(Int $x where * ≤ 1) { 1 } +multi factorial(Int $x) { + $x * samewith($x-1); } -say (a 10); # OUTPUT: «36288000␤» +say (factorial 10); # OUTPUT: «36288000␤» =end code X<|dispatch,nextcallee> diff --git a/doc/Language/glossary.pod6 b/doc/Language/glossary.pod6 index 0cf8d866b..6e6c53066 100644 --- a/doc/Language/glossary.pod6 +++ b/doc/Language/glossary.pod6 @@ -2,7 +2,7 @@ =TITLE Glossary -=SUBTITLE Glossary of Raku terminology +=SUBTITLE Glossary of Raku™ terminology X<|Abstract Class> =head1 Abstract class @@ -367,7 +367,7 @@ X<|iffy> =head1 iffy Often used as a Boolean value. See L. Made via -the L keyword|/language/modules#index-entry-use>. +the L keyword|/language/modules#use>. X<|import> =head1 import @@ -420,7 +420,7 @@ X<|IRC> =head1 IRC Internet Relay Chat. Raku developers and users usually hang out on -the C<#raku> channel of C. This channel is also +the C<#raku> channel of C. This channel is also populated by a host of friendly bots that allow you to interact with Raku and its codebase, as well as send delayed messages and other goodies. Check the full list in @@ -655,7 +655,7 @@ expressions such as C<$lhs = "this would be the right-hand side">. Since the left hand side of these expressions modify their value, when something behaves as a LHS it means that it can be read and written to. -X<|Value> +X<|lvalue> =head1 lvalue An I, or a I, is anything that can appear on the @@ -730,11 +730,16 @@ X<|Multi-Dispatch> X<|MMD> =head1 Multi-dispatch -The process of picking a candidate for calling of a set -of L or L that -come by the same name but with different arguments. The most narrow -candidate wins. In case of an ambiguity, a routine with C trait -will be chosen if one exists, otherwise an exception is thrown. +The mechanism used to invoke different routines (L or +L) of the same name, selecting the correct one based on the +L prototype and the arguments it was called with. + +The selection process is primarily based on types and number of arguments +(L), where the narrowest, most specific candidate wins, +typically without regard to the order of declaration. The C +trait may be used as a tie breaker in this first phase. There is also a +secondary phase where some different tie breakers may be evaluated in order +of declaration of the methods or subs. X<|multi-method> =head1 multi-method diff --git a/doc/Language/grammar_tutorial.pod6 b/doc/Language/grammar_tutorial.pod6 index 09e1f0f93..2bbba010f 100644 --- a/doc/Language/grammar_tutorial.pod6 +++ b/doc/Language/grammar_tutorial.pod6 @@ -277,7 +277,7 @@ grammar Quoted-Other is Letters is Quote-Other { my $quoted = q{"enhanced"}; my $parsed = Quoted-Quotes.parse($quoted); say $parsed; -#OUTPUT: +# OUTPUT: #「"enhanced"」 # quote => 「"」 # letters => 「enhanced」 @@ -286,7 +286,7 @@ say $parsed; $quoted = "|barred|"; $parsed = Quoted-Other.parse($quoted); say $parsed; -#OUTPUT: +# OUTPUT: #|barred|」 #quote => 「|」 #letters => 「barred」 diff --git a/doc/Language/grammars.pod6 b/doc/Language/grammars.pod6 index d4dd2e360..b9cc0c0d7 100644 --- a/doc/Language/grammars.pod6 +++ b/doc/Language/grammars.pod6 @@ -261,14 +261,14 @@ the C<:sym> adverb for that particular regex: grammar Foo { token TOP { + } proto token letter {*} - token letter:sym

{ } - token letter:sym { } - token letter:sym { } - token letter:sym { } + token letter:sym { } + token letter:sym { } + token letter:sym { } + token letter:sym { } token letter:sym<*> { . } - }.parse("I ♥ Perl", actions => class { + }.parse("I ♥ Raku", actions => class { method TOP($/) { make $.grep(*.).join } - }).made.say; # OUTPUT: «Perl␤» + }).made.say; # OUTPUT: «Raku␤» This comes in handy when you're already differentiating the proto regexes with the strings you're going to match, as using C«» token prevents repetition @@ -607,7 +607,7 @@ my $actions = KeyValuePairsActions; my @res = KeyValuePairs.parse(q:to/EOI/, :$actions).made; second=b hits=42 -perl=6 +raku=d EOI for @res -> $p { @@ -620,7 +620,7 @@ This produces the following output: =begin code :lang Key: second Value: b Key: hits Value: 42 -Key: perl Value: 6 +Key: raku Value: d =end code Rule C, which parsed a pair separated by an equals sign, aliases the two @@ -705,7 +705,7 @@ my $actions = ConfigurationSetsActions; my $sets = ConfigurationSets.parse(q:to/EOI/, :$actions).made; second=b # Just a thing hits=42 -perl=6 +raku=d third=c # New one hits=33 @@ -719,7 +719,7 @@ for @$sets -> $set { Which will print =for code :lang -Element→ second b hits 42 perl 6 +Element→ second b hits 42 raku d Element→ third c hits 33 diff --git a/doc/Language/hashmap.pod6 b/doc/Language/hashmap.pod6 index a13dc3891..f84951212 100644 --- a/doc/Language/hashmap.pod6 +++ b/doc/Language/hashmap.pod6 @@ -147,7 +147,7 @@ the string values into integers for the sort. There are several ways that can be method may present the least "line noise" to novices or non-Raku viewers: =for code :preamble - say %csv.keys.map(+*).sort.raku; # OUTPUT: «(2, 10).Seq␤» +say %csv.keys.map(+*).sort.raku; # OUTPUT: «(2, 10).Seq␤» In a hash constructor list the C syntax doesn't have to be used, or it may be intermixed with ordinary list values as long as the list has an even number of elements in total as well diff --git a/doc/Language/haskell-to-p6.pod6 b/doc/Language/haskell-to-p6.pod6 index abbecf899..a8f9794fb 100644 --- a/doc/Language/haskell-to-p6.pod6 +++ b/doc/Language/haskell-to-p6.pod6 @@ -444,7 +444,7 @@ Fold in Haskell is called Reduce in Raku. =begin code my @numbers = {...}; reduce { $^a + $^b }, 0, |@numbers; - @numbers.reduce({$^a + $^b}, with => 0) + @numbers.reduce: {$^a + $^b} =end code However, in Raku, if you want to use an infix operator (+ - / % etc) @@ -452,8 +452,8 @@ there is a nice little helper called the Reduction metaoperator. =begin code my @numbers = {...}; - [+] @numbers # This is the same - [+] 0, @numbers # as this + [+] @numbers # This is the same + [+] 0, |@numbers # as this =end code It inserts the operator in between all values in the list and produces a result, just like Fold. @@ -484,6 +484,31 @@ associativity attached to the operator/subroutine. say (1..5).reduce: &[<]; # True =end code +=head2 C + +The C function in Haskell runs over a list returning all elements +until a condition is met: + +=for code :lang +fibs = 0 : 1 : zipWith (+) fibs (tail fibs) +takeWhile (<20) fibs -- Returns [0,1,1,2,3,5,8,13] + +There's no single equivalent function in Raku; several alternatives have +been proposed in the +L. +This would be one of the alternatives: + +=for code +[1, 2, 3, 40, 50, 60, 7, 8, 9] ...^ !(* < 10) + +Although it's not a single function, it's essentially a specific way of using +the L using the caret for +excluding the last term, and using a condition for ending the sequence. This +specific example would be equivalent to + +=for code :lang +takeWhile (<10) [1, 2, 3, 40, 50, 60, 7, 8, 9] + =head2 Map TODO diff --git a/doc/Language/intro.pod6 b/doc/Language/intro.pod6 index 808f36d29..a5d40068d 100644 --- a/doc/Language/intro.pod6 +++ b/doc/Language/intro.pod6 @@ -2,7 +2,7 @@ =TITLE Brief introduction -=SUBTITLE Using Raku official documentation +=SUBTITLE Using Raku™ official documentation Documenting a large language like Raku has to balance several contradictory goals, such as being brief whilst being comprehensive, catering to professional diff --git a/doc/Language/io-guide.pod6 b/doc/Language/io-guide.pod6 index eceaacb42..a7f9eb680 100644 --- a/doc/Language/io-guide.pod6 +++ b/doc/Language/io-guide.pod6 @@ -76,10 +76,10 @@ files that are difficult to store entirely in memory all at the same time, these two routines are for you. =for code -"my-file.txt".IO.spurt: "I ♥ Perl!"; +"my-file.txt".IO.spurt: "I ♥ Raku!"; The code above creates a file named C in the current directory -and then writes text C into it. If Raku is your first language, +and then writes text C into it. If Raku is your first language, celebrate your accomplishment! Try to open the file you created with a text editor to verify what you wrote with your program. If you already know some other language, you may be wondering if this guide missed anything like @@ -137,8 +137,8 @@ We've seen in previous sections that writing stuff to files is a single-line of code in Raku. Reading from them, is similarly easy: =for code -say 'my-file.txt'.IO.slurp; # OUTPUT: «I ♥ Perl!␤» -say 'my-file.txt'.IO.slurp: :bin; # OUTPUT: «Buf[uint8]:0x<49 20 e2 99 a5 20 50 65 72 6c 21>␤» +say 'my-file.txt'.IO.slurp; # OUTPUT: «I ♥ Raku!␤» +say 'my-file.txt'.IO.slurp: :bin; # OUTPUT: «Buf[uint8]:0x<49 20 E2 99 A5 20 52 61 6B 75 21>␤» The L«C<.slurp>|/routine/slurp» method reads entire contents of the file and returns them as a single L object, or as a L @@ -153,13 +153,13 @@ L«C<.lines>|/type/IO::Path#method_lines» that lazily read the file in smaller chunks and return L objects that (by default) don't keep already-consumed values around. -Here's an example that finds lines in a text file that mention Perl and prints +Here's an example that finds lines in a text file that mention Raku and prints them out. Despite the file itself being too large to fit into available L, the program will not have any issues running, as the contents are processed in small chunks: =for code -.say for '500-PetaByte-File.txt'.IO.lines.grep: *.contains: 'Perl'; +.say for '500-PetaByte-File.txt'.IO.lines.grep: *.contains: 'Raku'; Here's another example that prints the first 100 words from a file, without loading it entirely: @@ -188,7 +188,7 @@ type; this gives you a finer control over the process. =begin code given 'some-file.txt'.IO.open { - say .readchars: 8; # OUTPUT: «I ♥ Perl␤» + say .readchars: 8; # OUTPUT: «I ♥ Raku␤» .seek: 1, SeekFromCurrent; say .readchars: 15; # OUTPUT: «I ♥ Programming␤» .close @@ -199,10 +199,10 @@ The L gives you L«.read|/type/IO::Handle#method_read», L«.readchars|/type/IO::Handle#method_readchars», L«.get|/type/IO::Handle#routine_get», -L«.getc|/type/IO::Handle#method_getc», +L«.getc|/type/IO::Handle#routine_getc», L«.words|/type/IO::Handle#routine_words», L«.lines|/type/IO::Handle#routine_lines», -L«.slurp|/type/IO::Handle#routine_slurp», +L«.slurp|/type/IO::Handle#method_slurp», L«.comb|/type/IO::Handle#method_comb», L«.split|/type/IO::Handle#method_split», and L«.Supply|/type/IO::Handle#method_Supply» diff --git a/doc/Language/iterating.pod6 b/doc/Language/iterating.pod6 index 6a170c00a..e7f649325 100644 --- a/doc/Language/iterating.pod6 +++ b/doc/Language/iterating.pod6 @@ -34,7 +34,7 @@ my @longer-chain = DNA.new('ACGTACGTT'); say @longer-chain.raku; # OUTPUT: «[("A", "C", "G"), ("T", "A", "C"), ("G", "T", "T")]␤» -say @longer-chain».join("").join("|"); #OUTPUT: «ACG|TAC|GTT␤» +say @longer-chain».join("").join("|"); # OUTPUT: «ACG|TAC|GTT␤» =end code In this example, which is an extension of the L that diff --git a/doc/Language/js-nutshell.pod6 b/doc/Language/js-nutshell.pod6 index ecb96e872..a6a5d5460 100644 --- a/doc/Language/js-nutshell.pod6 +++ b/doc/Language/js-nutshell.pod6 @@ -86,14 +86,14 @@ than the outer scope. This is what the equivalent variable declarations look like in Raku: =for code -my $foo = 1; # Lexically scoped -our $foo = 1; # Package scoped +my $foo = 1; # Lexically scoped +our $foo = 1; # Package scoped =for code -my constant foo = 1; # Lexically scoped; constant +my constant foo = 1; # Lexically scoped; constant =for code - constant foo = 1; # Package scoped; constant +constant foo = 1; # Package scoped; constant =for code my $*foo = 1; # Dynamic variable; lexically scoped @@ -102,7 +102,7 @@ our $*foo = 1; # Dynamic variable; package scoped GLOBAL::<$foo> := 1; # Globally scoped Use C where you'd use C, C for variables you'd define in the -outermost scope needed, and C where you'd uses C. +outermost scope needed, and C where you'd use C. You may have noticed the C<$> and C<$*> symbols placed before variable names. These are known as sigils and twigils respectively, and define what container @@ -110,9 +110,9 @@ the variable has. Refer to the documentation on L for more information on sigils, twigils, and containers. -Variables in Node.js can override others from outer scopes with the same name -(though linters will usually complain about it depending on how they're -configured): +Variables in Node.js can have the same name as others from outer scopes without +conflicting (though linters will usually complain about it depending on how +they're configured): =begin code :lang let foo = 1; @@ -340,6 +340,21 @@ say 1 +^ 1; # OUTPUT: 0 say +^1; # OUTPUT: -2 =end code +=head3 Checking for definedness + +Javascript includes a nullish coalescing operator, C, which progresses +only if null or undefined: + +=for code :lang +undefined || null || 0 || 1 ; // => 1 +undefined ?? null ?? 0 ?? 1 ; // => 0 + +This is very similar to Raku L|/routine/$SOLIDUS$SOLIDUS> operator: + +=for code +Any || Nil || 0 || 1 ; # => 1 +Any // Nil // 0 // 1 ; # => 0 + =head3 Custom operators and operator overloading Node.js does not allow operator overloading without having to use a Makefile or diff --git a/doc/Language/list.pod6 b/doc/Language/list.pod6 index e30fc72cb..efb43c2ca 100644 --- a/doc/Language/list.pod6 +++ b/doc/Language/list.pod6 @@ -57,7 +57,7 @@ be: # OUTPUT: «foo␤» Because the semicolon doubles as a -L +L it will end a literal list when used at the top level, instead creating a statement list. If you want to create a statement list inside parenthesis, use a sigil before the parenthesis: @@ -139,7 +139,7 @@ for @list -> @element { say $sub-element; } } -# OUTPUT +# OUTPUT: #1 2 3 → List #1 #2 @@ -236,7 +236,7 @@ variable may B be bound to a C, and trying to do so will yield an error. my @s := .Seq; CATCH { default { say .^name, ' ', .Str } } - # OUTPUT «X::TypeCheck::Binding Type check failed in binding; expected Positional but got Seq ($(("a", "b","c").Seq))␤» + # OUTPUT: «X::TypeCheck::Binding Type check failed in binding; expected Positional but got Seq ($(("a", "b","c").Seq))␤» This is because the C does not keep values around after you have used them. This is useful behavior if you have a very long sequence, as @@ -354,7 +354,7 @@ needed. =for code my $l := 1, 2, 4, 8 ... Inf; say $l[0..16]; -#OUTPUT: «(1 2 4 8 16 32 64 128 256 512 1024 2048 4096 8192 16384 32768 65536)␤» +# OUTPUT: «(1 2 4 8 16 32 64 128 256 512 1024 2048 4096 8192 16384 32768 65536)␤» You can easily assign lazy objects to other objects, conserving their laziness: @@ -500,7 +500,7 @@ structure in the result: Slices can be taken also across several dimensions using I, which are lists of slices separated by semicolons: my @sliceable = [[ ^10 ], ['a'..'h'], ['Ⅰ'..'Ⅺ']]; - say @sliceable[ ^3; 4..6 ]; #OUTPUT: «(4 5 6 e f g Ⅴ Ⅵ Ⅶ)␤» + say @sliceable[ ^3; 4..6 ]; # OUTPUT: «(4 5 6 e f g Ⅴ Ⅵ Ⅶ)␤» which is selecting the 4 to 6th element from the three first dimensions (C<^3>). @@ -526,11 +526,12 @@ normal behavior of the L<..|/type/Range> operator. The subscript operator L<[]|/language/subscripts#Slices> evaluates the WhateverCode providing the list's C<.elems> as an argument and uses the resulting range to slice: - =for code :preamble + =begin code :preamble say @a[0..*-1]; # OUTPUT: «(1 2 3 4 5)␤» say @a[0..^*-1]; # OUTPUT: «(1 2 3 4)␤» # Produces 0..^2.5 as the slice range say @a[0..^*/2]; # OUTPUT: «(1 2 3)␤» + =end code Notice that C<0..^*> and C<0..^*+0> behave consistently in subscripts despite one being an infinite range and the other a WhateverCode producing ranges, @@ -551,7 +552,7 @@ Which brings us to Arrays... =head1 Arrays -Arrays differ from lists in three major ways: Their elements may be typed, +Ls|/type/Array> differ from lists in three major ways: Their elements may be typed, they automatically itemize their elements, and they are mutable. Otherwise they are Lists and are accepted wherever lists are. diff --git a/doc/Language/math.pod6 b/doc/Language/math.pod6 index b316a5ac9..d267b89d8 100644 --- a/doc/Language/math.pod6 +++ b/doc/Language/math.pod6 @@ -7,7 +7,7 @@ =head1 Sets Raku includes the L data type, as well as support for -L. +L. L are not only native operations, they use their I symbols, ∩ and ∪. For instance, this code would check the fundamental laws of the arithmetic of sets diff --git a/doc/Language/modules-core.pod6 b/doc/Language/modules-core.pod6 index ea7ea1bab..7b8c07c37 100644 --- a/doc/Language/modules-core.pod6 +++ b/doc/Language/modules-core.pod6 @@ -4,8 +4,10 @@ =SUBTITLE Core modules that may be useful to module authors -The Rakudo implementation has a few modules included you may want to use. The -following is a list of them, along with links to their source code. +The Rakudo implementation has a few modules included you may want to use; please +note that the implementation is not part of the Raku specification and thus +might be subject to change without prior notice. The following is a list of +them, along with links to their source code. =head2 C modules and roles X<|CompUnit (Rakudo classes)> @@ -14,7 +16,7 @@ These modules are mostly used by distribution build tools, and are not intended to be used (at least until version 6.c) by the final user. =item L«C|https://github.com/rakudo/rakudo/blob/master/lib/CompUnit/Repository/Staging.rakumod». -=item L|https://github.com/rakudo/rakudo/blob/master/src/core/CompUnit/RepositoryRegistry.rakumod>. +=item L|https://github.com/rakudo/rakudo/blob/master/src/core.c/CompUnit/RepositoryRegistry.pm6>. =head2 C modules @@ -26,8 +28,9 @@ to be used (at least until version 6.c) by the final user. =head2 Other modules =item L«C|https://github.com/rakudo/rakudo/blob/master/lib/Pod/To/Text.rakumod» Used by several external modules -=item L«C|https://github.com/rakudo/rakudo/blob/master/lib/Test.rakumod» Test routines (L) +=item L«C|/type/Test» Test routines (see L) =item L«C|https://github.com/rakudo/rakudo/blob/master/lib/experimental.rakumod» +(L) =item L«C|https://github.com/rakudo/rakudo/blob/master/lib/newline.rakumod» =end pod diff --git a/doc/Language/modules.pod6 b/doc/Language/modules.pod6 index 143cdbc27..ce2567421 100644 --- a/doc/Language/modules.pod6 +++ b/doc/Language/modules.pod6 @@ -6,17 +6,16 @@ =head1 Creating and using modules -A module is usually a source file or set of source files that expose -Raku constructs N which are usually files -but could come from anywhere as long as there is a I that can provide it. See -L.>. +A module is usually a source file or set of source files that expose Raku +constructs N which are usually +files but could come from anywhere as long as there is a I +that can provide it. See L.>. Modules are typically packages (L, L, L), L, and sometimes -L. In Raku I can also refer to a type -of package declared with the C keyword (see L. In Raku I can also refer to a type of +package declared with the C keyword (see L and the examples below) but here we mostly mean "module" as a set of source files in a namespace. @@ -284,7 +283,7 @@ tags: C, C and C. B: there currently is no way for the user to import a single object if the module author hasn't made provision for that, and it is not an easy task at the moment (see -L). +L). One way the author can provide such access is to give each C trait its own unique tag. (And the tag can be the object name!). Then the user can @@ -378,96 +377,101 @@ dynamically. For example: say log-of-zero; # OUTPUT: «-Inf␤» =end code -=head3 EXPORT X<|sub EXPORT> +=head3 EXPORT You can export arbitrary symbols with an C sub. C must return a L, where the keys are the symbol names and the values are the desired values. The names should include the sigil (if any) for the associated type. - =begin code - # lib/MyModule.rakumod +=begin code :solo +# lib/MyModule.rakumod - class MyModule::Class { } +class MyModule::Class { } - sub EXPORT { - %( - '$var' => 'one', - '@array' => , - '%hash' => %( one => 'two', three => 'four' ), - '&doit' => sub { say 'Greetings from exported sub' }, - 'ShortName' => MyModule::Class - ) - } - =end code +sub EXPORT { + Map.new: + '$var' => 'one', + '@array' => , + '%hash' => %( one => 'two', three => 'four' ), + '&doit' => sub { say 'Greetings from exported sub' }, + 'ShortName' => MyModule::Class +} +=end code - =begin code :skip-test - # main.raku - use lib 'lib'; - use MyModule; - say $var; # OUTPUT: «one␤» - say @array; # OUTPUT: «(one two three)␤» - say %hash; # OUTPUT: «{one => two, three => four}␤» - doit(); # OUTPUT: «Greetings from exported sub␤» - say ShortName.new; # OUTPUT: «MyModule::Class.new␤» - =end code +Which is going to be used from this main file: -Note, C can't be declared inside a package because -it is part of the compunit rather than the package. +=begin code :skip-test +# main.raku +use lib 'lib'; +use MyModule; +say $var; # OUTPUT: «one␤» +say @array; # OUTPUT: «(one two three)␤» +say %hash; # OUTPUT: «{one => two, three => four}␤» +doit(); # OUTPUT: «Greetings from exported sub␤» +say ShortName.new; # OUTPUT: «MyModule::Class.new␤» +=end code -Whereas C packages deal with the named parameters passed -to C, the C sub handles positional parameters. If you -pass positional parameters to C, they will be passed to -C. If a positional is passed, the module no longer exports -default symbols. You may still import them explicitly by -passing C<:DEFAULT> to C along with your positional parameters. +Please note that C can't be declared inside a +L because it is part of the compunit rather than the +package. - =begin code - # lib/MyModule +Whereas C packages deal with the named parameters passed to +C, the C sub handles positional parameters. If you pass positional +parameters to C, they will be passed to C. If a positional is +passed, the module no longer exports default symbols. You may still import them +explicitly by passing C<:DEFAULT> to C along with your positional +parameters. - class MyModule::Class {} +=begin code +# lib/MyModule - sub EXPORT($short_name?) { - %( - do $short_name => MyModule::Class if $short_name - ) - } +class MyModule::Class {} - sub always is export(:MANDATORY) { say "works" } +sub EXPORT($short_name?) { + Map.new: do $short_name => MyModule::Class if $short_name +} - #import with :ALL or :DEFAULT to get - sub shy is export { say "you found me!" } - =end code +sub always is export(:MANDATORY) { say "works" } - =begin code :skip-test - # main.raku - use lib 'lib'; - use MyModule 'foo'; - say foo.new(); # OUTPUT: «MyModule::Class.new␤» +#import with :ALL or :DEFAULT to get +sub shy is export { say "you found me!" } +=end code - always(); # OK - is imported - shy(); # FAIL - won't be imported - =end code +Used from this main program -You can combine C with type captures for interesting -effect. This example creates a C postfix which will only work on -Ls. - - =begin code - # lib/MakeQuestionable.rakumod - sub EXPORT(::Questionable) { - my multi postfix:(Questionable $_) { .so }; - %( - '&postfix:' => &postfix:, - ) - } - =end code +=begin code :skip-test +# main.raku +use lib 'lib'; +use MyModule 'foo'; +say foo.new(); # OUTPUT: «MyModule::Class.new␤» - =begin code :skip-test - use MakeQuestionable Cool; - say ( 0?, 1?, {}?, %( a => "b" )? ).join(' '); # OUTPUT: «False True False True␤» - =end code +always(); # OK - is imported +shy(); # FAIL - «shy used at line 8. Did you mean 'say'?» +=end code + +You can combine C with type captures for interesting effect. This +example creates a C postfix which will only work on Ls; +please note that, by using C<$_> as an argument, we don't need to use a +variable in the routine body and use just C<.so>, acting by default on the +topic variable. + +=begin code +# lib/MakeQuestionable.rakumod +sub EXPORT(::Questionable) { + my multi postfix:(Questionable $_) { .so }; + Map.new: '&postfix:' => &postfix:, +} +=end code + +Which is used from here: + +=begin code :skip-test +use lib 'lib'; +use MakeQuestionable Cool; +say ( 0?, 1?, {}?, %( a => "b" )? ).join(' '); # OUTPUT: «False True False True␤» +=end code =head2 Introspection @@ -490,12 +494,17 @@ special export sub: =for code :solo unit module Bar; -sub EXPORT { %(Foo => &say) } # WRONG!!! Sub is scoped wrong +sub EXPORT { Map.new: Foo => &say } # WRONG!!! Sub is scoped wrong + +As explained in L, C is +part of the I, not the package. So this would be the right way to +do it: =for code :solo -sub EXPORT { %(Foo => &say) } # RIGHT!!! Sub is outside the module +sub EXPORT { Map.new: Foo => &say } # RIGHT!!! Sub is outside the module unit module Bar; +As explained =head2 Finding installed modules It is up to the module installer to know where C expects modules to be @@ -524,6 +533,130 @@ The directories in the C path will be searched for modules when Raku Cs, Cs or Cs them. Directories that start with a dot are ignored and symlinks are followed. +=head1 Testing modules and a distribution + +It is important in this section to repeat the note at the beginning of this +document, namely that there is a difference between a B C, +which approximates a I in other languages, and a B +L. +The reason for this is that a single file may contain a number of C, +C, C etc declarations, or these declarations may be spread between +different files. In addition, when a C is published (see +L) it may be +necessary to provide access to other resources, such as callable utilities. + +B also allows for a single distribution to provide multiple Cs +that can be Cd (or Cd etc). The information about a distribution +is contained in the C file in the distribution's root directory. See +below for more about C. Each entity that the B allows +to be Cd (or Cd etc), also called a C, is placed in the +C section of the C (as specified below). + +It should also be noted that when writing the C section of the +C file, it is the name of the B that is listed, not +the name of the C that is desired. Although, for very many entities, +the name of the I and the name of the I are the same. +Another global effect of the C list in a distribution made available to +the Ecosystem, is that package managers, e.g. C, can look for C +names in all distributions available. + +Given this arrangement, the B compiler, or a package manager such as +B, can obtain all the information needed about each C from a +C file in a directory. + +This also means that a testing program such as B's C or the B +equivalent L can be +run in the root directory of the B as, e.g., + +=for code :lang +prove -e 'raku -I.' + +or + +=for code :lang +prove6 -I. + +In both cases, the testing program looks for a directory C and runs the test +programs there (see L). + +The parameter B<-I.>, rather than B<-Ilib>, in the examples above is significant +because then the compiler will inspect the C file in the root +directory of the B. + +If you are just beginning to develop a module (or series of modules), and you +have not decided what to call or where to place the code (perhaps splitting it +into several C<*.rakumod> files), but assuming all the module files are under +the C directory, then it is possible to use + +=for code :lang +prove6 -Ilib + +This is deceptive. A distribution may pass all the tests based on local files, +and it may pass release steps, but the distribution (and the +modules/classes/roles it contains) may not be automatically installed. To give a +common example, but not the only way this problem can manifest itself, if the +distribution is listed in the C section of another distribution, and a +user is trying to install the other distribution using C (or a package +manager using the same testing regime), perhaps using a CLI command C, then C arranges for the tests of the dependent +modules based on B<-I.> and not C<-Ilib>. This will lead to B errors +complaining about the absence of named B unless the B +file is correct. + +The most basic test that should be run for each C that is defined for +the distribution is + +=for code :preamble +use-ok 'MyModule'; + +assuming inside C there is a line such as + +=for code :lang +depends: [ "MyModule": "lib/MyModule.rakumod" ], + +It is also highly recommended to use the C C test, which +verifies the validity of the C file. If you wish to add a +distribution (module) to the C, then this test will be applied to the +distribution. + +Since C only needs to be tested by the developer/maintainer of a +module, it can be within a set of extended tests in another directory, e.g. +C. This is because C, for example, only runs the tests in C by +default. Then to run the extended tests: + +=for code :lang +prove6 -I. xt/ + +Indeed it is becoming common practice by B community developers to place +the extensive testing of a distribution in C and to put minimal I +tests in C. Extensive testing is essential for development and quality +control, but it can slow down the installation of popular distributions. + +An alternative to placing the C test in an extended test directory, but +to ensure that it is only run when a developer or maintainer wants to, is to +make the test dependent on an environment variable, e.g., in +C there is the following code + +=begin code +use Test; + +plan 1; + +if ?%*ENV { + require Test::META <&meta-ok>; + meta-ok; + done-testing; +} else { + skip-rest "Skipping author test"; + exit; +} +=end code + +Then when testing the module by the developer, use + +=for code :lang + AUTHOR_TEST=1 prove6 -I. + =head1 Distributing modules If you've written a Raku module and would like to share it with the @@ -665,7 +798,7 @@ point, you might also consider adding C, C, C, or other files.> If your module requires extra processing during installation to fully -integrate with and use non-Perl operating system resources, you may +integrate with and use non-Raku operating system resources, you may need to add a X|Build.pm6> file (a "build hook") to the top-level directory. It will be used by the C installer as the first step in the installation process. See the README for C for a brief example. Also see various usage scenarios in existing @@ -740,7 +873,7 @@ distribution and that you wish to be installed; only module files that are explicitly included here will be installed and available with C or C in other programs. This field is mandatory. -Set C version to the minimum perl version your module works with. This +Set C version to the minimum Raku version your module works with. This field is mandatory. Use C<6.c> if your module is valid for Christmas release and newer ones, use C<6.d> if it requires, at least, the Diwali version. @@ -840,7 +973,7 @@ zef install ./your-module-folder Note that doing so precompiles and installs your module. If you make changes to the source, you'll need to re-install the module. (See C L, C<-I> -command line switch, or C env variable, to include a path to your +command line switch, or C env variable, to include a path to your module source while developing it, so you don't have to install it at all). =end item @@ -893,6 +1026,38 @@ Those are the most common upload errors.> =end item +=head2 Upload your module to zef ecosystem + +If you want to use the I ecosystem then you need to register your username +using I. + +=item Install fez if you haven't done so already + +=begin code :lang +zef install fez +=end code + +=item Register your user with zef's ecosystem + +=begin code :lang +fez register +>>= Email: your@email.com +>>= Username: username +>>= Password: +>>= registration successful, requesting auth key +>>= login successful, you can now upload dists +=end code + +=item Now you can upload your module! + +Before doing the following, ensure your C file's "auth" matches "zef:" and then: + +=begin code :lang +fez upload +>>= Vortex::TotalPerspective:ver<0.1.2>:auth looks OK +>>= Hey! You did it! Your dist will be indexed shortly +=end code + =head2 Upload your module to p6c If you want to use the I ecosystem you need to use git for your module's @@ -916,7 +1081,7 @@ local repository to know about your GitHub repository. =item Consider setting up automated testing (see L). =item Create a PR (Pull Request) on L adding -your module to META.list, or ping someone on IRC (#raku at freenode) to +your module to META.list, or ping someone on IRC (#raku at libera.chat) to get help having it added. =item After the pull request has been accepted, wait for an hour. If @@ -950,12 +1115,12 @@ writing/test modules at L To discuss module development in general, or if your module would fill a need in the ecosystem, naming, etc., you can use the -L<#raku on irc.freenode.net|irc://irc.freenode.net/#raku> IRC channel. +L<#raku on irc.libera.chat|irc://irc.libera.chat/#raku> IRC channel. To discuss toolchain specific questions, you can use the -L<#perl6-toolchain on irc.freenode.net|irc://irc.freenode.net/#perl6-toolchain> +L<#raku-toolchain on irc.libera.chat|irc://irc.libera.chat/#raku-toolchain> IRC channel. A repository to discuss tooling issues is also available at -L. +L. =end pod diff --git a/doc/Language/mop.pod6 b/doc/Language/mop.pod6 index 7fb728aef..c944d274b 100644 --- a/doc/Language/mop.pod6 +++ b/doc/Language/mop.pod6 @@ -16,11 +16,7 @@ is needed. For example: =begin code my $arr = [1, 2]; -sub show-type($arr) { - my $type = $arr.^name; - say $type; -} -show-type $arr; # OUTPUT: «Array␤» +say $arr.^name; # OUTPUT: «Array␤» =end code To get a more in-depth understanding of the metaobject for a C, here is @@ -61,8 +57,9 @@ uses such calls to metaobjects. These are introspective macros that resemble method calls. -Metamethods are generally named with ALLCAPS, and it is considered good -style to avoid creating your own methods with ALLCAPS names. This will avoid +Metamethods are generally named with ALLCAPS, and it is considered good style +to avoid creating your own methods with ALLCAPS names (since they are used +conventionally for things like L. This will avoid conflicts with any metamethods that may appear in future versions of the language. @@ -71,7 +68,6 @@ language. The type object of the type. This is a pseudo-method that can be overloaded without producing error or warning, but will be ignored. - For example C<42.WHAT> returns the C type object. =head2 X @@ -100,7 +96,8 @@ objects of this type are used to build classes. The same operation on the C<&> sigil will return C. You will be calling this object whenever you use the C<^> syntax to access metamethods. In fact, the code above is equivalent to C which is much -more unwieldy. L is part of the Rakudo implementation, so use with caution. +more unwieldy. L is part of the +Rakudo implementation, so use with caution. =head2 X @@ -125,25 +122,77 @@ The presence of a C object indicates that the object is "itemized". say (1, 2, 3).VAR ~~ Scalar; # OUTPUT: «False␤» say $(1, 2, 3).VAR ~~ Scalar; # OUTPUT: «True␤» +Please refer to the L

for more information. + +=head1 Metaclass methods + +Same as you can define object and class methods (which do not have access to +the instance variables), you can define metaclass methods, which will work on +the metaclass. These are conventionally defined by a caret (C<^>) at the +front of the method identifier. These metaclass methods might return a type +object or a simple object; in general, they are only conventionally related +to the metaobject protocol and are, otherwise, simple methods with a peculiar +syntax. + +These methods will get called with the type name as first argument, but this +needs to be declared explicitly. + +=for code +class Foo { + method ^bar( Mu \foo) { + foo.^set_name( foo.^name ~ "[þ]" ); + } +} +my $foo = Foo.new(); +say $foo.^name; # OUTPUT: «Foo␤» +Foo.^bar(); +say $foo.^name; # OUTPUT: «Foo[þ]␤» + +This metaclass method will, via invoking class metamethods, change the name +of the class it's been declared. Since this has been acting on the metaclass, +any new object of the same class will receive the same name; invoking C will return the same value. As it can be seen, the metaclass +method is +invoked with no arguments; C<\foo> will, in this case, become the C when +invoked. + +The metaclass methods can receive as many arguments as you want. + +=for code +class Foo { + method ^bar( Mu \foo, Str $addenda) { + foo.^set_name( foo.^name ~ $addenda ); + } +} +Foo.new().^bar( "[baz]" ); +my $foo = Foo.new(); +say $foo.^name; # OUTPUT: «Foo[baz]␤» + +Again, implicitly, the method call will furnish the first argument, which is +the type object. Since they are metaclass methods, you can invoke them on a +class (as above) or on an object (as below). The result will be exactly the +same. + =head1 Structure of the metaobject system B this documentation largely reflects the metaobject system as implemented by the L, since the L are very light on details. -For each type declarator keyword, such as C, C, C, -C, C, C or C, there is a separate metaclass in the C namespace. (Rakudo implements them in the -C namespace, and then maps C to -C). +For each type declarator keyword, such as C, C, C, C, +C, C or C, there is a separate metaclass in the +C namespace. (Rakudo implements them in the C +namespace, and then maps C to C). -Many of these metaclasses share common functionality. For example -roles, grammars and classes can all contain methods and attributes, as well -as being able to do roles. This shared functionality is implemented in -roles which are composed into the appropriate metaclasses. For example -L implements -the functionality that a type can hold roles and -L, which is the metaclass -behind the C keyword, does this role. +Many of these metaclasses share common functionality. For example roles, +grammars and classes can all contain methods and attributes, as well as being +able to do roles. This shared functionality is implemented in roles which are +composed into the appropriate metaclasses. For example L implements the +functionality that a type can hold roles and +L, which is the metaclass behind +the C keyword, does this role. Most metaclasses have a C method that you must call when you're done creating or modifying a metaobject. It creates method caches, validates things @@ -175,11 +224,10 @@ be mutable. However if all types were always mutable, all reasoning about them would get invalidated at any modification of a type. For example the list of parent types and thus the result of type checking can change during that time. -So to get the best of -both worlds, there is a time when a type transitions from mutable to -immutable. This is called I, and for syntactically declared -types, it happens when the type declaration is fully parsed (so usually when -the closing curly brace is parsed). +So to get the best of both worlds, there is a time when a type transitions from +mutable to immutable. This is called I, and for syntactically +declared types, it happens when the type declaration is fully parsed (so usually +when the closing curly brace is parsed). If you create types through the metaobject system directly, you must call C<.^compose> on them before they become fully functional. diff --git a/doc/Language/nativecall.pod6 b/doc/Language/nativecall.pod6 index 0b118e3d6..c5608fd6c 100644 --- a/doc/Language/nativecall.pod6 +++ b/doc/Language/nativecall.pod6 @@ -7,6 +7,8 @@ =head1 Getting started X<|nativecall> +X<|is native> +X<|native (trait)> The simplest imaginable use of C would look something like this: @@ -321,8 +323,7 @@ my $number_of_ints = 10; $ints[$number_of_ints - 1] = 0; # extend the array to 10 items =end code - -The memory management of arrays is important to understand. When you create an +It is important that you understand how arrays manage memory. When you create an array yourself, then you can add elements to it as you wish and it will be expanded for you as required. However, this may result in it being moved in memory (assignments to existing elements will never cause this, however). This @@ -330,12 +331,13 @@ means you'd best know what you're doing if you twiddle with an array after passing it to a C library. By contrast, when a C library returns an array to you, then the memory can not -be managed by NativeCall, and it doesn't know where the array ends. Presumably, -something in the library API tells you this (for example, you know that when -you see a null element, you should read no further). Note that NativeCall can -offer you no protection whatsoever here - do the wrong thing, and you will get a -segfault or cause memory corruption. This isn't a shortcoming of NativeCall, it's -the way the big bad native world works. Scared? Here, have a hug. Good luck! +be managed by C, and it doesn't know where the array ends. +Presumably, something in the library API tells you this (for example, you know +that when you see a null element, you should read no further). Note that +C can offer you no protection whatsoever here - do the wrong thing, +and you will get a segfault or cause memory corruption. This isn't a shortcoming +of C, it's the way the big bad native world works. Scared? Here, +have a hug. Good luck! X<|CArray> X<|CArray methods> @@ -440,7 +442,7 @@ values to the private members: class MyStruct is repr('CStruct') { has CArray[num64] $!arr; has Str $!str; - has Point $!point; # Point is a user-defined class + has Point $!point; # Point is a user-defined class shown above submethod TWEAK { my $arr := CArray[num64].new; @@ -456,7 +458,7 @@ class MyStruct is repr('CStruct') { As you may have predicted by now, a C pointer is represented by the type object of the struct type. -=head2 CUnions +=head2 Cs Likewise, it is possible to declare a Raku class that stores its attributes the same way a C compiler would lay them out in a similar @@ -579,7 +581,7 @@ pointer embedded in a C. =begin code use NativeCall; -sub strdup(Str $s --> Pointer[Str]) is native {*} +sub strdup(Str $s --> Pointer[Str]) is native { * } my Pointer[Str] $p = strdup("Success!"); say $p.deref; =end code @@ -749,9 +751,9 @@ sub LIBBAR { } # and later -sub mysql_affected_rows returns int32 is native(LIBMYSQL) {*}; -sub bar is native(LIBFOO) {*} -sub baz is native(LIBBAR) {*} +sub mysql_affected_rows returns int32 is native(LIBMYSQL) { * }; +sub bar is native(LIBFOO) { * } +sub baz is native(LIBBAR) { * } =end code You can also put an incomplete path like './foo' and NativeCall will @@ -760,7 +762,7 @@ If you wish to suppress this expansion, simply pass the string as the body of a block. =begin code :preamble -sub bar is native({ './lib/Non Standard Naming Scheme' }) {*} +sub bar is native({ './lib/Non Standard Naming Scheme' }) { * } =end code BE CAREFUL: the C trait and C are evaluated at compile time. @@ -786,11 +788,11 @@ can be a full version or just a part of it. (Try to stick to Major version, some BSD code does not care for Minor.) use NativeCall; - sub foo1 is native('foo', v1) {*} # Will try to load libfoo.so.1 - sub foo2 is native('foo', v1.2.3) {*} # Will try to load libfoo.so.1.2.3 + sub foo1 is native('foo', v1) { * } # Will try to load libfoo.so.1 + sub foo2 is native('foo', v1.2.3) { * } # Will try to load libfoo.so.1.2.3 my List $lib = ('foo', 'v1'); - sub foo3 is native($lib) {*} + sub foo3 is native($lib) { * } =head2 Routine @@ -799,7 +801,7 @@ The C trait also accepts a C as argument, allowing you to provide your own way to handle the way it will find the library file to load. use NativeCall; - sub foo is native(sub {'libfoo.so.42'}) {*} + sub foo is native(sub {'libfoo.so.42'}) { * } It will only be called at the first invocation of the sub. diff --git a/doc/Language/nativetypes.pod6 b/doc/Language/nativetypes.pod6 index d6a13bdd2..b070f6e8d 100644 --- a/doc/Language/nativetypes.pod6 +++ b/doc/Language/nativetypes.pod6 @@ -57,7 +57,7 @@ B: In v6.c, the default value for C would have been a NaN. This is due to the fact that Natives don't know their types because they're just values, without any metadata. In -L, you can have a +L, you can have a native candidate, but you cannot differentiate different sizes or signedness of the same native type. That is, you can have an L and L candidates, but there would be an @@ -76,15 +76,16 @@ Native types can also be composite. my int @intillos = ^10_000_000; say [+] @intillos; # OUTPUT: «49999995000000␤» -X<|native array>X<|array> -In this case, Iness extends to the composite type, which will be +X<|native array> +In this case, Iness extends to the composite type, which is called C my num @many-pi = ^8 »*» π ; say @many-pi.^name; # OUTPUT: «array[num]␤» -Native Cs are L, but they are not a subclass of -List. However, they behave similarly to Ls; for instance, -they can be shaped: +Native Cs behave as L and +L, but they are not a subclass of C; thus, +they behave similarly to Ls; for instance, they can be +shaped: =begin code my str @letter-pairs[10] = 'a'..'j' Z~ 'A'..'J'; @@ -111,8 +112,8 @@ X<|num32>X<|num64>X<|byte> =head1 Types with native representation and size What has been mentioned about types with native representation also applies -here; they will be auto-boxed to Raku types and will not be boundable. -However, these types, which are listed in the table below, have the +here; they will be auto-boxed to Raku types and you will not be able to bind +to them. However, these types, which are listed in the table below, have the characteristic of being usable in L functions. @@ -142,7 +143,7 @@ Since C is able to hold only 8 bits, it will I and assign the result of the original value modulo 256, which is what is shown. The main difference between types with declared native size and those without is -the use of X in their declaration. For instance, C is +the use of X> in their declaration. For instance, C is declared in this way: my native int8 is repr('P6int') is Int is nativesize(8) { } diff --git a/doc/Language/newline.pod6 b/doc/Language/newline.pod6 index 1eacaa628..76c6c0ef7 100644 --- a/doc/Language/newline.pod6 +++ b/doc/Language/newline.pod6 @@ -38,8 +38,8 @@ You can change the default behavior for a particular handle by setting the C<:nl-out> attribute when you create that handle. my $crlf-out = open(IO::Special.new(''), :nl-out("\\\n\r")); - $*OUT.say: 1; #OUTPUT: «1␤» - $crlf-out.say: 1; #OUTPUT: «1\␤␍» + $*OUT.say: 1; # OUTPUT: «1␤» + $crlf-out.say: 1; # OUTPUT: «1\␤␍» In this example, where we are replicating standard output to a new handle by using L, we are appending a C<\> to the end of @@ -48,7 +48,7 @@ we print to that handle will get those characters at the end of the line, as shown. In regular expressions, -L|/language/regexes#index-entry-regex_\n-regex_\N-\n_and_\N> is defined in +L|/language/regexes#\n_and_\N> is defined in terms of the L. It will match C<.> and also C<\v>, as well as any class that includes whitespace. diff --git a/doc/Language/numerics.pod6 b/doc/Language/numerics.pod6 index 79fc05b62..9be8d1626 100644 --- a/doc/Language/numerics.pod6 +++ b/doc/Language/numerics.pod6 @@ -245,7 +245,7 @@ say ((42 + FatRat.new(1,2))/99999999999999999999999).^name; # OUTPUT: «FatRat =end code There's no special operator or syntax available for construction of L -objects. Simply use L«C method|/type/FatRat#(Rational)_method_new», +objects. Simply use the C method, giving numerator as first positional argument and denominator as the second. If your program requires a significant amount of L creation, you could @@ -261,7 +261,7 @@ say (1🙼3).raku; # OUTPUT: «FatRat.new(1, 3)␤» Keep in mind that output routines like L or L do not try very hard to distinguish between how L types are output and may choose to display a L as an L or a L number. For a more definitive string to -output, use the L method: +output, use the L method: =begin code say 1.0; # OUTPUT: «1␤» @@ -544,8 +544,8 @@ At times, you may wish to coerce some value to a native type without creating an There are no C<.int> or similar coercion methods (method calls are latebound, so they're not well-suited for this purpose). Instead, simply use an anonymous variable: -=begin code :preamble -some-native-taking-sub (my int $ = $y), (my int32 $ = $z) +=begin code :preamble +some-native-taking-sub( (my int $ = $y), (my int32 $ = $z) ) =end code =head2 Overflow/Underflow diff --git a/doc/Language/objects.pod6 b/doc/Language/objects.pod6 index 8c59cddb1..ee17e504e 100644 --- a/doc/Language/objects.pod6 +++ b/doc/Language/objects.pod6 @@ -184,6 +184,24 @@ class Journey { } =end code +Alternatively, you can omit the twigil, which will still create the private +attribute (with a C twigil), and will also create an alias that binds +the name (without the twigil) to that attribute. Thus, you can declare the +same class above with + +=begin code +class Journey { + has $origin; + has $destination; + has @travelers; + has $notes; +} +=end code + +If you declare the class like this, you can subsequently access the attributes +either with or without the twigil – e.g., C<$!origin> and C<$origin> refer to +same attribute. + While there is no such thing as a public (or even protected) attribute, there is a way to have accessor methods generated automatically: replace the C twigil with the C<.> twigil (the C<.> should remind you of a method @@ -553,6 +571,15 @@ CATCH { default { put .^name ~ ":\n" ~ .Str } } # 'FunMath'. Did you mean '!do-subtraction'?␤» =end code +Private methods have their own namespace. They're not virtual, i.e., +private methods cannot be overriden within the inheriting class to provide any +polymorphic behavior, thus missing ones are detected at compile time. Unlike +in some languages where C is +an L on a +method, in Raku "private methods" and "methods" are quite different things - +that is to say, it's better to read "private method" as a compound noun rather +than an adjective describing a noun. + Private methods are not inherited by subclasses. X<|Submethods> @@ -651,13 +678,14 @@ $test.Parent::frob; # calls the frob method of Parent X<|delegation (trait handles)> =head2 Delegation -Delegation is a technique whereby a member of an object (the I«delegatee») is -evaluated in the context of another original object (the I«delegator»). In other -words, all method calls on the delegator are I«delegated» to the delegatee. +Delegation is a technique whereby an object, the I«delegator», accepts a +method call but has designated another object, the I«delegatee», to process the +call in its place. In other words, the I«delegator» publishes one or more +of the I«delegatee»'s methods as its own. In Raku, delegation is specified by applying the L«handles|/language/typesystem#trait_handles» trait to an attribute. The arguments provided to the trait specify the methods -the current object and the delegatee object will have in common. Instead of a +the object and the I«delegatee» attribute will have in common. Instead of a list of method names, a C (for renaming), a list of C, a C or a C can be provided. @@ -1257,8 +1285,8 @@ class B is A does M { class C is A does M { } -B.new.f; # OUTPUT «I am in class B␤» -C.new.f; # OUTPUT «I am in role M␤» +B.new.f; # OUTPUT: «I am in class B␤» +C.new.f; # OUTPUT: «I am in role M␤» =end code Note that each candidate for a multi-method is its own method. In this case, @@ -1279,8 +1307,8 @@ role Point { method abs { sqrt($.x * $.x + $.y * $.y) } method dimensions { 2 } } -say Point.new(x => 6, y => 8).abs; # OUTPUT «10␤» -say Point.dimensions; # OUTPUT «2␤» +say Point.new(x => 6, y => 8).abs; # OUTPUT: «10␤» +say Point.dimensions; # OUTPUT: «2␤» =end code We call this automatic creation of classes I, and the generated class diff --git a/doc/Language/operators.pod6 b/doc/Language/operators.pod6 index a065c584e..543a90b12 100644 --- a/doc/Language/operators.pod6 +++ b/doc/Language/operators.pod6 @@ -58,7 +58,7 @@ assigned to that level (column labeled C), and some exemplary operators X | Junctive or | \| ^ (\|) (^) (\+) (-) ∪ ⊖ ⊎ ∖ L | Named unary | temp let N | Structural infix | but does <=> leg unicmp cmp coll .. ..^ ^.. ^..^ - C | Chaining infix | != ≠ == < <= ≤ > >= ≥ eq ne lt le gt ge ~~ === eqv !eqv =~= ≅ (elem) (cont) (<) (>) (<=) (>=) (<\+) (>\+) ∈ ∉ ∋ ∌ ⊂ ⊄ ⊃ ⊅ ⊆ ⊈ ⊇ ⊉ ≼ ≽ + C | Chaining infix | != ≠ == ⩵ < <= ≤ > >= ≥ eq ne lt le gt ge ~~ === ⩶ eqv !eqv =~= ≅ (elem) (cont) (<) (>) (<=) (>=) (<\+) (>\+) (==) ∈ ∊ ∉ ∋ ∍ ∌ ≡ ≢ ⊂ ⊄ ⊃ ⊅ ⊆ ⊈ ⊇ ⊉ ≼ ≽ X | Tight and | && X | Tight or | \|\| ^^ // min max R | Conditional | ?? !! ff ff^ ^ff ^ff^ fff fff^ ^fff ^fff^ @@ -144,17 +144,6 @@ L<#prefix ...> etc. stub operators. Defining custom operators is covered in L. -=head1 Metaoperators - -Metaoperators can be parameterized with other operators or subroutines -in the same way as functions can take functions as parameters. To use a -subroutine as a parameter, prefix its name with a C<&>. Raku will -generate the actual combined operator in the background, allowing the -mechanism to be applied to user defined operators. To disambiguate -chained metaoperators, enclose the inner operator in square brackets. -There are quite a few metaoperators with different semantics as -explained, next. - =head1 Substitution operators Each substitution operator comes into two main forms: a lowercase one (e.g., @@ -312,9 +301,10 @@ judging the while loop condition. In dealing with simple and compound assignment operators, it is tempting to think that for instance the following two statements are (always) equivalent: - =for code :skip-test + =begin code :skip-test expression1 += expression2; # compound assignment expression1 = expression1 + expression2; # simple assignment + =end code They are not, however, for two reasons. Firstly, C in the compound assignment statement is evaluated only once, whereas C in the @@ -377,7 +367,18 @@ compound assignment operators: my $a = 3.14; $a .= round; # $a = $a.round; OUTPUT: «3» -=head1 Negated relational operators +=head1 Metaoperators + +Metaoperators can be parameterized with other operators or subroutines +in the same way as functions can take other functions as parameters. To use a +subroutine as a parameter, prefix its name with a C<&>. Raku will +generate the actual combined operator in the background, allowing the +mechanism to be applied to user defined operators. To disambiguate +chained metaoperators, enclose the inner operator in square brackets. +There are quite a few metaoperators with different semantics as +explained, next. + +=head2 Negated relational operators X<|! (negation metaoperator)>X<|!==>X<|!eq> The result of a relational operator returning C can be negated by @@ -394,7 +395,7 @@ There are shortcuts for C and C, namely C and C. my $today = Date.today; say so $release !before $today; # OUTPUT: «False␤» -=head1 Reversed operators +=head2 Reversed operators X<|R,reverse metaoperator> Any infix operator may be called with its two arguments reversed by @@ -406,7 +407,7 @@ prefixing with C. Associativity of operands is reversed as well. X<|»=«> X<|«=»> -=head1 X<<>;hyper,«;hyper,»;>>> +=head2 X<<>;hyper,«;hyper,»;>>> Hyper operators include C<«> and C<»>, with their ASCII variants C«<<» and C«>>». They apply a given operator enclosed (or preceded or followed, in the @@ -523,7 +524,7 @@ You can chain hyper operators to destructure a List of Lists. say $neighbors »>>+<<» ($p, *); # OUTPUT: «((1 3) (2 2) (2 4) (3 3))␤» X<|[] (reduction metaoperators)>X<|[+] (reduction metaoperators)> -=head1 Reduction metaoperators +=head2 Reduction metaoperators The reduction metaoperator, C<[ ]>, reduces a list with the given infix operator. It gives the same result as the L routine - @@ -556,7 +557,7 @@ C<\> already, quote it with C<[]> (e.g. C<[\[\x]]>). my @n = [\~] 1..*; say @n[^5]; # OUTPUT: «(1 12 123 1234 12345)␤» -=head1 Cross operators +=head2 Cross metaoperators X<|X (cross metaoperator)> The cross metaoperator, C, will apply a given infix operator in order of @@ -565,7 +566,7 @@ quickly. 1..3 X~ # OUTPUT: «<1a, 1b, 2a, 2b, 3a, 3b>␤» -=head1 Zip metaoperator +=head2 Zip metaoperator X<|Z (zip metaoperator)> The zip metaoperator (which is not the same thing as L) will @@ -586,7 +587,7 @@ default: my @l = 1 Z 2; # OUTPUT: «[(1 2)]» -=head1 Sequential operators +=head2 Sequential operators X<|S,sequential metaoperator> The sequential metaoperator, C, will suppress any concurrency or reordering @@ -594,7 +595,7 @@ done by the optimizer. Most simple infix operators are supported. say so 1 S& 2 S& 3; # OUTPUT: «True␤» -=head1 Nesting of metaoperators +=head2 Nesting of metaoperators To avoid ambiguity when chaining metaoperators, use square brackets to help the compiler understand you. @@ -680,7 +681,7 @@ Universal interface for positional access to zero or more elements of a say @alphabet[1]; # OUTPUT: «b␤» say @alphabet[*-1]; # OUTPUT: «z␤» say @alphabet[100]:exists; # OUTPUT: «False␤» - say @alphabet[15, 4, 17, 11].join; # OUTPUT: «perl␤» + say @alphabet[17, 0, 10, 20].join; # OUTPUT: «raku␤» say @alphabet[23 .. *].raku; # OUTPUT: «("x", "y", "z")␤» @alphabet[1, 2] = "B", "C"; @@ -717,7 +718,7 @@ in custom types. Decontainerization operator, which extracts the value from a container and makes it independent of the container type. -=begin code +=begin code :skip-test use JSON::Tiny; my $config = from-json('{ "files": 3, "path": "/home/some-user/raku.pod6" }'); @@ -778,8 +779,11 @@ Technically, not a real operator; it's syntax special-cased in the compiler. X«|methodop .&» =head2 methodop C«.&» -The operator to call a subroutine (with at least one positional argument), such -as a method. The invocant will be bound to the first positional argument. +The operator to call a L, such as a +L, a L, or a L +with method syntax. The invocant will be bound to the first positional +argument (and thus dispatch will fail if the C does not accept +at least one positional argument). Technically, not a real operator; it's syntax special-cased in the compiler. @@ -1099,7 +1103,7 @@ is carried out without loss of precision. Unicode superscripts will behave in exactly the same way. sub squared( Int $num ) { $num² }; - say squared($_) for ^5; OUTPUT: «0␤1␤4␤9␤16␤» + say squared($_) for ^5; # OUTPUT: «0␤1␤4␤9␤16␤» It also works for sequences of several Unicode superscript numbers: @@ -1321,13 +1325,13 @@ I operation assuming two's complement.X<|Numeric bitwise AND operator> =head2 infix C«+<» - multi sub infix:<< +< >>($a, $b --> Int:D) + multi sub infix:«+<»($a, $b --> Int:D) Integer bit shift to the left.X<|integer bit shift operator,left> =head2 infix C«+>» - multi sub infix:<< +> >>($a, $b --> Int:D) + multi sub infix:«+>»($a, $b --> Int:D) Integer bit shift to the right.X<|integer bit shift operator,right> @@ -1532,11 +1536,11 @@ element say [~] Blob.new([3,4,5]); # OUTPUT: «Blob:0x<03 04 05>␤» say [~] 1|2; # OUTPUT: «any(1, 2)␤» -=head2 infix C«∘» +=head2 infix C, infix C«∘» - multi sub infix:<∘>() - multi sub infix:<∘>(&f) - multi sub infix:<∘>(&f, &g --> Block:D) + multi sub infix:() + multi sub infix:(&f) + multi sub infix:(&f, &g --> Block:D) X<|o, operators> The X C«infix:<∘>» or C«infix:» @@ -1549,27 +1553,27 @@ Both C<.count> and C<.arity> of the right-hand side will be maintained, as well as the C<.of> of the left hand side. =begin code - sub f($p){ say 'f'; $p / 2 } - sub g($p){ say 'g'; $p * 2 } - - my &composed = &f ∘ &g; - say composed 2; # OUTPUT: «g␤f␤2␤» - # equivalent to: - say 2.&g.&f; - # or to: - say f g 2; - say &composed.arity; # OUTPUT: «1␤» - say &composed.count; # OUTPUT: «1␤» - say &composed.of; # OUTPUT: «(Mu)␤» +sub f($p){ say 'f'; $p / 2 } +sub g($p){ say 'g'; $p * 2 } + +my &composed = &f ∘ &g; +say composed 2; # OUTPUT: «g␤f␤2␤» +# equivalent to: +say 2.&g.&f; +# or to: +say f g 2; +say &composed.arity; # OUTPUT: «1␤» +say &composed.count; # OUTPUT: «1␤» +say &composed.of; # OUTPUT: «(Mu)␤» =end code =begin code - sub f($a, $b, $c) { [~] $c, $b, $a } - sub g($str){ $str.comb } - my &composed = &f ∘ &g; - say composed 'abc'; # OUTPUT: «cba␤» - # equivalent to: - say f |g 'abc'; +sub f($a, $b, $c) { [~] $c, $b, $a } +sub g($str){ $str.comb } +my &composed = &f ∘ &g; +say composed 'abc'; # OUTPUT: «cba␤» +# equivalent to: +say f |g 'abc'; =end code The single-arg candidate returns the given argument as is. The zero-arg candidate @@ -1595,10 +1599,10 @@ details. =head2 infix C«(&)», infix C«∩» multi sub infix:<(&)>(**@p) - multi sub infix:<∩>(**@p) X. +'&' as in left hand side arguments 'and' right hand side arguments. Returns the B of all of its arguments. This creates a new L that contains only the elements common to all of the arguments if none of the arguments are a L, @@ -1606,7 +1610,7 @@ L, L or L. =begin code say (&) ; # OUTPUT: «Set(b c)␤» - ; # OUTPUT: «Set(c d)␤» + say ; # OUTPUT: «Set(c d)␤» =end code If any of the arguments are L or L, @@ -1618,12 +1622,9 @@ of that element over all arguments). say (&) bag(); # OUTPUT: «Bag(a(2) b c)␤» =end code -C«∩» is equivalent to C«(&)», at codepoint U+2229 (INTERSECTION). - =head2 infix C«(.)», infix C«⊍» multi sub infix:<(.)>(**@p) - multi sub infix:<⊍>(**@p) X. @@ -1638,8 +1639,6 @@ L if any of the arguments is a L. say ⊍ bag(); # OUTPUT: «Bag(a(6) b c(2))␤» =end code -C«⊍» is equivalent to C«(.)», at codepoint U+228D (MULTISET MULTIPLICATION). - =head1 Junctive OR (any) precedence =head2 infix C«|» @@ -1661,10 +1660,11 @@ resulting in a positive match. See also L for more deta =head2 infix C«(|)», infix C«∪» multi sub infix:<(|)>(**@p) - multi sub infix:<∪>(**@p) X. +'|' as in left hand side arguments 'or' right hand side arguments. + Returns the B of all of its arguments. This creates a new L that contains all the elements its arguments contain if none of the arguments are a L, L, @@ -1682,12 +1682,9 @@ weighted by the I weight that appeared for that element. say ∪ bag(); # OUTPUT: «Bag(a(2) b c d)␤» =end code -C«∪» is equivalent to C«(|)», at codepoint U+222A (UNION). - =head2 infix C«(+)», infix C«⊎» multi sub infix:<(+)>(**@p) - multi sub infix:<⊎>(**@p) X. @@ -1706,12 +1703,9 @@ If any of the arguments is a L, the result is a new C. say (+) (a => 2.5, b => 3.14).Mix; # OUTPUT: «Mix(a(3.5) b(4.14) c)␤» =end code -C«⊎» is equivalent to C«(+)», at codepoint U+228E (MULTISET UNION). - =head2 infix C«(-)», infix C«∖» multi sub infix:<(-)>(**@p) - multi sub infix:<∖>(**@p) X. @@ -1736,8 +1730,6 @@ element in each of the other arguments. say ∖ mix(); # OUTPUT: «Mix(a(2) c(-1) d)␤» =end code -C«∖» is equivalent to C«(-)», at codepoint U+2216 (SET MINUS). - =head2 infix C«^» multi sub infix:<^>($a, $b --> Junction:D) is assoc @@ -1750,10 +1742,7 @@ details. =head2 infix C«(^)», infix C«⊖» multi sub infix:<(^)>($a, $b) - multi sub infix:<⊖>($a,$b) - multi sub infix:<(^)>(**@p) - multi sub infix:<⊖>(**@p) X. @@ -1774,8 +1763,6 @@ the result is a new C (or C). say ⊖ bag(); # OUTPUT: «Bag(a c)␤» =end code -C«⊖» is equivalent to C«(^)», at codepoint U+2296 (CIRCLED MINUS). - =head1 Named unary precedence =head2 prefix C«temp» @@ -1998,7 +1985,7 @@ aspects of the particular character like capitalization. The main difference between C and C is that the behavior of the former can be changed by the -L|/type/Any#index-entry-%24*COLLATION-%24*COLLATION> dynamic +L|/type/variables#index-entry-%24*COLLATION> dynamic variable. B These are not yet implemented in the JVM. @@ -2059,7 +2046,7 @@ Constructs a L from the arguments, excluding both start and e =head1 Chaining binary precedence -=head2 infix C«==» +=head2 infix C«==», infix C«⩵» multi sub infix:<==>(Any, Any) multi sub infix:<==>(Int:D, Int:D) @@ -2074,7 +2061,9 @@ X. Coerces both arguments to L (if necessary); returns C if they are equal. -=head2 infix C«!=» +Since Rakudo version 2021.07, ⩵ is an alias for this operator. + +=head2 infix C«!=», infix C«≠» sub infix:(Mu, Mu --> Bool:D) @@ -2083,13 +2072,7 @@ X. Coerces both arguments to L (if necessary); returns C if they are distinct. -Is an alias to C«!==». - -=head2 infix C«≠» - -Numeric inequality operator. - -Equivalent to L«!=|/routine/!=», at codepoint U+2260 (NOT EQUAL TO). +Is equivalent to C«!==». =head2 infix C«<» @@ -2102,7 +2085,7 @@ X. Coerces both arguments to L (if necessary); returns C if the first argument is smaller than the second. -=head2 infix C«<=» +=head2 infix C«<=», infix C«≤» multi sub infix:«<=»(Int:D, Int:D) multi sub infix:«<=»(Num:D, Num:D) @@ -2113,12 +2096,6 @@ X. Coerces both arguments to L (if necessary); returns C if the first argument is smaller than or equal to the second. -=head2 infix C«≤» - -Numeric less than or equal to operator. - -Equivalent to L«<=|/routine/<=», at codepoint U+2264 (LESS-THAN OR EQUAL TO). - =head2 infix C«>» multi sub infix:«>»(Int:D, Int:D) @@ -2130,7 +2107,7 @@ X. Coerces both arguments to L (if necessary); returns C if the first argument is larger than the second. -=head2 infix C«>=» +=head2 infix C«>=», infix C«≥» multi sub infix:«>=»(Int:D, Int:D) multi sub infix:«>=»(Num:D, Num:D) @@ -2141,12 +2118,6 @@ X. Coerces both arguments to L (if necessary); returns C if the first argument is larger than or equal to the second. -=head2 infix C«≥» - -Numeric greater than or equal to operator. - -Equivalent to L«>=|/routine/>=», at codepoint U+2265 (GREATER-THAN OR EQUAL TO). - =head2 infix C«eq» multi sub infix:(Any, Any) @@ -2327,7 +2298,7 @@ say infix:(33); # OUTPUT: «True␤» say infix:(False); # OUTPUT: «True␤» -=head2 infix C«===» +=head2 infix C«===», infix C«⩶» sub infix:<===>(Any, Any) @@ -2358,6 +2329,8 @@ class must create an instance method C, that should return a L object that won't change for the lifetime of the object. +Since Rakudo version 2021.07, ⩶ is an alias for this operator. + =head2 infix C«=:=» multi sub infix:<=:=>(Mu \a, Mu \b) @@ -2452,18 +2425,17 @@ Note that setting $*TOLERANCE = 0 will cause all comparisons to fail. =head2 infix (elem), infix ∈ multi sub infix:<(elem)>($a,$b --> Bool:D) - multi sub infix:<∈>($a,$b --> Bool:D) X. Returns C if C<$a> is an B of C<$b>. - =begin code - say 2 (elem) (1, 2, 3); # OUTPUT: «True␤» - say 4 ∈ (1, 2, 3); # OUTPUT: «False␤» - =end code +=begin code +say 2 (elem) (1, 2, 3); # OUTPUT: «True␤» +say 4 ∈ (1, 2, 3); # OUTPUT: «False␤» +=end code -C«∈» is equivalent to C«(elem)», at codepoint U+2208 (ELEMENT OF). +Since release 2020.05, ∊ is an alias for this operator. =head2 infix C«∉» @@ -2474,28 +2446,52 @@ X. Returns C if C<$a> is B an B of C<$b>. Equivalent to C. +=begin code +say 4 ∉ (1, 2, 3); # OUTPUT: «True␤» +say 2 !(elem) (1, 2, 3); # OUTPUT: «False␤» +=end code + +=head2 infix C«(==)», infix C«≡» + + multi sub infix:<(==)>($a,$b --> Bool:D) + +X + +Returns C if C<$a> and C<$b> are B. + =begin code - say 4 ∉ (1, 2, 3); # OUTPUT: «True␤» - say 2 !(elem) (1, 2, 3); # OUTPUT: «False␤» + say (1, 2, 3) (==) (1, 3, 2); # OUTPUT: «True␤» + say (1, 2, 3) ≡ (1, 2, 4); # OUTPUT: «False␤» =end code -C«∉» is codepoint U+2209 (NOT AN ELEMENT OF). +=head2 infix C«≢» + + multi sub infix:<≢>($a,$b --> Bool:D) + +X + +Returns C if C<$a> and C<$b> are B. Equivalent to +C. + + =begin code + say (1, 2, 3) ≢ (1, 2, 4); # OUTPUT: «True␤» + say (1, 2, 3) ≢ (1, 3, 2); # OUTPUT: «False␤» + =end code =head2 infix (cont), infix ∋ multi sub infix:<(cont)>($a,$b --> Bool:D) - multi sub infix:<∋>($a,$b --> Bool:D) X. -Returns C if C<$a> B C<$b>. +Returns C if C<$a> B C<$b> as an element. - =begin code - say (1,2,3) (cont) 2; # OUTPUT: «True␤» - say (1, 2, 3) ∋ 4; # OUTPUT: «False␤» - =end code +=begin code +say (1,2,3) (cont) 2; # OUTPUT: «True␤» +say (1, 2, 3) ∋ 4; # OUTPUT: «False␤» +=end code -C«∋» is equivalent to C«(cont)», at codepoint U+220B (CONTAINS AS MEMBER). +Since release 2020.05, ∍ is an alias for this operator. =head2 infix C«∌» @@ -2511,12 +2507,9 @@ C. say (1,2,3) !(cont) 2; # OUTPUT: «False␤» =end code -C«∌» is codepoint U+220C (DOES NOT CONTAIN AS MEMBER). - =head2 infix C«(<)», infix C«⊂» - multi sub infix:<< (<) >>($a,$b --> Bool:D) - multi sub infix:<⊂>($a,$b --> Bool:D) + multi sub infix:«(<)»($a,$b --> Bool:D) X. @@ -2529,8 +2522,6 @@ elements of C<$a> are elements of C<$b> but C<$a> is a smaller set than C<$b>. say 4 ⊂ (1,2,3); # OUTPUT: «False␤» =end code -C«⊂» is equivalent to C«(<)», at codepoint U+2282 (SUBSET OF). - =head2 infix C«⊄» multi sub infix:<⊄>($a,$b --> Bool:D) @@ -2546,12 +2537,9 @@ C«!(<)». say 4 !(<) (1,2,3); # OUTPUT: «True␤» =end code -C«⊄» is codepoint U+2284 (NOT A SUBSET OF). - =head2 infix C«(<=)», infix C«⊆» - multi sub infix:<< (<=) >>($a,$b --> Bool:D) - multi sub infix:<⊆>($a,$b --> Bool:D) + multi sub infix:«(<=)»($a,$b --> Bool:D) X. @@ -2565,8 +2553,6 @@ set than C<$b>. say 4 ⊆ (1,2,3); # OUTPUT: «False␤» =end code -C«⊆» is equivalent to C«(<=)», at codepoint U+2286 (SUBSET OF OR EQUAL TO). - =head2 infix C«⊈» multi sub infix:<⊈>($a,$b --> Bool:D) @@ -2582,12 +2568,9 @@ C«!(<=)». say 4 !(<=) (1,2,3); # OUTPUT: «True␤» =end code -C«⊈» is codepoint U+2288 (NEITHER A SUBSET OF NOR EQUAL TO). - =head2 infix C«(>)», infix C«⊃» - multi sub infix:<< (>) >>($a,$b --> Bool:D) - multi sub infix:<⊃>($a,$b --> Bool:D) + multi sub infix:«(>)»($a,$b --> Bool:D) X. @@ -2600,8 +2583,6 @@ elements of C<$b> are elements of C<$a> but C<$a> is a larger set than C<$b>. say 4 ⊃ (1,2,3); # OUTPUT: «False␤» =end code -C«⊃» is equivalent to C«(>)», at codepoint U+2283 (SUPERSET OF). - =head2 infix C«⊅» multi sub infix:<⊅>($a,$b --> Bool:D) @@ -2617,12 +2598,9 @@ C«!(>)». say 4 !(>) (1,2,3); # OUTPUT: «True␤» =end code -C«⊅» is codepoint U+2285 (NOT A SUPERSET OF). - =head2 infix C«(>=)», infix C«⊇» - multi sub infix:<< (>=) >>($a,$b --> Bool:D) - multi sub infix:<⊇>($a,$b --> Bool:D) + multi sub infix:«(>=)»($a,$b --> Bool:D) X. @@ -2636,8 +2614,6 @@ set than C<$b>. say 4 ⊇ (1,2,3); # OUTPUT: «False␤» =end code -C«⊇» is equivalent to C«(>=)», at codepoint U+2287 (SUPERSET OF OR EQUAL TO). - =head2 infix C«⊉» multi sub infix:<⊉>($a,$b --> Bool:D) @@ -2653,8 +2629,6 @@ C«!(>=)». say 4 !(>=) (1,2,3); # OUTPUT: «True␤» =end code -C«⊉» is codepoint U+2289 (NEITHER A SUPERSET OF OR EQUAL TO). - =head1 Tight AND precedence =head2 infix C«&&» @@ -2954,7 +2928,7 @@ Called the I. It copies the value of the right-hand side into the Scalar container on the left-hand side. The item assignment operator should be distinguished from the L, which uses the same +operator|/language/operators#infix_=_(list_assignment)>, which uses the same operator symbol C<=> but has a lower precedence. The context of the left-hand side of the C<=> symbol determines whether it is parsed as item assignment or list assignment. See the section on L and L for common cases. The list assignment operator should be distinguished from the L, which uses the same +operator|/language/operators#infix_=_(item_assignment)>, which uses the same operator symbol C<=> but has a higher precedence. The context of the left-hand side of the C<=> symbol determines whether it is parsed as item assignment or list assignment. See the section on L. =head2 infix X The C operator returns -L«C|/type/Slip#index-entry-Empty-Empty» upon encountering the +L«C|/type/Slip#constant_Empty» upon encountering the first L argument, otherwise the last argument. Last argument is returned as-is, without being checked for definedness at all. Short-circuits. The result of the left side is bound @@ -3363,7 +3337,7 @@ behavior: =head2 infix X The C operator returns -L«C|/type/Slip#index-entry-Empty-Empty» upon encountering the first +L«C|/type/Slip#constant_Empty» upon encountering the first L argument, otherwise the last argument. Last argument is returned as-is, without being checked for definedness at all. Short-circuits. The result of the left side is bound to C<$_> for the right side, or passed as @@ -3373,7 +3347,7 @@ L must be C<0> or C<1>. At first glance, L might appear to be the same thing as the L operator. The difference is subtle: L returns -L«C|/type/Slip#index-entry-Empty-Empty» when it encounters a +L«C|/type/Slip#constant_Empty» when it encounters a L item (that isn't the last item), whereas L returns that item. In other words, L is a means to act when items aren't defined, diff --git a/doc/Language/packages.pod6 b/doc/Language/packages.pod6 index 4774d7618..5e787c3fd 100644 --- a/doc/Language/packages.pod6 +++ b/doc/Language/packages.pod6 @@ -141,7 +141,7 @@ the setting's outermost scope, use C instead. =head2 Interpolating into names X<|interpolating into names> -X<|::()> You may L a string into a +X<|::()> You may L a string into a package or variable name using C<::($expr)> where you'd ordinarily put a package or variable name. The string is allowed to contain additional instances of C<::>, which will be interpreted as package nesting. You may only interpolate @@ -257,6 +257,61 @@ go into that package by default. Process-wide variables live in the C package. Most predefined globals such as C<$*UID> and C<$*PID> are actually process globals. +=head1 Programmatic use of modules + +It is sometimes useful to be able to programmatically define and use modules. +Here is a practical example. + +Assume we have a series of modules with the module files in a directory +tree like this: + +=begin code :lang +lib/ + TomtomMaps/ + Example/ + # a directory of example file modules programmatically + # created from the Tomtom Maps SDK + A01.rakumod + #... + C09.rakumod + #... +=end code + +Module C looks like this: + +=begin code :solo +unit module TomtomMaps::Example::C09; + +# ensure you use the 'our' declarator +our sub print-example($fh, # filehandle open for writing + :$api-maps-key +) { # do not need to export the sub + $fh.print: qq:to/HERE/; + # ... the example html file + HERE +} +=end code + +We can access and use the subroutines like this: + +=begin code :solo +use lib 'lib'; +my $module-dir = 'TomtomMaps::Example'; +my $example = 'C09'; +my $m = "{$module-dir}::{$example}"; + +# you must use the runtime 'require', not the compile-time 'use' +require ::($m); + +my $fh = open "./example-{$example}.html", :w; +my $api-maps-key = 'ghghfxnnhrgfsWE.mmn'; + +# execute the subroutine +&::($m)::print-example($fh, :$api-maps-key); # the map's html file is written + +$fh.close; +=end code + =end pod # vim: expandtab softtabstop=4 shiftwidth=4 ft=perl6 diff --git a/doc/Language/performance.pod6 b/doc/Language/performance.pod6 index f46642b9d..48eac3f7e 100644 --- a/doc/Language/performance.pod6 +++ b/doc/Language/performance.pod6 @@ -80,7 +80,7 @@ opening in SQLite. =begin code :lang # create a profile - perl6 --profile=demo.sql -e 'say (^20).combinations(3).elems' + raku --profile=demo.sql -e 'say (^20).combinations(3).elems' # create a SQLite database sqlite3 demo.sqlite @@ -229,7 +229,7 @@ there are a number of L. =item If low-level C hacking is your idea of fun, checkout -L and visit the freenode IRC channel #moarvm +L and visit the libera.chat IRC channel #moarvm (L). =head2 Still need more ideas? @@ -267,7 +267,7 @@ an informed response (a few days or weeks, depending on the exact nature of your problem and potential solutions). If I hasn't worked out, please consider filing an issue about your experience at -L before moving on. +L before moving on. Thanks. :) diff --git a/doc/Language/phasers.pod6 b/doc/Language/phasers.pod6 index 5e3983e03..7bcefa325 100644 --- a/doc/Language/phasers.pod6 +++ b/doc/Language/phasers.pod6 @@ -321,17 +321,17 @@ I run. =head2 X -Runs at every successful block exit, as part of the LEAVE queue (shares the +Runs at every successful block exit, as part of the C queue (shares the same order of execution). =head2 X -Runs at every unsuccessful block exit, as part of the LEAVE queue (shares the +Runs at every unsuccessful block exit, as part of the C queue (shares the same order of execution). =head2 X -Asserts a precondition at every block entry. Runs before the ENTER phase. +Asserts a precondition at every block entry. Runs before the C phase. C
 phasers fire off before any C or C.
 
@@ -341,7 +341,7 @@ a C
 phaser fails.
 
 =head2 X
 
-Asserts a postcondition at every block entry. Runs after the LEAVE phase.
+Asserts a postcondition at every block entry. Runs after the C phase.
 
 For phasers such as C and C that are run when exiting a scope
 normally, the return value (if any) from that scope is available as the current
@@ -369,12 +369,12 @@ a loop, and may occur only at the top level of such a loop block.
 
 =head2 X
 
-Runs at loop initialization, before ENTER.
+Runs at loop initialization, before c.
 
 =head2 X
 
 Runs when loop is continued (either through C or because you got to the
-bottom of the loop and are looping back around), before LEAVE.
+bottom of the loop and are looping back around), before C.
 
 A C executes only if the end of the loop block is reached normally, or an
 explicit C is executed. In distinction to C phasers, a C
@@ -391,11 +391,12 @@ using C or C; it is executed after C.
 
 =head2 X
 
-Runs when an exception is raised by the current block, before the LEAVE phase.
+Runs when an exception is raised by the current block, before the C phase.
+Also see L.
 
 =head2 X
 
-Runs when a control exception is raised by the current block, before the LEAVE
+Runs when a control exception is raised by the current block, before the C
 phase. It is raised by C, C, C, C, C, C, C,
 C, C, C and C.
 
diff --git a/doc/Language/pod.pod6 b/doc/Language/pod.pod6
index 22d56540b..953b252bb 100644
--- a/doc/Language/pod.pod6
+++ b/doc/Language/pod.pod6
@@ -2,7 +2,7 @@
 
 =TITLE Pod6
 
-=SUBTITLE An easy-to-use markup language for documenting Raku modules and programs
+=SUBTITLE An easy-to-use markup language for documenting Raku modules and programs
 
 Pod6 is an easy-to-use markup language. It can be used for
 writing language documentation, for documenting programs and modules, as
@@ -33,7 +33,9 @@ Delimited blocks are bounded by C<=begin> and C<=end> markers, both of
 which are followed by a valid Raku identifier, which is the
 C of the block. Typenames that are entirely lowercase (for
 example: C<=begin head1>) or entirely uppercase (for example: C<=begin
-SYNOPSIS>) are reserved.
+SYNOPSIS>) are reserved. Indentation of the =begin/=end lines is
+required to be the same to create a valid block; otherwise, an error
+or unexpected results will occur.
 
 =begin code :lang
 =begin head1
@@ -79,7 +81,7 @@ values cannot be closures. See L
 for details of the various
 Raku pair notations.
 
-IN the future, the configuration section may be extended over subsequent
+In the future, the configuration section may be extended over subsequent
 lines by
 starting those lines with an C<=> in the first (virtual) column followed
 by a whitespace character. N
 
 L
 
+Alongside the normal way of describing a path, viz. C< L >, it is also
+possible to use the module-style notation, e.g., C< L >.
+
 =head2 Placement links
 
 This code is not implemented in C, but is partially implemented
@@ -789,7 +794,7 @@ C
 
 Once installed, run the following command in the terminal:
 =begin code :lang
-perl6 --doc=HTML input.pod6 > output.html
+raku --doc=HTML input.pod6 > output.html
 =end code
 
 =head2 Markdown
@@ -802,7 +807,7 @@ C
 
 Once installed, run the following command in the terminal:
 =begin code :lang
-perl6 --doc=Markdown input.pod6 > output.md
+raku --doc=Markdown input.pod6 > output.md
 =end code
 
 =head2 Text
@@ -812,13 +817,13 @@ C module.
 
 Using the terminal, run the following command:
 =begin code :lang
-perl6 --doc=Text input.pod6 > output.txt
+raku --doc=Text input.pod6 > output.txt
 =end code
 
 You can omit the C<=Text> portion:
 
 =begin code :lang
-perl6 --doc input.pod6 > output.txt
+raku --doc input.pod6 > output.txt
 =end code
 
 You can even embed Pod6 directly in your program and add the
diff --git a/doc/Language/pragmas.pod6 b/doc/Language/pragmas.pod6
index 8b7d898ba..d9b0b06b1 100644
--- a/doc/Language/pragmas.pod6
+++ b/doc/Language/pragmas.pod6
@@ -139,7 +139,7 @@ only affects the lexical block it was used in:
         CATCH { default { say "Caught {.^name}" } }
     } # OUTPUT: «Caught X::Str::Numeric␤»
 
-Inside L«C blocks|/language/exceptions#index-entry-try_blocks-try», the
+Inside L«C blocks|/language/exceptions#index-entry-try_blocks», the
 C pragma is enabled by default, and you can I it with C:
 
@@ -202,7 +202,7 @@ X<|lib, pragma>
 
 This pragma adds subdirectories to the library search
 path so that the interpreter can
-L.
+L.
 
 =begin code :solo
 use lib ;
@@ -293,7 +293,7 @@ Lexically controls whether compile-time warnings generated by the
 compiler get shown. Enabled by default.
 
     =begin code :lang
-    $ perl6 -e 'say :foo<>.Pair'
+    $ raku -e 'say :foo<>.Pair'
     Potential difficulties:
       Pair with <> really means an empty list, not null string; use :foo('') to represent the null string,
         or :foo() to represent the empty list more accurately
@@ -301,7 +301,7 @@ compiler get shown. Enabled by default.
       ------> say :foo<>⏏.Pair
     foo => Nil
 
-    $ perl6 -e 'no worries; say :foo<>.Pair'
+    $ raku -e 'no worries; say :foo<>.Pair'
     foo => Nil
     =end code
 
diff --git a/doc/Language/py-nutshell.pod6 b/doc/Language/py-nutshell.pod6
index a3e6280ff..9b79383e6 100644
--- a/doc/Language/py-nutshell.pod6
+++ b/doc/Language/py-nutshell.pod6
@@ -141,12 +141,12 @@ Python
 =begin code :lang
 s = 10
 l = [1, 2, 3]
-d = { a : 12, b : 99 }
+d = { 'a' : 12, 'b' : 99 }
 
 print s
 print l[2]
 print d['a']
-# 10, 2, 12
+# 10, 3, 12
 =end code
 
 Raku
@@ -357,6 +357,46 @@ I
         say $c;
     }
 
+Uses of Python's C and C<.items()> mechanisms for
+iterating lists or dict/maps can both be achieved using the same
+L method in Raku (because the "key" of a list is its
+array-like numeric index):
+
+I
+
+=begin code :lang
+elems = ["neutronium", "hydrogen", "helium", "lithium"]
+for i, e in enumerate(elems):
+    print "Elem no. %d is %s" % (i, e)
+symbols = ["n", "H", "He", "Li"]
+elem4Symbol = {s: e for s, e in zip(symbols, elems)}
+for symbol, elem in elem4Symbol.items():
+    print "Symbol '%s' stands for %s" % (symbol, elem)
+# Elem no. 0 is neutronium
+# Elem no. 1 is hydrogen
+# Elem no. 2 is helium
+# Elem no. 3 is lithium
+# Symbol 'H' stands for hydrogen
+# Symbol 'He' stands for helium
+# Symbol 'Li' stands for lithium
+# Symbol 'n' stands for neutronium
+=end code
+
+I
+
+    my @elems = ;
+    for @elems.kv -> $i, $e {
+        say "Elem no. $i is $e"
+    }
+
+    my @symbols = ;
+    my %elem-for-symbol;
+    %elem-for-symbol{@symbols} = @elems;
+
+    # Note that the iteration order will differ from Python
+    for %elem-for-symbol.kv -> $symbol, $element {
+        say "Symbol '$symbol' stands for $element";
+    }
 
 =head2 X
 
@@ -777,14 +817,14 @@ print(tuple3)                                      # OUTPUT: «(1, 'two', 3, 'ha
 
 Raku
 
-Raku does not have a builtin Tuple type, though they are available as modules.
-You can obtain the same behavior from Raku using the List type.
+Raku does not have a builtin Tuple type. You can get the same behavior from
+Raku using the List type, or from an external module.
 
     my $list1 = (1, "two", 3, "hat");
     my $list2 = (5, 6, "seven");
     say $list1[1];                                 # OUTPUT: «two␤»
-    my $list3 = slip($list1), slip($list2);
-    my $list4 = |$list1, |$list2;                  # equivalent to previous line
+    my $list3 = (slip($list1), slip($list2));
+    my $list4 = (|$list1, |$list2);                # equivalent to previous line
     say $list3;                                    # OUTPUT: «(1, two, 3, hat, 5, 6, seven)␤»
 
 =end pod
diff --git a/doc/Language/quoting.pod6 b/doc/Language/quoting.pod6
index 4b5d64946..249869a97 100644
--- a/doc/Language/quoting.pod6
+++ b/doc/Language/quoting.pod6
@@ -420,11 +420,11 @@ I interpolate variables. Thus
     say qx{echo "hello $world"}
 
 prints simply C. Nevertheless, if you have declared an environment
-variable before calling C, this will be available within C, for
+variable before calling C, this will be available within C, for
 instance
 
 =begin code :skip-test
-WORLD="there" perl6
+WORLD="there" raku
 > say qx{echo "hello $WORLD"}
 =end code
 
@@ -461,8 +461,8 @@ better ways to execute external commands.
 
 =head2 X
 
-A convenient way to write multi-line string literals are I, which
-let you choose the delimiter yourself:
+A convenient way to write a multi-line string literal is by using a I, which
+lets you choose the delimiter yourself:
 
 =begin code
 say q:to/END/;
@@ -472,7 +472,7 @@ string
 END
 =end code
 
-The contents of the heredoc always begin on the next line, so you can (and
+The contents of the I always begin on the next line, so you can (and
 should) finish the line.
 
 =begin code :preamble
@@ -483,7 +483,7 @@ TERMINATOR
 =end code
 
 If the terminator is indented, that amount of indention is removed from the
-string literals. Therefore this heredoc
+string literals. Therefore this I
 
 =begin code
 say q:to/END/;
@@ -503,7 +503,7 @@ some multi line
 
 =end code
 
-Heredocs include the newline from before the terminator.
+I include the newline from before the terminator.
 
 To allow interpolation of variables use the C form, but you will then have
 to escape metacharacters C<\{> as well as C<$> if it is not the sigil for a
@@ -525,7 +525,51 @@ option {
 };
 =end code
 
-You can begin multiple Heredocs in the same line.
+Some other situations to pay attention to are innocent-looking ones
+where the text looks like a Raku expression. For example, the
+following generates an error:
+
+=begin code :lang
+my $title = 'USAFA Class of 1965';
+say qq:to/HERE/;
+$title
+HERE
+# Output:
+Type Str does not support associative indexing.
+  in block  at here.raku line 2
+=end code
+
+The angle bracket to the right of '$title' makes it look like a hash index
+to Raku when it is actually a C variable, hence the error message.
+One solution is to enclose the scalar with curly braces which is one
+way to enter an expression in any interpolating quoting construct:
+
+=begin code :lang
+say qq:to/HERE/;
+{$title}
+HERE
+=end code
+
+Another option is to escape the `<` character to avoid it being parsed
+as the beginning of an indexing operator:
+
+=begin code :lang
+say qq:to/HERE/;
+$title\
+HERE
+=end code
+
+Because a I can be very long but is still interpreted by Raku
+as a single line, finding the source of an error can sometimes be
+difficult. One crude way to debug the error is by starting with the
+first visible line in the code and treating is as a I with
+that line only. Then, until you get an error, add each line in turn.
+(Creating a Raku program to do that is left as an exercise for the
+reader.)
+
+You can begin multiple Heredocs in the same line. If you do so, the
+second heredoc will not start until after the first heredoc has
+ended.
 
 =begin code
 my ($first, $second) = qq:to/END1/, qq:to/END2/;
@@ -537,8 +581,11 @@ my ($first, $second) = qq:to/END1/, qq:to/END2/;
    MULTILINE
    STRING
    END2
+say $first;  # OUTPUT: «FIRST␤MULTILINE␤STRING␤»
+say $second; # OUTPUT: «SECOND␤MULTILINE␤STRING␤»
 =end code
 
+X<|Unquoting>
 =head2 Unquoting
 
 Literal strings permit interpolation of embedded quoting constructs by using the
diff --git a/doc/Language/rb-nutshell.pod6 b/doc/Language/rb-nutshell.pod6
index f96c7ccc0..bbebd1a7d 100644
--- a/doc/Language/rb-nutshell.pod6
+++ b/doc/Language/rb-nutshell.pod6
@@ -289,7 +289,10 @@ add(2, 3);                       # => 5, and it works without it
 =end code
 
 =for code :lang
-foo_method = &foo;     # Ruby
+def foo
+  ...
+end
+foo_method = method(:foo);     # Ruby
 =for code
 sub foo { ... };
 my &foo_method = &foo; # Raku
@@ -945,7 +948,7 @@ class Person {
 Creating a new instance of the class uses the C<.new> method. In Ruby you must
 manually assign instance variables as needed inside C. In Raku
 you get a default constructor that accepts key/value pairs of accessor
-attributes, and can do further setup in the C method. Like with Ruby,
+attributes, and can do further setup in the C method. Like with Ruby,
 you can override C itself for more advanced functionality, but this is
 rare.
 
@@ -967,9 +970,9 @@ p = Person.new( name: 'Jack', age: 23 )
 class Person {
     has $.name = 'Jill';
     has $.age  = 42;
-    has $!birth_year;
-    method BUILD {
-        $!birth_year = now.Date.year - $.age;
+    has $.birth_year;
+    method TWEAK {
+        $!birth_year = now.Date.year - $!age;
     }
 }
 my $p = Person.new( name => 'Jack', age => 23 )
@@ -1050,7 +1053,7 @@ See L for lots of further details.
 
 =head1 Environment variables
 
-=head2 Perl module library path
+=head2 Raku module library path
 
 In Ruby, one of the environment variables to specify extra search paths for
 modules is C.
@@ -1059,12 +1062,12 @@ modules is C.
 $ RUBYLIB="/some/module/lib" ruby program.rb
 
 In Raku this is similar, you merely needs to change the name. As you probably
-guessed, you just need to use C:
+guessed, you just need to use C:
 
 =for code :lang
-$ PERL6LIB="/some/module/lib" perl6 program.p6
+$ RAKULIB="/some/module/lib" raku program.raku
 
-As with Ruby, if you don't specify C, you need to specify the
+As with Ruby, if you don't specify C, you need to specify the
 library path within the program via the C pragma:
 
 =for code :solo
@@ -1155,11 +1158,11 @@ sub MAIN ( Int :$length where * > 0, :$filename = 'file.dat', Bool :$verbose ) {
 =end code
 
 =begin code :lang
-perl6 example.p6 --file=foo --length=42 --verbose
+raku example.p6 --file=foo --length=42 --verbose
     42
     foo
     Verbosity on
-perl6 example.p6 --length=abc
+raku example.p6 --length=abc
     Usage:
       example.p6 [--length=] [--file=] [--verbose]
 =end code
diff --git a/doc/Language/regexes.pod6 b/doc/Language/regexes.pod6
index 84c8fa096..00fef38d9 100644
--- a/doc/Language/regexes.pod6
+++ b/doc/Language/regexes.pod6
@@ -84,12 +84,14 @@ of a L that runs until the end of
 the line.
 =end item
 
-Secondly, the C form enables the use of
-L, which may be placed between C and the
-opening delimiter to modify the definition of the entire regex:
+Secondly, the C form allows you to insert
+L between C and the
+opening delimiter to modify the definition of the entire regex.  This is equivalent to
+inserting the adverb at the beginning of the regex, but may be clearer:
 
     rx:r:s/pattern/;            # :r (:ratchet) and :s (:sigspace) adverbs, defining
                                 # a ratcheting regex in which whitespace is significant
+    rx/:r:s pattern/;           # Same, but possibly less readable
 
 Although anonymous regexes are not, as such, I, they may effectively be
 given a name by putting them inside a named variable, after which they can be
@@ -370,16 +372,16 @@ An unescaped dot C<.> in a regex matches any single character.
 
 So, these all match:
 
-    'perl' ~~ /per./;       # matches the whole string
-    'perl' ~~ / per . /;    # the same; whitespace is ignored
-    'perl' ~~ / pe.l /;     # the . matches the r
-    'speller' ~~ / pe.l/;   # the . matches the first l
+    'raku' ~~ /rak./;       # matches the whole string
+    'raku' ~~ / rak . /;    # the same; whitespace is ignored
+    'raku' ~~ / ra.u /;     # the . matches the k
+    'raker' ~~ / rak. /;    # the . matches the e
 
 while this doesn't match:
 
-    'perl' ~~ /. per /;
+    'raku' ~~ / . rak /;
 
-because there's no character to match before C in the target string.
+because there's no character to match before C in the target string.
 
 Notably C<.> also matches a logical newline C<\n>:
 
@@ -392,7 +394,7 @@ Notably C<.> also matches a logical newline C<\n>:
       ;
 
     say $text ~~ / .* /;
-    # OUTPUT «「Although I am a␤multi-line text,␤I can be matched␤with /.*/.␤」»
+    # OUTPUT: «「Although I am a␤multi-line text,␤I can be matched␤with /.*/.␤」»
 
 =head1 Character classes
 
@@ -676,7 +678,7 @@ C«<:Ll+:N>» or C«<:Ll+:Number>» or C«<+ :Lowercase_Letter + :Number>».
 It's also possible to group categories and sets of categories with
 parentheses; for example:
 
-    say $0 if 'perl6' ~~ /\w+(<:Ll+:N>)/ # OUTPUT: «「6」␤»
+    say $0 if 'raku9' ~~ /\w+(<:Ll+:N>)/ # OUTPUT: «「9」␤»
 
 =head2 X«Enumerated character classes and ranges|regex,<[ ]>;regex,<-[ ]>»
 
@@ -691,6 +693,23 @@ whitespace.
     "ÀÁÂÃÄÅÆ" ~~ / <[ \x[00C0] .. \x[00C6] ]>* /;
     # Unicode named codepoint range
     "αβγ" ~~ /<[\c[GREEK SMALL LETTER ALPHA]..\c[GREEK SMALL LETTER GAMMA]]>*/;
+    # Non-alphanumeric
+    '$@%!' ~~ /<[ ! @ $ % ]>+/  # OUTPUT: «「$@%!」␤»
+
+As the last line above illustrates, within C«<[ ]>» you do I need to
+quote or escape most non-alphanumeric characters the way you do in regex text
+outside of C«<[ ]>».  You do, however, need to escape the much smaller set of
+characters that have special meaning within C«<[ ]>», such as C<\>, C<[>, and
+C<]>.
+
+X<|escaping characters>
+To escape characters that would have some meaning inside the C«<[ ]>», precede
+the character with a C<\>.
+
+    say "[ hey ]" ~~ /<-[ \] \[ \s ]>+/; # OUTPUT: «「hey」␤»
+
+You do not have the option of quoting special characters inside a C«<[ ]>» –
+a C<'> just matches a literal C<'>.
 
 Within the C«< >» you can use C<+> and C<-> to add or remove multiple range
 definitions and even mix in some of the Unicode categories above. You can also
@@ -706,12 +725,6 @@ You can include Unicode properties in the list as well:
     /<:Zs + [\x9] - [\xA0]>/
     # Any character with "Zs" property, or a tab, but not a "no-break space"
 
-X<|escaping characters>
-You can use C<\> to escape characters that would have some meaning in the
-regular expression:
-
-    say "[ hey ]" ~~ /<-[ \] \[ \s ]>+/; # OUTPUT: «「hey」␤»
-
 To negate a character class, put a C<-> after the opening angle bracket:
 
     say 'no quotes' ~~ /  <-[ " ]> + /;  # <-["]> matches any character except "
@@ -850,7 +863,7 @@ ordinary and a modified quantifier:
 
 =head2 X|regex,:>
 
-One way to prevent L is
+One way to prevent L is
 through the use of the C adverb as described
 L. Another more fine-grained way of preventing
 backtracking in regexes is attaching a C<:> modifier to a quantifier:
@@ -1070,21 +1083,21 @@ anchoring the regex match to that position.
 
 The C<^> anchor only matches at the start of the string:
 
-    say so 'properly' ~~ /  perl/;    # OUTPUT: «True␤»
-    say so 'properly' ~~ /^ perl/;    # OUTPUT: «False␤»
-    say so 'perly'    ~~ /^ perl/;    # OUTPUT: «True␤»
-    say so 'perl'     ~~ /^ perl/;    # OUTPUT: «True␤»
+    say so 'karakul'  ~~ /  raku/;    # OUTPUT: «True␤»
+    say so 'karakul'  ~~ /^ raku/;    # OUTPUT: «False␤»
+    say so 'rakuy'    ~~ /^ raku/;    # OUTPUT: «True␤»
+    say so 'raku'     ~~ /^ raku/;    # OUTPUT: «True␤»
 
 The C<$> anchor only matches at the end of the string:
 
-    say so 'use perl' ~~ /  perl  /;   # OUTPUT: «True␤»
-    say so 'use perl' ~~ /  perl $/;   # OUTPUT: «True␤»
-    say so 'perly'    ~~ /  perl $/;   # OUTPUT: «False␤»
+    say so 'use raku' ~~ /  raku  /;   # OUTPUT: «True␤»
+    say so 'use raku' ~~ /  raku $/;   # OUTPUT: «True␤»
+    say so 'rakuy'    ~~ /  raku $/;   # OUTPUT: «False␤»
 
 You can combine both anchors:
 
-    say so 'use perl' ~~ /^ perl $/;   # OUTPUT: «False␤»
-    say so 'perl'     ~~ /^ perl $/;   # OUTPUT: «True␤»
+    say so 'use raku' ~~ /^ raku $/;   # OUTPUT: «False␤»
+    say so 'raku'     ~~ /^ raku $/;   # OUTPUT: «True␤»
 
 Keep in mind that C<^> matches the start of a B, not the start of
 a B. Likewise, C<$> matches the end of a B, not the end of
@@ -1434,7 +1447,7 @@ which, by default, don't capture.
 If you do not need the captures, using non-capturing C<[ ... ]>
 groups provides the following benefits:
 =item  they more cleanly communicate the regex intent,
-=item  they make it easier to count the capturing groups that do mean and
+=item  they make it easier to count the capturing groups that do match, and
 =item  they make matching a bit faster.
 
 =head2 Capture numbers
@@ -2278,7 +2291,7 @@ When two adverbs are used together, they keep their colon at the front
 
     "þor is Þor" ~~ m:g:i/þ/;  # OUTPUT: «(「þ」 「Þ」)␤»
 
-That implies that when there are two vowels together after a C<:>, they
+That implies that when there are multiple characters together after a C<:>, they
 correspond to the same adverb, as in C<:ov> or C<:P5>.
 
 =head3 X
@@ -2643,7 +2656,7 @@ C.
 
 =head1 Backtracking
 
-Raku defaults to I when evaluating regular expressions.
+Raku defaults to L when evaluating regular expressions.
 Backtracking is a technique that allows the engine to try different
 matching in order to allow every part of a regular expression to succeed.
 This is costly, because it requires the engine to usually
diff --git a/doc/Language/setbagmix.pod6 b/doc/Language/setbagmix.pod6
index 221219bf1..34fb2d088 100644
--- a/doc/Language/setbagmix.pod6
+++ b/doc/Language/setbagmix.pod6
@@ -11,7 +11,7 @@ L, L, L and
 L.   They all share similar semantics.
 
 In a nutshell, these classes hold, in general, unordered collections of
-objects, much like an L.
+objects, much like an L.
 The L role is the role that is implemented by all
 of these classes: therefore they are also referenced as Ces.
 
@@ -174,6 +174,18 @@ Returns C if C<$a> is B a B of C<$b>, else C.
 L,
 L.
 
+=head3 infix (==), infix ≡
+
+Returns C if C<$a> and C<$b> are B, else C.
+L,
+L.
+
+=head3 infix ≢
+
+Returns C if C<$a> and C<$b> are B, else C.
+L,
+L.
+
 =head2 Set operators that return a C
 
 =head3 infix (|), infix ∪
diff --git a/doc/Language/statement-prefixes.pod6 b/doc/Language/statement-prefixes.pod6
index ca33b3c9b..6ed06215e 100644
--- a/doc/Language/statement-prefixes.pod6
+++ b/doc/Language/statement-prefixes.pod6
@@ -180,7 +180,7 @@ C, which goes to C<@factor>.
 =head2 X|start (statement prefix)>
 
 As a statement prefix, C behaves in the same way as L, that is, it runs the statement
+block|/language/control#start>, that is, it runs the statement
 asynchronously, and returns a promise.
 
 =begin code
diff --git a/doc/Language/structures.pod6 b/doc/Language/structures.pod6
index 7a90313e4..3d71094db 100644
--- a/doc/Language/structures.pod6
+++ b/doc/Language/structures.pod6
@@ -188,7 +188,7 @@ say $gets-logs( "2018-05-28" );
 # OUTPUT: «({changing => Logs} Stuff More stuff)␤»
 =end code
 
-L|/type/Block#(Code)_method_assuming> wraps around a block
+L|/type/Code#method_assuming> wraps around a block
 call, giving a value (in this case, C) to the arguments we need,
 and passing on the arguments to the other arguments we represent using
 C<*>. In fact, this corresponds to the natural language statement "We
@@ -227,7 +227,7 @@ Regexes are actually a type of callable:
 And in the example above we are calling regexes stored in an array, and
 applying them to a string literal.
 
-Callables are composed by using the L:
+Callables are composed by using the L:
 
 =begin code :preamble
 my $typer = -> $thing { $thing.^name ~ ' → ' ~ $thing };
@@ -397,7 +397,7 @@ done by using C<.Bool> method (or just using C), since you
 don't need to reify I the elements to find out if there are C of them.
 
 There are times where you I want to fully-reify a list before doing
-something. For example, the L«C|/type/IO::Handle#method_lines»
+something. For example, the L«C|/type/IO::Handle#routine_lines»
 returns a L. The following code contains a bug; keeping
 reification in mind, try to spot it:
 
@@ -408,7 +408,7 @@ close $fh;
 say $lines[0];
 
 We open a L, then assign return of
-L«C<.lines>|/type/IO::Handle#method_lines» to a L variable,
+L«C<.lines>|/type/IO::Handle#routine_lines» to a L variable,
 so the returned L does not get reified right away. We then
 L«C|/routine/close» the filehandle, and try to print an element from
 C<$lines>.
diff --git a/doc/Language/subscripts.pod6 b/doc/Language/subscripts.pod6
index af7e86451..9e2508645 100644
--- a/doc/Language/subscripts.pod6
+++ b/doc/Language/subscripts.pod6
@@ -23,7 +23,7 @@ Raku provides two universal subscripting interfaces:
 
 =head2 B subscripting
 
-B subscripting(via L subscripting (via L|/language/operators#postcircumfix_[_]>) addresses elements of an ordered
 collection by their position. Index 0 refers to the first element, index 1 to
 the second, and so on:
@@ -33,6 +33,11 @@ the second, and so on:
     say @chores[1];  # OUTPUT: «feed dog␤»
     say @chores[2];  # OUTPUT: «wash car␤»
 
+Note that Rakudo's implementation of subscripting allows only 63 bits on
+64 bit builds. See
+L.
+If larger subscripts are required, one may use L
+or alternatively, use a C with C subscripting (see below).
 
 =head2 B subscripting
 
@@ -959,35 +964,63 @@ optional named parameter will contain a C value when the method is called
 on the object for the first time. It should return the invocant.
 
 =begin code
+role Logger { method log( Str $msg) {…}}
+
+class ConsoLogger does Logger { method log ( Str $msg ) { "❢ $msg".say }}
+
 class DNA {
-    has $.chain is rw;
-
-    method STORE ($chain where {
-                         $chain ~~ /^^ <[ACGT]>+ $$ / and
-                         $chain.chars %% 3
-                     }, :$INITIALIZE --> DNA) {
-        if $INITIALIZE {
-            self = DNA.new( chain => $chain )
-        } else {
-            self.chain = $chain;
-            self
+    has $.chain;
+    has Logger $!logger;
+
+    submethod BUILD( :$chain, :$logger = ConsoLogger.new() ) {}
+
+    method STORE (Str $chain where {
+            /^^ <[ACGT]>+ $$ / and
+            .chars %% 3
+        },
+        :$INITIALIZE --> DNA) {
+
+        if ($INITIALIZE) {
+            $!logger = ConsoLogger.new();
+            $!logger.log( "Initialized" );
         }
+
+        $!chain  := $chain;
+        $!logger.log("Change value to $chain" );
+        self
     }
 
-    method Str(::?CLASS:D:) { return $.chain.comb.rotor(3) }
+    method Str(::?CLASS:D:) { return $!chain.comb.rotor(3).map( *.join("")).join("|") }
 };
 
-my @string is DNA = 'GAATCC';
-say @string.Str;    # OUTPUT: «((G A A) (T C C))␤»
-@string = 'ACGTCG';
-say @string.Str;    # OUTPUT: «((A C G) (T C G))␤»
+my @string is DNA = 'GAATCC';    # OUTPUT: «❢ Initialized␤❢ Change value to GAATCC␤»
+say ~@string;                    # OUTPUT: «GAA|TCC␤»
+@string = 'ACGTCG';              # OUTPUT: «❢ Change value to ACGTCG␤»
+say  ~@string;                   # OUTPUT: «ACG|TCG␤»
 =end code
 
 This code takes into account the value of C<$INITIALIZE>, which is set to
 C only if we are assigning a value to a variable declared using the C
-syntax for the first time. The C method should set the C variable
-and return it in all cases, including when the variable has already been
-initialized.
+syntax for the first time; for instance, as in this case, we might need to
+initialize any injected dependency. The C method should set the C
+variable and return it in all cases, including when the variable has already
+been initialized; however, only in the first case we need to initialize the
+logger we are using in this example.
+
+The presence of the C flag can be also used to create immutable
+data structures:
+
+=begin code
+class A {
+    has @.foo handles ;
+    multi method STORE(*@!foo, :$INITIALIZE!) { }
+    multi method STORE(|) { die "Immutable" }
+}
+
+my @a is A = 1,2,3,4;
+say @a;        # OUTPUT: «[1,2,3,4]␤»
+@a = 4,5,6,7;  # dies: Immutable
+=end code
 
 =head2 Methods to implement for associative subscripting
 
diff --git a/doc/Language/syntax.pod6 b/doc/Language/syntax.pod6
index de4dda91e..120b858a0 100644
--- a/doc/Language/syntax.pod6
+++ b/doc/Language/syntax.pod6
@@ -7,8 +7,8 @@
 Raku borrows many concepts from human language. Which is not
 surprising, considering it was designed by a linguist.
 
-It reuses common elements in different contexts, has the notion of nouns
-(terms) and verbs (operators), is context-sensitive (in the every day
+It reuses common elements in different contexts; it has the notion of nouns
+(terms) and verbs (operators); it is context-sensitive (in the every day
 sense, not necessarily in the Computer Science interpretation), so a
 symbol can have a different meaning depending on whether a noun or a
 verb is expected.
@@ -57,14 +57,14 @@ or even
 if True {say "Hello"}
 =end code
 
-though you can't leave out any of the remaining whitespace.
+though you can't leave out any more whitespace in this last example.
 
 =head2 X
 X<|syntax,Unspace>
 
-In many places where the compiler would not allow a space you can use
+In places where the compiler would not allow a space you can use
 any amount of whitespace, as long as it is quoted with a backslash.
-Unspaces in tokens are not supported. Newlines that are unspaced still
+Unspaces in tokens, however, are not supported. Newlines that are unspaced still
 count when the compiler produces line numbers. Use cases for unspace are
 separation of postfix operators and routine argument lists.
 
@@ -174,11 +174,13 @@ if $age > 250 {     # catch obvious outliers
 }
 =end code
 
+X<|Embedded comments>
 =head3 Multi-line / embedded comments
 
 Multi-line and embedded comments start with a hash character, followed by a
 backtick, and then some opening bracketing character, and end with the matching
-closing bracketing character. Only the paired characters (), {}, [], and <> are
+closing bracketing character. Whitespace is not permitted between the backtick and the
+bracketing character; it will be treated as a single-line comment. Only the paired characters (), {}, [], and <> are
 valid for bounding comment blocks. (Unlike matches and substitutions, where pairs
 such as !!, || or @ may be used.) The content can not only span multiple lines,
 but can also be embedded inline.
@@ -199,10 +201,12 @@ That says why we do what we do below.
 say "No more";
 =end code
 
-Curly braces inside the comment can be nested, so in C<#`{ a { b } c }>,
-the comment goes until the very end of the string. You may also use multiple
-curly braces, such as C<#`{{ double-curly-brace }}>, which might help
-disambiguate from nested delimiters. You can embed these comments in
+Curly braces inside the comment can be nested, so in C<#`{ a { b } c }>, the
+comment goes until the very end of the string; this is why if the opening
+bracketing character also occurs in the body of the comment, e.g. C<#`[ This is a
+box [ of stuff ] ]>, it must have a paired closing character, as shown. You may
+also use multiple curly braces, such as C<#`{{ double-curly-brace }}>, which
+might help disambiguate from nested delimiters. You can embed these comments in
 expressions, as long as you don't insert them in the middle of keywords or
 identifiers.
 
@@ -1004,8 +1008,8 @@ on a single list of inputs, resulting in a single value.
     say [+] <1 2 3 4 5>;    # OUTPUT: «15␤»
     (((1 + 2) + 3) + 4) + 5 # equivalent expanded version
 
-Wrap an infix operator in C<« »> (or the ASCII equivalent C<<< >>>) to create a
-new hyper operator that works pairwise on two lists.
+Wrap an infix operator in C<« »> (or the ASCII equivalent C< << >> >) to
+create a new hyper operator that works pairwise on two lists.
 
     say <1 2 3> «+» <4 5 6> # OUTPUT: «(5 7 9)␤»
 
diff --git a/doc/Language/system.pod6 b/doc/Language/system.pod6
index 91ee69e6e..6aee44934 100644
--- a/doc/Language/system.pod6
+++ b/doc/Language/system.pod6
@@ -7,7 +7,7 @@
 =head1 Getting arguments through the command line
 
 The simplest way is to use the
-L|/language/variables#%24%2AARGS> variable to obtain
+L|/language/variables#%40%2AARGS> variable to obtain
 arguments from the command line; this array will contain the strings that follow
 the program name. L|/language/variables#Runtime_environment> will
 contain the environment variables, so that if you use:
diff --git a/doc/Language/temporal.pod6 b/doc/Language/temporal.pod6
index c36274c38..b195bfc18 100644
--- a/doc/Language/temporal.pod6
+++ b/doc/Language/temporal.pod6
@@ -8,10 +8,10 @@ X<|Date and time functions>
 
 Raku includes several classes that deal with temporal information: L, L, L and L. The three first are I, so they mix in the L role, which defines all methods and properties that classes that deal with date should assume. It also includes a class hierarchy of exceptions rooted in L.
 
-We will try to illustrate these classes in the next (somewhat extended) example, which can be used to process all files in a directory (by default C<.>) with a particular extension (by default C<.p6>) in a directory, sort them according to their age, and compute how many files have been created per month and how many were modified in certain periods expressed in ranges of months:
+We will try to illustrate these classes in the next (somewhat extended) example, which can be used to process all files in a directory (by default C<.>) with a particular extension (by default C<.raku>) in a directory, sort them according to their age, and compute how many files have been created per month and how many were modified in certain periods expressed in ranges of months:
 
 =begin code
-sub MAIN( $path = ".", $extension = "p6" ) {
+sub MAIN( $path = ".", $extension = "raku" ) {
     my DateTime $right = DateTime.now;
     my %metadata;
     my %files-month;
@@ -58,11 +58,11 @@ sub MAIN( $path = ".", $extension = "p6" ) {
 
 C is used in line 2 to contain the current date and time returned by L|/routine/now>.
 
-A CATCH phaser is declared in lines 7 to 11. Its main mission is to distinguish between C-related exceptions and other types. These kind of exception can arise from L or L. Barring some corruption of the file attributes, both are impossible, but in any case they should be caught and separated from other types of exceptions.
+A CATCH phaser is declared in lines 7 to 11. Its main mission is to distinguish between C-related exceptions and other types. These kinds of exception can arise from L or L. Barring some corruption of the file attributes, both are impossible, but in any case they should be caught and separated from other types of exceptions.
 
-We use Ls in lines 12-13 to represent the moment in which the files where accessed and modified. An Instant is measured in atomic seconds, and is a very low-level description of a time event; however, the L declared in line 14 represent the time transcurred among two different Cs, and we will be using it to represent the age.
+We use Ls in lines 12-13 to represent the moment in which the files where accessed and modified. An Instant is measured in atomic seconds and is a very low-level description of a time event; however, the L declared in line 14 represents the time transcurred among two different Cs and we will be using it to represent the age.
 
-For some variables we might be interested in dealing with them with some I traits. C<$time-of-day> contains the time of the day the file was changed; C will return an Instant, but it is converted into a Date (which is C while C is not) and then the time of day is extracted from that. C<$time-of-day> will have C< «Str+{Dateish}␤» > type.
+For some variables, we might be interested in dealing with them with some I traits. C<$time-of-day> contains the time of the day the file was changed; C will return an Instant, but it is converted into a Date (which is C while C is not) and then the time of day is extracted from that. C<$time-of-day> will have C< «Str+{Dateish}␤» > type.
 
 X<|Date ranges>
 We will use the date in this variable to find out the period when the files were changed.
diff --git a/doc/Language/testing.pod6 b/doc/Language/testing.pod6
index 8f6e11c8d..386909081 100644
--- a/doc/Language/testing.pod6
+++ b/doc/Language/testing.pod6
@@ -107,11 +107,37 @@ the C module:
     use Test;
     ...
 
+B Before Rakudo version 2020.05 the environment variable
+C was used to enable this feature, it is still
+supported but deprecated.
+
+Test timing in microseconds can be emitted by setting the
+C environmental variable:
+
+=for code :lang
+$ env RAKU_TEST_TIMES=1 raku -e 'use Test; plan 1; pass sleep(1);'
+1..1
+# between two timestamps 0 microseconds
+ok 1 -
+# t=1000721
+
+The same variable can be used within the test file. Set it before loading
+the C module:
+
+=for code
+BEGIN %*ENV = 1;
+use Test;
+...
+
+B Before Rakudo version 2020.05 the environment variable
+C was used to enable this feature, it is still
+supported but deprecated.
+
 =head1 Test plans
 
-Tests plans use L|/type/Test#plan> for declaring how many plans are
+Tests plans use L|/type/Test#sub_plan> for declaring how many plans are
 going to be done or, as might be the case, skipped. If no plan is declared,
-L|/type/Test#done-testing> is used to declare the end of the
+L|/type/Test#sub_done-testing> is used to declare the end of the
 tests.
 
 =head1 Testing return values
@@ -120,95 +146,95 @@ The C module exports various functions that check the return value of a
 given expression and produce standardized test output.
 
 In practice, the expression will often be a call to a function or method that
-you want to unit-test. L|/type/Test#ok> and L|/type/Test#nok> will
+you want to unit-test. L|/type/Test#sub_ok> and L|/type/Test#sub_nok> will
 match C and C. However, where possible it's better to use one of
 the specialized comparison test functions below, because they can print more
 helpful diagnostics output in case the comparison fails.
 
 =head2 By string comparison
 
-L|/type/Test#is> and L|/type/Test#isnt> test for equality using the
+L|/type/Test#sub_is> and L|/type/Test#sub_isnt> test for equality using the
 proper operator, depending on the object (or class) it's handled.
 
 =head2 By approximate numeric comparison
 
-L|/type/Test#is-approx> compares numbers with a certain precision,
+L|/type/Test#sub_is-approx> compares numbers with a certain precision,
 which can be absolute or relative. It can be useful for numeric values whose
 precision will depend on the internal representation.
 
 =head2 By structural comparison
 
-Structures can be also compared using L|/type/Test#is-deeply>,
+Structures can be also compared using L|/type/Test#sub_is-deeply>,
 which will check that internal structures of the objects compared is the same.
 
 =head2 By arbitrary comparison
 
-You can use any kind of comparison with L|/type/Test#cmp-ok>, which
+You can use any kind of comparison with L|/type/Test#sub_cmp-ok>, which
 takes as an argument the function or operator that you want to be used for
 comparing.
 
 =head2 By object type
 
-L|/type/Test#isa-ok> tests whether an object is of a certain type.
+L|/type/Test#sub_isa-ok> tests whether an object is of a certain type.
 
 
 =head2 By method name
 
-L|/type/Test#can-ok> is used on objects to check whether they have
+L|/type/Test#sub_can-ok> is used on objects to check whether they have
 that particular method.
 
 =head2 By role
 
 =item X
 
-L|/type/Test#does-ok> checks whether the given variable can do a
+L|/type/Test#sub_does-ok> checks whether the given variable can do a
 certain L.
 
 =head2 By regex
 
-L|/type/Test#like> and L|/type/Test#unlike> check using
+L|/type/Test#sub_like> and L|/type/Test#sub_unlike> check using
 regular expressions; in the first case passes if a match exists, in the second
 case when it does not.
 
 =head1 Testing modules
 
-Modules are tentatively loaded with L|/type/Test#use-ok>, which fails
+Modules are tentatively loaded with L|/type/Test#sub_use-ok>, which fails
 if they fail to load.
 
 =head1 Testing exceptions
 
-L|/type/Test#dies-ok> and L|/type/Test#lives-ok> are
+L|/type/Test#sub_dies-ok> and L|/type/Test#sub_lives-ok> are
 opposites ways of testing code; the first checks that it throws an exception,
-the second that it does not; L|/type/Test#throws-like> checks
+the second that it does not; L|/type/Test#sub_throws-like> checks
 that the code throws the specific exception it gets handed as an argument;
-L|/type/Test#fails-like>, similarly, checks if the code returns a
-specific type of L. L|/type/Test#eval-dies-ok> and
-L|/type/Test#eval-lives-ok> work similarly on strings that are
+L|/type/Test#sub_fails-like>, similarly, checks if the code returns a
+specific type of L. L|/type/Test#sub_eval-dies-ok> and
+L|/type/Test#sub_eval-lives-ok> work similarly on strings that are
 evaluated prior to testing.
 
 =head1 Grouping tests
 
 The result of a group of subtests is only C if all subtests are C; they
-are grouped using L|/type/Test#subtest>.
+are grouped using L|/type/Test#sub_subtest>.
 
 
 =head1 Skipping tests
 
 Sometimes tests just aren't ready to be run, for instance a feature might not
 yet be implemented, in which case tests can be marked as
-L|/type/Test#todo>. Or it could be the case that a given feature only
+L|/type/Test#sub_todo>. Or it could be the case that a given feature only
 works on a particular platform - in which case one would
-L|/type/Test#skip> the test on other platforms;
-L|/type/Test#skip-rest> will skip the remaining tests instead of a
-particular number given as argument; L|/type/Test#bail-out> will
+L|/type/Test#sub_skip> the test on other platforms;
+L|/type/Test#sub_skip-rest> will skip the remaining tests instead of a
+particular number given as argument; L|/type/Test#sub_bail-out> will
 simply exit the tests with a message.
 
 =head1 Manual control
 
 If the convenience functionality documented above does not suit your needs, you
 can use the following functions to manually direct the test harness output;
-L|/type/Test#pass> will say a test has passed, and
-L|/type/Test#diag> will print a (possibly) informative message.
+L|/type/Test#sub_pass> will say a test has passed, and
+L|/type/Test#sub_diag> will print a (possibly) informative message.
 
 =end pod
 
diff --git a/doc/Language/traps.pod6 b/doc/Language/traps.pod6
index 24847b86f..fd531324d 100644
--- a/doc/Language/traps.pod6
+++ b/doc/Language/traps.pod6
@@ -2,7 +2,7 @@
 
 =TITLE Traps to avoid
 
-=SUBTITLE Traps to avoid when getting started with Raku
+=SUBTITLE Traps to avoid when getting started with Raku™
 
 When learning a programming language, possibly with the background of
 being familiar with another programming language, there are always some
@@ -45,10 +45,10 @@ behavior similar to a constant, but allowing the value to get updated:
 unit module Something::Or::Other;
 my $config-file := "config.txt".IO.slurp;
 
-=head2 Assigning to C produces a different value, usually C
+=head2 Assignment of C can produce a different value, usually C
 
-Actually, assigning to C
-L. So:
+Actually, assignment of C to a variable
+L. For example,
 
 =begin code
 my @a = 4, 8, 15, 16;
@@ -79,7 +79,7 @@ my $result2 = 'abcdef' ~~ / dex /;
 say "Result2 is { $result2.^name }"; # OUTPUT: «Result2 is Any␤»
 =end code
 
-A L will be C|/language/regexes#Literals>
+A L will be C|/language/regexes#Match_syntax>
 if it finds nothing; however assigning C to C<$result2> above
 will result in its default value, which is C as shown.
 
@@ -429,13 +429,12 @@ below.
 
 In Raku, L are not lists of characters. One
 L over them or index into them as you
-can with L, despite the name of the L<.index
-routine|/type/Str#routine_index>.
+can with L, despite the name of the L<.index method|/type/Str#method_index>.
 
 =head2 Cs become strings, so beware C<.index()>ing
 
 L inherits from L, which provides access to
-L<.index|/type/Str#routine_index>. Because of the way C<.index>
+L<.index|/type/Str#method_index>. Because of the way C<.index>
 L a C into a L, this can
 sometimes appear to be returning the index of an element in the list, but
 that is not how the behavior is defined.
@@ -451,7 +450,7 @@ These same caveats apply to L<.rindex|/type/Str#routine_rindex>.
 
 =head2 Cs become strings, so beware C<.contains()>
 
-Similarly, L<.contains|/type/List#(Cool)_method_contains> does not look for
+Similarly, L<.contains|/type/Cool#method_contains> does not look for
 elements in the list.
 
 =for code
@@ -731,7 +730,7 @@ say %h{Dog}; # OUTPUT: «(Any)␤»
 =end code
 
 The C<:{ … }> syntax is used to create
-L. The
+L. The
 intentions of someone who wrote that code were to create a hash with
 Enum objects as keys (and C attempts to get a value using
 the Enum object to perform the lookup). However, that's not how pair
@@ -1581,7 +1580,7 @@ for 1..4 { say "$^a $^b $^c $^d"; }               # OUTPUT: «1 2 3 4␤»
 
 =head2 Using C<»> and C interchangeably
 
-While L<|/language/operators#index-entry-hyper_%3C%3C-hyper_%3E%3E-hyper_%C2%AB-hyper_%C2%BB-Hyper_Operators>>
+While L<|/language/operators#methodop_%C2%BB._/_methodop_%3E%3E.>>
 may look like a shorter way to write C, they differ in some key aspects.
 
 First, the C<»> includes a I to the compiler that it may
@@ -1771,14 +1770,24 @@ say foo rand; # OUTPUT: «Type check failed in binding to parameter ''; ex
 =head2 Using regexes within grammar's actions
 
 =begin code
+# Define a grammar
 grammar will-fail {
     token TOP {^  $}
     token word { \w+ }
 }
 
+# Define an action class
 class will-fail-actions {
-    method TOP ($/) { my $foo = ~$/; say $foo ~~ /foo/;  }
+    method TOP ($/) {      # <- note the $/ in the signature, which is readonly
+        my $foo = ~$/;
+        say $foo ~~ /foo/; # <- the regex tries to assign the result to $/ and will fail
+    }
 }
+
+# Try to parse something...
+will-fail.parse('word', :actions(will-fail-actions));
+CATCH { default { put .^name, ': ', .Str } };
+# OUTPUT: «X::AdHoc: Cannot assign to a readonly variable or a value␤»
 =end code
 
 Will fail with C
@@ -1921,8 +1930,8 @@ my @chunks = Blob.new;
 # …
 say [~] @chunks; # OUTPUT: «Blob:0x<>␤»
 
-
-Or you can utilize L|/language/operators#infix || > operator to
+http://localhost:30000/language/operators.html#
+Or you can utilize L|/language/operators#infix_%7C%7C > operator to
 make it use an empty Blob in case the list is empty:
 
 =for code
diff --git a/doc/Language/typesystem.pod6 b/doc/Language/typesystem.pod6
index 8cc8d9e46..4c0a3aa6e 100644
--- a/doc/Language/typesystem.pod6
+++ b/doc/Language/typesystem.pod6
@@ -10,7 +10,7 @@ A type defines a new object by creating a type object that provides an
 interface to create instances of objects or to check values against. Any type
 object is a subclass of L or L. Introspection
 methods are provided via inheritance from those base classes and the
-introspection postfix L<.^|/language/operators#postfix_.^>. A new type is
+introspection metamethod L<.^|/language/operators#methodop_.^>. A new type is
 introduced to the current scope by one of the following type declarators at
 compile time or with the L at runtime. All
 type names must be unique in their scope.
@@ -39,7 +39,7 @@ type constraint may change in this case.
 To test if an object is a type object, use
 L
 against a type constrained with a
-L or
+L or
 L«C<.DEFINITE>|/language/mop#index-entry-syntax_DEFINITE-DEFINITE» method:
 
 =begin code :ok-test
@@ -78,8 +78,8 @@ Values can become undefined at runtime via L, use
 L,
- L and
-L.
+ L and
+L.
 
 =head3 Coercion
 
@@ -448,7 +448,6 @@ L.
 
     class Correct {
         has $.attr is required;
-        submethod BUILD (:$attr) { $!attr = $attr }
     }
     say Correct.new(attr => 42);
     # OUTPUT: «Correct.new(attr => 42)␤»
@@ -460,6 +459,15 @@ L.
     CATCH { default { say .^name => .Str } }
     # OUTPUT: «X::Attribute::Required => The attribute '$!attr' is required, but you did not provide a value for it.␤»
 
+Note a class with a private attribute will give the same error:
+
+    class D {
+        has $!attr is required;
+    }
+    D.new;
+    CATCH { default { say .^name => .Str } }
+    # OUTPUT: «X::Attribute::Required => The attribute '$!attr' is required, but you did not provide a value for it.␤»
+
 You can provide a reason why it's required as an argument to C
 
 =for code :skip-test
@@ -511,7 +519,7 @@ C. A forward declaration of the trusted class may be required.
         trusts B;
         has $!foo;
         method !foo { return-rw $!foo }
-        method perl { "A.new(foo => $!foo)" }
+        method raku { "A.new(foo => $!foo)" }
     };
     class B {
         has A $.a .= new;
@@ -736,7 +744,7 @@ Attempting to access unicode enum keys without said syntax will result in an
 error:
 
 =for code :skip-test
-say ♣ ; # OUTPUT: «(exit code 1) ===SORRY!===␤Argument to "say" seems to be    malformed…
+say ♣ ; # OUTPUT: «(exit code 1) ===SORRY!===␤Argument to "say" seems to be malformed…
 
 If no value is given C will be assumed as the values type and incremented
 by one per key starting at zero. As enum key types C, C, C and
@@ -780,7 +788,16 @@ the keys.
     enum E ;
     my @keys = E::.values;
     say @keys.map: *.raku;
-    # OUTPUT: «(E::one E::two)␤»
+    # OUTPUT: «(E::one E::two)␤» or «(E::two E::one)␤»
+
+Note that, as the output above indicates, the iteration order of enums
+is not guaranteed.  This is because the methods that "iterate over" an
+enum do not iterate I on the enum (which, after all, is not
+iterable).  Instead, these iteration methods create a C with the
+same keys and values as the enum.  Because Cs provide only unordered,
+iteration the iteration methods on an enum do as well.  If you need to
+iterate an enum in order, you can sort on its C, for example
+with C.
 
 With the use of B<()> parentheses, an enum can be defined using any
 arbitrary dynamically defined list. The list should consist of Pair
@@ -852,17 +869,8 @@ against the C role.
 
 =head3 Methods
 
-=head4 method enums
-
-Defined as:
-
-    method enums()
-
-Returns the list of enum-pairs.
-
-    enum Mass ( mg => 1/1000, g => 1/1, kg => 1000/1 );
-    say Mass.enums; # OUTPUT: «{g => 1, kg => 1000, mg => 0.001}␤»
-
+See the L«C|/type/Enumeration» role for available methods on
+enum types and enum-pairs.
 
 =head3 Coercion
 
@@ -903,7 +911,7 @@ For a full explanation see L.
 =head2 C
 
 A X|subset> declares a new type that will re-dispatch to its base
-type. If a L|/type/Signature#where> clause is supplied any assignment
+type. If a L|/type/Signature#index-entry-where_clause> clause is supplied any assignment
 will be checked against the given code object.
 
     subset Positive of Int where * > -1;
@@ -920,6 +928,14 @@ Subsets can be used in signatures, e.g. by typing the output:
     a(1, "foo");  # passes
     a("foo", 1);  # fails
 
+If you skip the base type, it defaults to C. So the following two are equivalent:
+
+=for code :preamble
+subset A-or-B where * ~~ A | B
+
+=for code :preamble
+subset A-or-B of Any where * ~~ A | B
+
 Subsets can be anonymous, allowing inline placements where a subset is required
 but a name is neither needed nor desirable.
 
diff --git a/doc/Language/unicode_ascii.pod6 b/doc/Language/unicode_ascii.pod6
index 635e823fb..a8f295663 100644
--- a/doc/Language/unicode_ascii.pod6
+++ b/doc/Language/unicode_ascii.pod6
@@ -53,7 +53,7 @@ line), or C (Separator, paragraph) property.
 This list contains the single codepoints [and their ASCII
 equivalents] that have a special meaning in Raku.
 
-X<|«>X<|»>X<|×>X<|÷>X<|≤>X<|≥>X<|≠>X<|−>X<|∘>X<|≅>X<|π>X<|τ>X<|𝑒>X<|∞>X<|…>X<|‘>X<|’>X<|‚>X<|“>X<|”>X<|„>X<|「>X<|」>X<|⁺>X<|⁻>X<|¯>X<|⁰>X<|¹>X<|²>X<|³>X<|⁴>X<|⁵>X<|⁶>X<|⁷>X<|⁸>X<|⁹>X<|∈>X<|∉>X<|∋>X<|∌>X<|⊆>X<|⊈>X<|⊂>X<|⊄>X<|⊇>X<|⊉>X<|⊃>X<|⊅>X<|≼>X<|≽>X<|∪>X<|∩>X<|∖>X<|⊖>X<|⊍>X<|⊎>
+X<|«>X<|»>X<|×>X<|÷>X<|≤>X<|≥>X<|≠>X<|−>X<|∘>X<|≅>X<|π>X<|τ>X<|𝑒>X<|∞>X<|…>X<|‘>X<|’>X<|‚>X<|“>X<|”>X<|„>X<|「>X<|」>X<|⁺>X<|⁻>X<|¯>X<|⁰>X<|¹>X<|²>X<|³>X<|⁴>X<|⁵>X<|⁶>X<|⁷>X<|⁸>X<|⁹>X<|∈>X<|∉>X<|∋>X<|∌>X<|≡>X<|≢>X<|⊆>X<|⊈>X<|⊂>X<|⊄>X<|⊇>X<|⊉>X<|⊃>X<|⊅>X<|≼>X<|≽>X<|∪>X<|∩>X<|∖>X<|⊖>X<|⊍>X<|⊎>
 =table
   Symbol | Codepoint | ASCII      | Remarks
   =======|===========|============|=========================
@@ -98,6 +98,8 @@ X<|«>X<|»>X<|×>X<|÷>X<|≤>X<|≥>X<|≠>X<|−>X<|∘>X<|≅>X<|π>X<|τ>X<
   ∉      |  U+2209   | !(elem)    |
   ∋      |  U+220B   | (cont)     |
   ∌      |  U+220C   | !(cont)    |
+  ≡      |  U+2261   | (==)       |
+  ≢      |  U+2262   | !(==)      |
   ⊆      |  U+2286   | (<=)       |
   ⊈      |  U+2288   | !(<=)      |
   ⊂      |  U+2282   | (<)        |
diff --git a/doc/Language/unicode_entry.pod6 b/doc/Language/unicode_entry.pod6
index 77cbaf6d9..921b1690d 100644
--- a/doc/Language/unicode_entry.pod6
+++ b/doc/Language/unicode_entry.pod6
@@ -6,7 +6,7 @@
 
 Raku allows the use of unicode characters as variable names.  Many
 operators are defined with unicode symbols (in particular the L) as well as some quoting
+operators|/language/setbagmix#Operators_with_set_semantics>) as well as some quoting
 constructs.  Hence it is good to know how to enter these symbols into editors,
 the Raku shell and the command line, especially if the symbols aren't
 available as actual characters on a keyboard.
@@ -66,6 +66,211 @@ ibus-daemon --xim --verbose --daemonize --replace
 Setting C<--xim> should also allow programs not using ibus to still use the xim
 input method and be backward compatible.
 
+=head1 XKB (Linux)
+X<|Xkb>
+
+The X Window System receives keyboard events using the XKB extension, which makes it possible to read the output of various kinds of keyboards, provided that there's a configuration file available.
+
+XKB provides the concept of I or I.
+For example the symbol C is the output of the key marked as "A" at level 1; the symbol C belongs to the level 2 layout, which is normally reached using the shift key.
+There are more levels available; one can configure a certain key, let's say the right alt key (or AltGr), as a switch to a third level. The combination of the level-3 modifier and the shift key would switch to a fourth layout: level 4.
+XKB provides for the possibility to add a level 5 switch key which, used in combination with the shift key, would switch to a level 6 layout.
+
+For an in-depth explanation see L|https://www.x.org/wiki/XKB/> .
+
+The advantage of this method is that input of characters usually unreachable on a normal keyboard is as easy as pressing the combination of the shift plus another key to output an uppercase letter.
+
+=head2 Single-user configuration
+
+For a personal configuration it's enough to create a .xkb file and a symbol file in a C subdirectory.
+The .xkb file can be created with this command:
+
+=for code :lang
+setxkbmap -print > raku.xkb
+
+Here's an example of such a file:
+
+=for code :lang
+xkb_keymap {
+  xkb_keycodes  { include "evdev+aliases(qwerty)" };
+  xkb_types     { include "complete" };
+  xkb_compat    { include "complete" };
+  xkb_symbols   { include "pc+raku(raku)+inet(evdev)+level3(ralt_switch)+compose(caps)" };
+};
+
+This file declares the keycodes generated by the keyboard and the symbols produced on the screen.
+
+In this case there's a PC-type keyboard whose configuration is in the file C, which may contain several variants among which the chosen is the one named C. The L|https://en.wikipedia.org/wiki/Evdev> manages the event collection. This configuration uses the right Alt key as a third level switch and the Caps Lock as the Compose key.
+
+Once chosen the base directory for the configuration files (it might be C<$HOME/.config/xkb> for example) and put the raku.xkb in it, one has to create a I directory and put a key layout file in it.
+Here's an example of such a file, named C:
+
+=begin code :lang
+default  partial alphanumeric_keys modifier_keys
+xkb_symbols "basic" {
+
+    name[Group1]= "English (US)";
+
+    key  {  [     grave,  asciitilde  ]  };
+    key  {  [    1,  exclam     ]  };
+    key  {  [    2,  at    ]  };
+    key  {  [    3,  numbersign  ]  };
+    key  {  [    4,  dollar    ]  };
+    key  {  [    5,  percent    ]  };
+    key  {  [    6,  asciicircum  ]  };
+    key  {  [    7,  ampersand  ]  };
+    key  {  [    8,  asterisk  ]  };
+    key  {  [    9,  parenleft  ]  };
+    key  {  [    0,  parenright  ]  };
+    key  {  [     minus,  underscore  ]  };
+    key  {  [     equal,  plus    ]  };
+
+    key  {  [    q,  Q     ]  };
+    key  {  [    w,  W    ]  };
+    key  {  [    e,  E    ]  };
+    key  {  [    r,  R    ]  };
+    key  {  [    t,  T    ]  };
+    key  {  [    y,  Y    ]  };
+    key  {  [    u,  U    ]  };
+    key  {  [    i,  I    ]  };
+    key  {  [    o,  O    ]  };
+    key  {  [    p,  P    ]  };
+    key  {  [ bracketleft,  braceleft  ]  };
+    key  {  [ bracketright,  braceright  ]  };
+
+    key  {  [    a,  A     ]  };
+    key  {  [    s,  S    ]  };
+    key  {  [    d,  D    ]  };
+    key  {  [    f,  F    ]  };
+    key  {  [    g,  G    ]  };
+    key  {  [    h,  H    ]  };
+    key  {  [    j,  J    ]  };
+    key  {  [    k,  K    ]  };
+    key  {  [    l,  L    ]  };
+    key  {  [ semicolon,  colon    ]  };
+    key  {  [ apostrophe,  quotedbl  ]  };
+
+    key  {  [    z,  Z     ]  };
+    key  {  [    x,  X    ]  };
+    key  {  [    c,  C    ]  };
+    key  {  [    v,  V    ]  };
+    key  {  [    b,  B    ]  };
+    key  {  [    n,  N    ]  };
+    key  {  [    m,  M    ]  };
+    key  {  [     comma,  less    ]  };
+    key  {  [    period,  greater    ]  };
+    key  {  [     slash,  question  ]  };
+
+    key  {  [ backslash,         bar  ]  };
+};
+
+partial alphanumeric_keys
+xkb_symbols "raku" {
+
+   include "raku(basic)"
+   name[Group1]= "English (raku operators, with AltGr)";
+
+   key  { [     grave, asciitilde, dead_grave, leftsinglequotemark   ] }; //‘
+   key  { [         1,     exclam,      U00B9                        ] }; //¹
+   key  { [         2,         at,      U00B2                        ] }; //²
+   key  { [         3, numbersign,      U00B3,      U2026            ] }; //³…
+   key  { [         4,     dollar,      U2074                        ] }; //⁴
+   key  { [         5,    percent,      U2075                        ] }; //⁵
+   key  { [         6,asciicircum,      U2076                        ] }; //⁶
+   key  { [         7,  ampersand,      U2077                        ] }; //⁷
+   key  { [         8,   asterisk,      U2078,      multiply         ] }; //⁸×
+   key  { [         9,  parenleft,      U2079                        ] }; //⁹
+   key  { [         0, parenright,      U2070                        ] }; //⁰
+   key  { [     minus, underscore,      U2212,      U207B            ] }; //⁻−
+   key  { [     equal,       plus,      U2261,      U207A            ] }; //≡⁺
+   key  { [ backslash,        bar,      U2262,      U221E            ] }; //≢∞
+   key  { [         e,          E,   EuroSign,      U1D452           ] }; //€𝑒
+   key  { [         t,          T,      U03C4,      U2296            ] }; //τ⊖
+   key  { [         u,          U,      U222A,      U2229            ] }; //∪∩
+   key  { [         o,          O,      U2218                        ] }; //∘
+   key  { [         p,          P,      U03C0                        ] }; //π
+   key  { [ bracketleft,  braceleft,    U2260,      U201E            ] }; //≠„
+   key  { [ bracketright, braceright,   U2245,      U201A            ] }; //≅‚
+   key  { [         a,          A,      U2208,      U2209            ] }; //∈∉
+   key  { [         s,          S,      U220B,      U220C            ] }; //∋∌
+   key  { [         l,          L,      UFF62,      UFF63            ] }; //「」
+   key  { [ semicolon,      colon,      U201C,      U201D            ] }; //“”
+   key  { [apostrophe,   quotedbl,  rightsinglequotemark             ] }; //’
+   key  { [         x,          X,      U2284,      U2285            ] }; //⊄ ⊅
+   key  { [         c,          C,      U2283,      U2283            ] }; //⊂ ⊃
+   key  { [         b,          B,      U228E,      U228D            ] }; //⊎⊍
+   key  { [         n,          N,      U269B                        ] }; //⚛
+   key  { [     comma,       less,   guillemotleft, U2264            ] }; //«≤
+   key  { [    period,    greater,  guillemotright, U2265            ] }; //»≥
+   key  { [     slash,   question,   division,      U2216            ] }; //÷∖
+
+   include "level3(ralt_switch)"
+};
+=end code
+
+This file contains two layouts: the first is the basic layout of a US keyboard with just two shift levels, the second one includes the first and adds several Unicode symbols to some of the keys using two additional shift levels.
+The format of this file is documented L|https://www.x.org/releases/X11R7.5/doc/input/XKB-Enhancing.html>.
+
+For a different keyboard one needs to change the first layout, marked C, with the one pertaining to the specific national layout. Usually these layouts are located in the C directory. After that one has to modify the second layout to conform to the specific language key layout.
+
+If one's base directory is $HOME/.config/xkb, this command will load the new configuration:
+
+=for code :lang
+xkbcomp -I$HOME/.config/xkb $HOME/.config/xkb/raku.xkb $DISPLAY
+
+(There might be some warnings for symbols not defined)
+
+While this is a non-invasive method, one has to load manually the configuration file whenever is needed.
+
+=head2 System-wide configuration
+
+The advantage of this method is that since it modifies the system files, the user can choose the new layout using the usual interface provided by their desktop manager and make it permanent.
+
+The drawbacks are that one has to have root access to the system and that a system upgrade might overwrite one's layout file.
+
+To modify the system-wide configuration one has to locate the specific file describing their language mapping and add the C part shown in the previous section.
+
+In order for the new layout to show in the system menus one has to add a specific description in the C rule file, usually in C. Locate the section corresponding the one's language keyboard layout. For example the C layout starts like this:
+
+=for code :lang
+  […]
+  
+    
+      
+        us
+        
+        en
+        English (US)
+        
+          eng
+        
+      
+      
+        
+          
+          […]
+
+One has to add the newly defined variant:
+
+=for code :lang
+        
+          
+            raku
+            raku (Raku operators, with AltGr)
+            
+              eng
+            
+          
+        
+
+After logging out and in again, the new variant should appear in the list of the layouts and variants.
+Alternatively one can now load the layout with this command:
+
+=for code :lang
+setxkbmap -layout us -variant raku
+
+This actually reloads the C variant of the C keyboard, but unfortunately disables other keyboard layouts in case of multi-keyboard use.
+
 =head3 KDE
 
 If you are using KDE, open the start menu and type in “Autostart” and click B
@@ -76,6 +281,75 @@ ibus-daemon command as shown above, with the C<--desktop> option set to
 C<--desktop=plasma>. Click OK. It should now launch automatically when you
 log in again.
 
+=head3 How to enter Unicode characters using a two-key combination
+
+Using the XCompose input method it is possible to enter Unicode characters using simple two-key combinations.
+Here's an example of a configuration which would enable entering all the Unicode characters used by Raku.
+This example uses both Super keys as C. For example, to enter the C<π> symbol one has to press and
+release the right C (or "Windows") key, then press and release the C

key. + +=for code :lang + : "«" guillemotleft + : "»" guillemotright + : "⁻" U207B + <0> : "⁰" U2070 + <1> : "¹" U00B9 + <2> : "²" U00B2 + <3> : "³" U00B3 + <4> : "⁴" U2074 + <5> : "⁵" U2075 + <6> : "⁶" U2076 + <7> : "⁷" U2077 + <8> : "⁸" U2078 + <9> : "⁹" U2079 + : "×" U00D7 + : "÷" U00F7 + : "𝑒" U1D452 +

: "π" U03C0 + : "τ" U03C4 + : "‘" U2018 + : "’" U2019 + : "‚" U201A + : "“" U201C + : "”" U201D + : "„" U201E + : "…" U2026 + : "≡" U2261 + : "≢" U2262 + <8> : "∞" U221E + : "∅" U2205 + : "∈" U2208 + : "∉" U2209 + <3> : "∋" U220B + : "∌" U220C + : "−" U2212 + : "∖" U2216 + : "∘" U2218 + : "∩" U2229 + : "∪" U222A + : "≅" U2245 + : "≠" U2260 + : "≤" U2264 + : "≥" U2265 + : "⊂" U2283 + : "⊃" U2283 + : "⊄" U2284 + : "⊅" U2285 + : "⊆" U2286 + : "⊇" U2287 + : "⊈" U2288 + : "⊉" U2289 + : "⊍" U228D + : "⊎" U228E + : "⊖" U2296 + : "「" UFF62 + : "」" UFF63 + +One can add these lines to their ~/.XCompose file. To activate the changes one needs to exit their X session +and login back again. +Note that since Ubuntu Gnome uses one C key for its own purposes, one might want to substitute one or +both the Super_* keys with, for example, Meta_R. + =head1 WinCompose (Windows) X<|WinCompose> @@ -294,7 +568,7 @@ Thus constructs such as these are now possible: =head2 Set/bag operators -The L all +The L all have set-theory-related symbols, the unicode code points and their ascii equivalents are listed below. To compose such a character, it is merely necessary to enter the character composition chord (e.g. C in Vim; @@ -307,6 +581,8 @@ C in Bash) then the unicode code point hexadecimal number. ∉ U+2209 !(elem) ∋ U+220B (cont) ∌ U+220C !(cont) + ≡ U+2261 (==) + ≢ U+2262 !(==) ⊆ U+2286 (<=) ⊈ U+2288 !(<=) ⊂ U+2282 (<) diff --git a/doc/Language/variables.pod6 b/doc/Language/variables.pod6 index 6730b3a3c..de22ec498 100644 --- a/doc/Language/variables.pod6 +++ b/doc/Language/variables.pod6 @@ -19,13 +19,13 @@ associative-sigil C<%> and the callable-sigil C<&>. Sigils provide a link between syntax, the type system and L. They provide a shortcut for the most -common type constraints when declaring variables and serve as markers +common type constraints when declaring variables, and serve as markers for L. The L and the L -provide type constraint that enforce a base type -L require to know what +provide type constraint that enforce base type +L required to know what methods to dispatch to. The L does the same for function calls. The latter also tells the compiler where parentheses @@ -114,34 +114,34 @@ container (scalar-context) triggers item assignment, unless the Scalar is explicitly put in list-context by surrounding parentheses C<( )>: my $a; - $a = 1,2,3; # item assignment to Scalar - say $a; # OUTPUT: «1␤» ( '=' has higher precedence than ',' ) + $a = 1,2,3; # item assignment to Scalar + say $a; # OUTPUT: «1␤» ( '=' has higher precedence than ',' ) - my $b = 1,2,3; # item assignment to Scalar (same as preceding example) - say $b; # OUTPUT: «1␤» + my $b = 1,2,3; # item assignment to Scalar (same as preceding example) + say $b; # OUTPUT: «1␤» my $c; - ($c) = 4,5,6; # list assignment to Scalar; '( )' is list-contextualizer - say $c; # OUTPUT: «(4,5,6)␤» + ($c) = 4,5,6; # list assignment to Scalar; '( )' is list-contextualizer + say $c; # OUTPUT: «(4,5,6)␤» - (my $d) = 4,5,6; # list assignment to Scalar (same as preceding example) - say $d; # OUTPUT: «(4,5,6)␤» + (my $d) = 4,5,6; # list assignment to Scalar (same as preceding example) + say $d; # OUTPUT: «(4,5,6)␤» Assignment to a List container (list-context) always triggers list assignment: my @e; - @e = 7,8,9; # list assignment to Array - say @e; # OUTPUT: «[7,8,9]␤» + @e = 7,8,9; # list assignment to Array + say @e; # OUTPUT: «[7,8,9]␤» my $f; - ($f,) = 7,8,9; # list assignment to List with one element - say $f; # OUTPUT: «7␤» - say ( ($f,) ).VAR.^name; # OUTPUT: «List␤» + ($f,) = 7,8,9; # list assignment to List with one element + say $f; # OUTPUT: «7␤» + say ( ($f,) ).VAR.^name; # OUTPUT: «List␤» # ATTENTION: special declaration syntax! - my ($g) = 7,8,9; # list assignment to List with one element - say $g; # OUTPUT: «7␤» - say ( ($g) ).VAR.^name # OUTPUT: «List␤» + my ($g) = 7,8,9; # list assignment to List with one element + say $g; # OUTPUT: «7␤» + say ( ($g) ).VAR.^name # OUTPUT: «List␤» The last two examples above are simple I that select the first item of the right-hand side list. See for a more elaborate discussion @@ -219,10 +219,10 @@ See L for more information. =head1 Twigils X<|Twigil> -Twigils influence the scoping of a variable; however, they -have no influence over whether the primary sigil interpolates. That is, if -C<$a> interpolates, so do C<$^a>, C<$*a>, C<$=a>, C<$?a>, C<$.a>, etc. It -only depends on the C<$>. +We use the term twigils, a word play with I, that indicates it uses two +symbols in front of an identifier; the second symbol will be placed between +the sigil and the identifier, and it will be related to the scoping of a +variable, that is, where that variable is defined and can be changed. =begin table @@ -241,9 +241,9 @@ only depends on the C<$>. =end table -X<|$*> X<|Dynamically scoped variables> =head2 The C<*> twigil +X<|twigil,*>X<|twigil,$*>X<|twigil,@*>X<|twigil,%*>X<|twigil,&*> This twigil is used for dynamic variables which are looked up through the caller's, not through the outer, scope. Look at the example below.N are two orthogonal issues. =head2 The C twigil -X<|$?> +X<|twigil,?>X<|twigil,$?>X<|twigil,@?>X<|twigil,%?>X<|twigil,&?> Compile-time variables may be addressed via the C twigil. They are known to the compiler and may not be modified after being compiled in. A popular @@ -321,7 +321,7 @@ For a list of these special variables, see L. =head2 The C twigil -X<|$!> +X<|twigil,!>X<|twigil,$!>X<|twigil,@!>X<|twigil,%!>X<|twigil,&!> L are variables that exist per instance of a class. They may be directly accessed from within the class via C: @@ -344,7 +344,7 @@ L. =head2 The C<.> twigil -X<|$.> +X<|twigil,.>X<|twigil,$.>X<|twigil,@.>X<|twigil,%.>X<|twigil,&.> The C<.> twigil isn't really for variables at all. In fact, something along the lines of @@ -377,7 +377,8 @@ For more details on objects, classes and their attributes and methods see L. =head2 The C<^> twigil -X<|$^> +X<|twigil,^>X<|twigil,$^>X<|twigil,@^>X<|twigil,%^>X<|twigil,&^> + The C<^> twigil declares a formal positional parameter to blocks or subroutines; that is, variables of the form C<$^variable> are a type of placeholder variable. @@ -391,8 +392,7 @@ the block in the code has two formal parameters, namely C<$a> and C<$b>. Note that even though C<$^b> appears before C<$^a> in the code, C<$^a> is still the first formal parameter to that block. This is because the placeholder variables are sorted in Unicode -order. If you have self-declared a parameter using C<$^a> once, you may refer -to it using only C<$a> thereafter. +order. Although it is possible to use nearly any valid identifier as a placeholder variable, it is recommended to use short names or ones that can be trivially @@ -412,8 +412,14 @@ Placeholder variables cannot have type constraints or a variable name with a single upper-case letter (this is disallowed to enable catching some Perl-isms). +The C<^> twigil can be combined with any sigil to create a placeholder variable +with that sigil. The sigil will have its normal semantic effects, as described +in the L. Thus C<@^array>, C<%^hash>, and C<&^fun> are all +valid placeholder variables. + + =head2 The C<:> twigil -X<|$:> +X<|twigil,:>X<|twigil,$:>X<|twigil,@:>X<|twigil,%:>X<|twigil,&:> The C<:> twigil declares a formal named parameter to a block or subroutine. Variables declared using this form are a type of placeholder variable too. @@ -426,8 +432,37 @@ therefore not ordered using Unicode order). For instance: See L<^|/syntax/$CIRCUMFLEX_ACCENT> for more details about placeholder variables. +=head3 A note on C<^> and C<:> + +Unlike other twigils, C<^> and C<:> I variables, which can then be +referred to without that twigil. Thus, the previous example could be written as: + + say { $:add ?? $^a + $^b !! $a - $b }( 4, 5 ) :!add # OUTPUT: «-1␤» + +That is, once you have used C<$^a> to declare C<$a>, you can refer to that variable +in the same scope with I C<$^a> or C<$a>. The same is true for C<:>: after +declaring C<$:add>, you are free to refer to that declared variable with C<$add> if +you prefer. + +In some instances, this is just a convenience – but it can be much more significant +when dealing with nested blocks. For example: + + { say $^a; with "inner" { say $^a } }("outer"); # OUTPUT: «outer␤inner␤» + { say $^a; with "inner" { say $a } }("outer"); # OUTPUT: «outer␤outer␤» + +The first line declares I formal positional parameters, while the second declares +only one (but refers to it twice). This can be especially significant with constructs +such as C, C, and C that are often used without much consideration of +the fact that they create blocks. + +Just like the C<^>twigil, the C<:> twigil can be combined with any sigil; using +C<:> with a sigil will create a formal named parameter with that sigil (applying +the L). Thus C<@:array>, C<%:hash>, and +C<&:fun> are all valid, and each creates a formal named parameter with the +specified sigil. + =head2 The C<=> twigil -X<|$=> +X<|twigil,=>X<|twigil,$=>X<|twigil,@=>X<|twigil,%=>X<|twigil,&=> The C<=> twigil is used to access Pod variables. Every Pod block in the current file can be accessed via a Pod object, such as C<$=data>, @@ -451,7 +486,7 @@ Note that all those C<$=someBlockName> support the C and the C roles. =head2 The C<~> twigil -X<|$~> +X<|twigil,$~>X<|twigil,~> The C<~> twigil is for referring to sublanguages (called slangs). The following are useful: @@ -530,7 +565,7 @@ sentence surround the variables with parentheses: my ( $foo, $bar ); -see also L. +see also L. Additionally, lexical scoping means that variables can be temporarily redefined in a new scope: @@ -678,7 +713,7 @@ say $anon-class.new( :3bar).equal( $anon-class.new( :3bar ) ); =head2 The C declarator C declares lexically scoped variables, just like C. However, -initialization happens exactly once the first time the initialization +initialization happens exactly once, the first time the initialization is encountered in the normal flow of execution. Thus, state variables will retain their value across multiple executions of the enclosing block or routine. @@ -744,7 +779,7 @@ Use C<.clone> or coercion to create a new container that can be bound to. sub f() { state $i; $i++; - @a\ .push: "k$i" => $i; + @a .push: "k$i" => $i; @a-cloned.push: "k$i" => $i.clone; }; @@ -1058,33 +1093,43 @@ short. =head2 Pre-defined lexical variables -There are three special variables that are available in every block: +There are three special variables that are always available: =begin table - Variable Meaning + Variable Meaning Scope - $_ topic variable - $/ regex match - $! exceptions + $_ topic variable every block + $/ regex match every sub / method + $! exceptions every sub / method =end table X<|topic variable> =head3 The C<$_> variable -C<$_> is the topic variable. It's the default parameter for blocks that do not -have an explicit signature, so constructs like C and C bind the value or values of the variable to C<$_> by invoking the -block. +C<$_> is the topic variable. A fresh one is created in every B. +It's also the default parameter for blocks that do not have an explicit +signature, so constructs like C and C bind the value or values of the variable to C<$_> by invoking +the block. - for { say $_ } # sets $_ to 'a', 'b' and 'c' in turn + for { say $_ } # binds $_ to 'a', 'b' and 'c' in turn say $_ for ; # same, even though it's not a block - given 'a' { say $_ } # sets $_ to 'a' + given 'a' { say $_ } # binds $_ to 'a' say $_ given 'a'; # same, even though it's not a block -C blocks set C<$_> to the exception that was caught. The C<~~> -smartmatch operator sets C<$_> on the right-hand side expression to the +Because C<$_> is bound to the value of the iteration, you can also +assign to C<$_> if it is bound to something assignable. + + my @numbers = ^5; # 0 through 4 + $_++ for @numbers; # increment all elements of @numbers + say @numbers; + + # OUTPUT: «1 2 3 4 5␤» + +C blocks bind C<$_> to the exception that was caught. The C<~~> +smartmatch operator binds C<$_> on the right-hand side expression to the value of the left-hand side. Calling a method on C<$_> can be shortened by leaving off the variable name: @@ -1107,8 +1152,8 @@ work on C<$_>: X<|match variable> =head3 The C<$/> variable -C<$/> is the match variable. It stores the result of the last -L +C<$/> is the match variable. A fresh one is created in every B. +It is set to the result of the last L match and so usually contains objects of type L. 'abc 12' ~~ /\w+/; # sets $/ to a Match object @@ -1198,16 +1243,39 @@ parentheses). This behavior has been deprecated as of the 6.d version. +=head4 Thread-safety issues + +Because C<$/> is only defined per B, you are in fact +re-using the same C<$/> when you do matching in a loop. In a single +threaded program, this is not an issue. However, if you're going to +use C or C to have multiple threads do matching in +parallel, the sharing of the "outer" C<$/> becomes an issue, because +then it is being shared B threads! Fortunately, the solution +is very simple: define your own C<$/> inside the scope where you are +doing the matching. For example, taking a source of text, running +a regex on it, and map that to a hash using parallel execution: + +=begin code :preamble +my %mapped = @source.race.map: { + my $/; # need one in this block to prevent racing issues + m/foo (.*?) bar (.*)/; # matches on $_, stores in $/ + $0 => $1 # short for $/[0] / $/[1] +} +=end code + X<|error variable> =head3 The C<$!> variable -C<$!> is the error variable. If a C block or statement prefix catches -an exception, that exception is stored in C<$!>. If no exception was caught, -C<$!> is set to the C type object. +C<$!> is the error variable. A fresh one is created in every B. +If a C block or statement prefix catches an exception, that exception +is stored in C<$!>. If no exception was caught, C<$!> is set to C. Note that C blocks I set C<$!>. Rather, they set C<$_> inside the block to the caught exception. +Also note that the same thread-safety issues apply to the use of C<$!> as +they do to C<$/>. + X<|$?FILE>X<|$?LINE>X<|::?CLASS> =head2 Compile-time variables @@ -1261,6 +1329,7 @@ C file: ] =end code +X<|%?RESOURCES> Every resource file is added to an installed Distribution and is accessible using a C-like access to C<%?RESOURCES>, returning a C object: @@ -1328,10 +1397,28 @@ sub do-work { do-work; =end code +Note that, in a L, +C<&?ROUTINE> refers to the current candidate, I the C +as a whole. + +Thus, the following recursive definition does B work: + +=begin code +multi broken-fibonacci($n where * ≤ 1) { $n } +multi broken-fibonacci($n where * > 0) { + &?ROUTINE($n - 1) + &?ROUTINE($n - 2) +} +=end code + +If called, C<&?ROUTINE> would always refer to the second +multi candidate and would never dispatch to the first. If +you want to use self-recursion for the whole C, either +use the function name or L. + =head3 X<&?BLOCK> -The special compile variable C behaves similarly to -C but it allows to introspect a single block of code. +The special compile variable C<&?BLOCK> behaves similarly to +C<&?ROUTINE> but it allows to introspect a single block of code. It holds a L and allows for recursion within the same block: diff --git a/doc/Programs/01-debugging.pod6 b/doc/Programs/01-debugging.pod6 index 12716234d..fcd9d3643 100644 --- a/doc/Programs/01-debugging.pod6 +++ b/doc/Programs/01-debugging.pod6 @@ -74,7 +74,7 @@ a string: outer; # OUTPUT: - # perl6 /tmp/script.p6 + # raku /tmp/script.p6 # in sub inner at /tmp/script.p6 line 2 # in sub outer at /tmp/script.p6 line 3 # in block at /tmp/script.p6 line 4 @@ -100,7 +100,7 @@ Modules|https://modules.raku.org/> website for more modules like these. =head2 L|https://modules.raku.org/repo/Debugger::UI::CommandLine> A command-line debugger frontend for Rakudo. This module installs the -C command-line utility, and is bundled with the Rakudo +C command-line utility, and is bundled with the Rakudo Star distributions. Please check L for instructions and a tutorial. diff --git a/doc/Programs/03-environment-variables.pod6 b/doc/Programs/03-environment-variables.pod6 index e9b6f9422..7b74654f9 100644 --- a/doc/Programs/03-environment-variables.pod6 +++ b/doc/Programs/03-environment-variables.pod6 @@ -1,71 +1,10 @@ =begin pod :kind("Programs") :subkind("programs") :category("programs") -=TITLE Running Rakudo +=TITLE Environment variables used by the C command line =SUBTITLE How to run Rakudo, a Raku implementation, and modify its behavior with environment variables. -=head1 NAME - -raku - Rakudo Raku Compiler - -=head1 SYNOPSIS - -=for code :lang -raku [switches] [--] [programfile] [arguments] - -=head1 DESCRIPTION - -With no arguments, enters a REPL. With a C<[programfile]> or the C<-e> -option, compiles the given program and by default also executes the -compiled code. - -=begin code :lang --c check syntax only (runs BEGIN and CHECK blocks) ---doc extract documentation and print it as text --e program one line of program, strict is enabled by default --h, --help display this help text --n run program once for each line of input --p same as -n, but also print $_ at the end of lines --I path adds the path to the module search path --M module loads the module prior to running the program ---target=[stage] specify compilation stage to emit ---optimize=[level] use the given level of optimization (0..3) ---encoding=[mode] specify string encoding mode --o, --output=[name] specify name of output file --v, --version display version information ---stagestats display time spent in the compilation stages ---ll-exception display a low level backtrace on errors ---profile write profile information as HTML file (MoarVM) ---profile-filename provide a different filename (also allows .json) ---doc=[module] Use Pod::To::[module] to render inline documentation. ---full-cleanup try to free all memory and exit cleanly (MoarVM) ---debug-port=port listen for incoming debugger connections (MoarVM) ---debug-suspend pause execution at the entry point (MoarVM) ---tracing output a line to stderr on every interpreter instr (only - if enabled in MoarVM) -=end code - -Note that only boolean single-letter options may be bundled. - -The supported values for C<--target> are: - -=begin code :lang -Target Backend Description -====== ======= =========== -parse all a representation of the parse tree -ast all an abstract syntax tree (before optimizations) -optimize all an abstract syntax tree (after optimizations) - -mbc MoarVM MoarVM byte code -jar JVM JVM archive -=end code - -For C<--profile-filename>, specifying a name ending in C<.json> will write a raw -JSON profile dump. The default if this is omitted is C.html>. - -=head1 ENVIRONMENT VARIABLES - Rakudo's behavior can be tweaked by a (growing) number of environment variables; this section attempts to document all those currently in use. They are interpreter specific in all cases, except where some use conventional names @@ -78,7 +17,7 @@ page|https://github.com/rakudo/rakudo/wiki/dev-env-vars#moarvm>. =head2 Module loading X<|RAKUDOLIB>X<|RAKULIB>X<|PERL6LIB> -=item C, C (I; F) +=item C, C (I; B) C and C append a comma-delimited list of paths to the search list for modules. C is evaluated first. B These env @@ -86,7 +25,7 @@ vars were added in the Rakudo compiler in version 2020.05. The deprecated older env var C is still available. X<|RAKUDO_MODULE_DEBUG> -=item C (I; F) +=item C (I; B) If true, causes the module loader to print debugging information to standard error. @@ -106,32 +45,32 @@ as of version 2019.12, and before that it was available as C. X<|RAKUDO_NO_DEPRECATIONS> -=item C (I; F) +=item C (I; B) If true, suppresses deprecation warnings triggered by the C trait. X<|RAKUDO_DEPRECATIONS_FATAL> -=item C (I; F) +=item C (I; B) If true, deprecation warnings become thrown exceptions. X<|RAKUDO_VERBOSE_STACKFRAME> -=item C (I; F) +=item C (I; B) Displays source code in stack frames surrounded by the specified number of lines of context; for instance C will use one context line. X<|RAKUDO_BACKTRACE_SETTING> -=item C (I; F) +=item C (I; B) Controls whether C<.setting> files are included in backtraces. =head2 Affecting precompilation X<|RAKUDO_PREFIX> -=item C (I; F) +=item C (I; B) When this is set, Rakudo will look for the standard repositories (perl, vendor, site) in the specified directory. This is intended as an escape hatch for @@ -139,11 +78,11 @@ build-time bootstrapping issues, where Rakudo may be built as an unprivileged user without write access to the runtime paths in NQP's config. X<|RAKUDO_PRECOMP_DIST> -=item C (F) +=item C (B) X<|RAKUDO_PRECOMP_LOADING> -=item C (F) +=item C (B) X<|RAKUDO_PRECOMP_WITH> -=item C (F) +=item C (B) These are internal variables for passing serialized state to precompilation jobs in child processes. Please do not set them manually. @@ -187,19 +126,19 @@ L«C<$*DEFAULT-READ-ELEMS>|/language/variables#$*DEFAULT-READ-ELEMS» dynamic variable. X<|RAKUDO_ERROR_COLOR> -=item C (I; F) +=item C (I; B) Controls whether to emit ANSI codes for error highlighting. Defaults to true if unset, except on Windows. X<|RAKUDO_MAX_THREADS> -=item C (I; F) +=item C (I; B) Indicates the maximum number of threads used by default when creating a C. Defaults to 64. X<|TMPDIR>X<|TEMP>X<|TMP> -=item C, C, C (I; F) +=item C, C, C (I; B) The C method will return C<$TMPDIR> if it points to a directory with full access permissions for the current user, with a fallback @@ -209,7 +148,7 @@ C and C use more Windows-appropriate lists which also include the C<%TEMP%> and C<%TMP%> environment variables. X<|PATH> -=item C, C (I; F) +=item C, C (I; B) The C method splits C<$PATH> as a shell would; i.e. as a colon-separated list. C inherits this diff --git a/doc/Programs/04-running-raku.pod6 b/doc/Programs/04-running-raku.pod6 new file mode 100644 index 000000000..c183dcb7d --- /dev/null +++ b/doc/Programs/04-running-raku.pod6 @@ -0,0 +1,116 @@ +=begin pod :kind("Programs") :subkind("programs") :category("programs") + +=TITLE Running Raku + +=SUBTITLE How to run Rakudo, a Raku implementation, and the command line +options you can use with it. + +=head1 NAME + +raku - Rakudo Raku Compiler + +=head1 SYNOPSIS + +=for code :lang +raku [switches] [--] [programfile] [arguments] + +=head1 DESCRIPTION + +With no arguments, it enters a REPL. With a C<[programfile]> or the C<-e> +option, compiles the given program and by default also executes the +compiled code. + +=begin code :lang + - read program source from STDIN or start REPL if a TTY + -c check syntax only (runs BEGIN and CHECK blocks) + --doc extract documentation and print it as text + -e program one line of program, strict is enabled by default + -h, --help display this help text + -n run program once for each line of input + -p same as -n, but also print $_ at the end of lines + -I path adds the path to the module search path + -M module loads the module prior to running the program + --target=stage specify compilation stage to emit + --optimize=level use the given level of optimization (0..3) + --rakudo-home=path Override the path of the Rakudo runtime files + -o, --output=name specify name of output file + -v, --version display version information + -V print configuration summary + --stagestats display time spent in the compilation stages + --ll-exception display a low level backtrace on errors + --doc=module use Pod::To::[module] to render inline documentation + --repl-mode=interactive|non-interactive + when running without "-e" or filename arguments, + a REPL is started. By default, if STDIN is a TTY, + "interactive" REPL is started that shows extra messages and + prompts, otherwise a "non-interactive" mode is used where + STDIN is read entirely and evaluated as if it were a program, + without any extra output (in fact, no REPL machinery is even + loaded). This option allows to bypass TTY detection and + force one of the REPL modes. + --profile[=name] write profile information to a file + Extension controls format: + .json outputs in JSON + .sql outputs in SQL + any other extension outputs in HTML + --profile-compile[=name] + write compile-time profile information to a file + Extension controls format: + .json outputs in JSON + .sql outputs in SQL + any other extension outputs in HTML + --profile-kind[=name] + choose the type of profile to generate + instrumented - performance measurements (default) + heap - record heap snapshots after every garbage + collector run + --profile-filename=name + provide a different filename for profile. + Extension controls format: + .json outputs in JSON + .sql outputs in SQL + any other extension outputs in HTML + This option will go away in a future Rakudo release + --profile-stage=stage + write profile information for the given compilation + stage to a file. Use --profile-compile to set name + and format + --full-cleanup try to free all memory and exit cleanly + --debug-port=port listen for incoming debugger connections + --debug-suspend pause execution at the entry point + --tracing output a line to stderr on every interpreter instr (only if + enabled in MoarVM) +=end code + +Note that only Boolean single-letter options may be bundled. + +The supported values (stages) for C<--target> are: + +=begin code :lang +Target Backend Description +====== ======= =========== +parse all a representation of the parse tree +ast all an abstract syntax tree (before optimizations) +optimize all an abstract syntax tree (after optimizations) + +mbc MoarVM MoarVM byte code +jar JVM JVM archive +=end code + +For C<--profile-filename>, specifying a name ending in C<.json> will write a raw +JSON profile dump. The default if this is omitted is C.html>. + +Please check out the L to check for different ways to change the +behavior of the different layers of Raku. + +=head1 AUTHORS + +Written by the Rakudo contributors, see the CREDITS file. + +This manual page was written by Reini Urban, Moritz Lenz and the Rakudo +contributors. + +=end pod + +# vim: expandtab softtabstop=4 shiftwidth=4 ft=perl6 diff --git a/doc/Type/Allomorph.pod6 b/doc/Type/Allomorph.pod6 new file mode 100644 index 000000000..f16f19e88 --- /dev/null +++ b/doc/Type/Allomorph.pod6 @@ -0,0 +1,283 @@ +=begin pod :kind("Type") :subkind("class") :category("basic") + +=TITLE class Allomorph + +=SUBTITLE Dual value number and string + + class Allomorph is Str { } + +The C class is a common parent class for Raku's +dual value types: L«C|/type/ComplexStr», +L«C|/type/IntStr», L«C|/type/NumStr», +L«C|/type/RatStr». + +The dual value types (often referred to as +L) allow for the representation +of a value as both a string and a numeric type. Typically they will be +created for you when the context is "stringy" but they can be determined +to be numbers, such as in some L: + + my $c = <42+0i>; say $c.^name; # OUTPUT: «ComplexStr␤» + my $i = <42>; say $i.^name; # OUTPUT: «IntStr␤» + my $n = <42.1e0>; say $n.^name; # OUTPUT: «NumStr␤» + my $r = <42.1>; say $r.^name; # OUTPUT: «RatStr␤» + +As a subclass of both a L«C|/type/Numeric» class and +L«C|/type/Str», via the C class, an allomorph will be +accepted where either is expected. However, an allomorph does not share +object identity with its C parent class- or C-only variants: + +=begin code +my ($complex-str, $int-str, $num-str, $rat-str) + = < 42+0i 42 42e10 42.1 >; + +my (Complex $complex, Int $int, Num $num, Rat $rat) + = $complex-str, $int-str, $num-str, $rat-str; # OK! + +my Str @strings + = $complex-str, $int-str, $num-str, $rat-str; # OK! + +# ∈ operator cares about object identity +say 42+0i ∈ < 42+0i 42 42e10 42.1 >; # OUTPUT: «False␤» +say 42 ∈ < 42+0i 42 42e10 42.1 >; # OUTPUT: «False␤» +say 42e10 ∈ < 42+0i 42 42e10 42.1 >; # OUTPUT: «False␤» +say 42.1 ∈ < 42+0i 42 42e10 42.1 >; # OUTPUT: «False␤» +=end code + +Please see L for a more +complete description on how to work with these allomorphs. + +=head1 Methods + +=head2 method ACCEPTS + + multi method ACCEPTS(Allomorph:D: Any:D \a) + +If the C parameter is L (including +another L), +checks if invocant's L value +L C. +If the C parameter is L, checks if invocant's +L value L C. +If the C parameter is anything else, checks if both +L and L values of the invocant +C C. + + say "5.0" ~~ <5>; # OUTPUT: «False␤» + say 5.0 ~~ <5>; # OUTPUT: «True␤» + say <5.0> ~~ <5>; # OUTPUT: «True␤» + +=head2 method Bool + + multi method Bool(::?CLASS:D:) + +Returns C if the invocant is numerically C<0>, otherwise returns +C. The C value of the invocant is not considered. + +B: For the C subclass L«C|/type/RatStr» also +see L«C|/type/Rational#method_Bool». + +=head2 method chomp + + method chomp(Allomorph:D:) + +Calls L«C|/type/Str#routine_chomp» on the invocant's +C value. + +=head2 method chop + + method chop(Allomorph:D: |c) + +Calls L«C|/type/Str#routine_chop» on the invocant's +C value. + +=head2 method comb + + method comb(Allomorph:D: |c) + +Calls L«C|/type/Str#routine_comb» on the invocant's +C value. + +=head2 method fc + + method fc(Allomorph:D:) + +Calls L«C|/type/Str#routine_fc» on the invocant's +C value. + +=head2 method flip + + method flip(Allomorph:D:) + +Calls L«C|/type/Str#routine_flip» on the invocant's +C value. + +=head2 method lc + + method lc(Allomorph:D:) + +Calls L«C|/type/Str#routine_lc» on the invocant's +C value. + +=head2 method pred + + method pred(Allomorph:D:) + +Calls L«C|/type/Numeric#method_pred» on the invocant's +numeric value. + +=head2 method raku + + multi method raku(Allomorph:D:) + +Return a representation of the object that can be used via +L«C|/routine/EVAL» to reconstruct the value of the object. + +=head2 method samecase + + method samecase(Allomorph:D: |c) + +Calls L«C|/type/Str#method_samecase» on the invocant's +C value. + +=head2 method samemark + + method samemark(Allomorph:D: |c) + +Calls L«C|/type/Str#routine_samemark» on the invocant's +C value. + +=begin comment +=head2 method samespace + + method samespace(Allomorph:D: |c) + +See L +=end comment + +=head2 method split + + method split(Allomorph:D: |c) + +Calls L«C|/type/Str#routine_split» on the invocant's +C value. + +=head2 method Str + + method Str(Allomorph:D:) + +Returns the C value of the invocant. + +=head2 method subst + + method subst(Allomorph:D: |c) + +Calls L«C|/type/Str#method_subst» on the invocant's +C value. + +=head2 method subst-mutate + + method subst-mutate(Allomorph:D \SELF: |c) + +Calls L«C|/type/Str#method_subst-mutate» on the +invocant's C value. + +=head2 method substr + + method substr(Allomorph:D: |c) + +Calls L«C|/type/Str#method_substr» on the +invocant's C value. + +=head2 method substr-rw + + method substr-rw(Allomorph:D \SELF: $start = 0, $want = Whatever) + +Calls L«C|/type/Str#method_substr-rw» on the +invocant's C value. + +=head2 method succ + + method succ(Allomorph:D:) + +Calls L«C|/type/Numeric#method_succ» on the invocant's +numeric value. + +=head2 method tc + + method tc(Allomorph:D:) + +Calls L«C|/type/Str#routine_tc» on the invocant's C value. + +=head2 method tclc + + method tclc(Allomorph:D:) + +Calls L«C|/type/Str#routine_tclc» on the invocant's C +value. + +=head2 method trim + + method trim(Allomorph:D:) + +Calls L«C|/type/Str#method_trim» on the invocant's C +value. + +=head2 method trim-leading + + method trim-leading(Allomorph:D:) + +Calls L«C|/type/Str#method_trim-leading» on the +invocant's C value. + +=head2 method trim-trailing + + method trim-trailing(Allomorph:D:) + +Calls L«C|/type/Str#method_trim-trailing» on the +invocant's C value. + +=head2 method uc + + method uc(Allomorph:D:) + +Calls L«C|/type/Str#routine_uc» on the invocant's C value. + +=head2 method WHICH + + multi method WHICH(Allomorph:D:) + +Returns an object of type L«C|/type/ValueObjAt» which +uniquely identifies the object. + + my $f = <42.1e0>; + say $f.WHICH; # OUTPUT: «NumStr|Num|42.1|Str|42.1e0␤» + +=head1 Operators + +=head2 infix cmp + + multi sub infix:(Allomorph:D $a, Allomorph:D $b) + +Compare two C objects. The comparison is done on the +C value first and then on the C value. If you want to +compare in a different order then you would coerce to an C +or C value first: + + my $f = IntStr.new(42, "smaller"); + my $g = IntStr.new(43, "larger"); + say $f cmp $g; # OUTPUT: «Less␤» + say $f.Str cmp $g.Str; # OUTPUT: «More␤» + +=head2 infix eqv + + multi sub infix:(Allomorph:D $a, Allomorph:D $b --> Bool:D) + +Returns C if the two C C<$a> and C<$b> are of the same +type, their C values are L and their +C values are also L. Returns C +otherwise. + +=end pod + +# vim: expandtab softtabstop=4 shiftwidth=4 ft=perl6 diff --git a/doc/Type/Any.pod6 b/doc/Type/Any.pod6 index 8ad2d4dd1..6b69a92bc 100644 --- a/doc/Type/Any.pod6 +++ b/doc/Type/Any.pod6 @@ -84,9 +84,8 @@ L-L from it. Defined as: - multi method list(Any:U: --> List) - multi method list(Any:D \SELF: --> List) - + multi method list(Any:U:) + multi method list(Any:D \SELF:) Applies the infix L«C<,>|/routine/,» operator to the invocant and returns the resulting L: @@ -115,7 +114,7 @@ scalar in a list context by calling C<.list> and turning it into an C. Defined as: - method push(|values --> Positional:D) + multi method push(Any:U \SELF: |values --> Positional:D) The method push is defined for undefined invocants and allows for autovivifying undefined to an empty L, unless the undefined value @@ -162,6 +161,10 @@ Examples: say 'bca'.comb.sort({$^b cmp $^a}).join; # OUTPUT: «cba␤» say '231'.comb.sort(&infix:«<=>»).join; # OUTPUT: «123␤» + sub by-character-count { $^a.chars <=> $^b.chars } + say .sort(&by-character-count); + # OUTPUT: «(us we Let what have seen unto young impart Hamlet tonight)␤» + =head2 routine map Defined as: @@ -313,7 +316,8 @@ into lists of pairs. Note that L containerize their elements by default, and so C will not flatten them. You can use the -L to call the + +L to call the L«C<.List>|/routine/List» method on all the inner L and so de-containerize them, so that C can flatten them: @@ -322,7 +326,7 @@ and so de-containerize them, so that C can flatten them: For more fine-tuned options, see L, L, and -L +L =head2 method eager @@ -493,6 +497,14 @@ Defined as: Coerces the invocant to L. +=head2 method Seq + +Defined as: + + method Seq() is nodal + +Coerces the invocant to L. + =head2 method Bag Defined as: @@ -684,7 +696,7 @@ Defined as: B: This method is deprecated in 6.d and will be removed in 6.e. Use C<.map> followed by C<.flat> instead. -Applies L|/type/Any#method_map> to every element with the block and +Applies L|/type/Any#routine_map> to every element with the block and C and B: $*COLLATION.set(:quaternary(False), :tertiary(False)); - say 'a' coll 'A'; #OUTPUT: «Same␤» + say 'a' coll 'A'; # OUTPUT: «Same␤» say ('a','A').collate == ('A','a').collate; # OUTPUT: «True␤» The variable affects the L|/routine/coll> operator as shown as well as diff --git a/doc/Type/Array.pod6 b/doc/Type/Array.pod6 index 1d8f60daf..3297ceef6 100644 --- a/doc/Type/Array.pod6 +++ b/doc/Type/Array.pod6 @@ -15,6 +15,16 @@ L. B from version 6.d, C<.raku> (C<.perl> before version 2019.11) can be called on multi-dimensional arrays. +If you want to declare an C of a specific type, you can do so using +several different ways: + +=for code +my @foo of Int = 33,44; # [33 44] +my @bar is Array[Int] = 33,44; # [33 44] + +The second example, which parameterizes a type, is only available from Rakudo +2019.03. + =head1 Methods =head2 method gist @@ -22,16 +32,16 @@ called on multi-dimensional arrays. Exactly the same as L«C|/type/List#method_gist», except using square brackets for surrounding delimiters. -=head2 routine pop +=head2 method pop Defined as: - multi sub pop(Array:D ) - multi method pop(Array:D:) + method pop(Array:D:) is nodal -Removes and returns the last item from the array. Fails for an empty array. +Removes and returns the last item from the array. Fails if the array is empty. -Example: +Like many C methods, method C may be called via the corresponding +L. For example: my @foo = ; # a b @foo.pop; # b @@ -40,15 +50,18 @@ Example: CATCH { default { put .^name, ': ', .Str } }; # OUTPUT: «X::Cannot::Empty: Cannot pop from an empty Array␤» -=head2 routine push +=head2 method push Defined as: - multi sub push(Array:D, **@values --> Array:D) - multi method push(Array:D: **@values --> Array:D) + multi method push(Array:D: **@values is raw --> Array:D) + multi method push(Array:D: \value --> Array:D) + multi method push(Array:D: Slip \values --> Array:D) -Adds the C<@values> to the end of the array, and returns the modified array. -Throws for lazy arrays. +Adds the provided value or values to the end of the array, and returns the +modified array. If any argument is a C, method C will add the values +produced by the argument's L. It throws if the +invocant array or a C L. Example: @@ -65,35 +78,38 @@ an array or list as the thing to push, it becomes one additional element: say @a.elems; # OUTPUT: «4␤» say @a[3].join; # OUTPUT: «def␤» -Only if you supply multiple values as separate arguments to C are -multiple values added to the array: +Multiple values are added to the array only if you supply them as separate +arguments or in a L: my @a = '1'; - my @b = ; + say @a.push: 'a', 'b'; # OUTPUT: «[1 a b]␤» my @c = ; - @a.push: @b, @c; - say @a.elems; # OUTPUT: «3␤» + say @a.push: @c.Slip; # OUTPUT: «[1 a b E F]␤» -See L for when you want to append multiple -values that are stored in a single array. +See L if you want to append multiple +values that are produced by a single non-slipping C. -=head2 routine append +=head2 method append Defined as - sub append(\array, |elems) - multi method append(Array:D: \values) - multi method append(Array:D: **@values is raw) + multi method append(Array:D: **@values is raw --> Array:D) + multi method append(Array:D: \arg --> Array:D) -Appends the argument list to the array passed as the first argument. This -modifies the array in-place. Returns the modified array. Throws for lazy -arrays. +Adds the provided values to the end of the array and returns the modified array, +or throws if the invocant array or an argument that requires flattening L. -The difference from method C is that if you append a B array -or list argument, C will flatten that array / list, whereas C -appends the list / array as just a single element. +In contrast with L, method C +adheres to the L +and is probably best thought of as: -Example: + multi method append(Array:D: +values --> Array:D) + +This means that if you pass a B argument that is a +non-L C, C will try to flatten it. + +For example: my @a = ; my @b = ; @@ -157,17 +173,16 @@ array's underlying iterator. =for code my @a = ; -say @a.flat.^name; OUTPUT: «Seq␤» +say @a.flat.^name; # OUTPUT: «Seq␤» -=head2 routine shift +=head2 method shift Defined as: - multi sub shift(Array:D ) - multi method shift(Array:D:) + method shift(Array:D:) is nodal -Removes and returns the first item from the array. Fails for an empty arrays. +Removes and returns the first item from the array. Fails if the array is empty. Example: @@ -194,10 +209,10 @@ Example: @foo.unshift: 1, 3 ... 11; say @foo; # OUTPUT: «[(1 3 5 7 9 11) a b c]␤» -The notes in L apply, +The notes in L apply, regarding how many elements are added to the array. -The L is the equivalent for adding multiple elements from one +The L is the equivalent for adding multiple elements from one list or array. =head2 routine prepend @@ -331,7 +346,7 @@ say @a2[1]; # OUTPUT: «17␤» Defined as: - method of + method of() Returns the type constraint for the values of the invocant. By default, i.e. if no type constraint is given during declaration, the method diff --git a/doc/Type/Associative.pod6 b/doc/Type/Associative.pod6 index e6d71e346..5ac6a5fac 100644 --- a/doc/Type/Associative.pod6 +++ b/doc/Type/Associative.pod6 @@ -7,7 +7,7 @@ role Associative[::TValue = Mu, ::TKey = Str(Any)] { } A common role for types that support name-based lookup through -L«postcircumfix:<{ }>|/language/operators#postcircumfix_{_}», for example +L«postcircumfix:<{ }>|/language/operators#postcircumfix_{_}» such as L and L. It is used for type checks in operators that expect to find specific methods to call. See L @@ -23,7 +23,8 @@ my %whatever := Whatever.new; =end code Please note that we are using binding C<:=> here, since by default C<%> -assignments expect a C in the right-hand side. However, with the +assignments expect a C in the right-hand side, and thus assignment +would try and convert it to a hash (also failing). However, with the Associative role: class Whatever is Associative {}; @@ -39,14 +40,14 @@ Defined as: method of() -C is actually a +C, as the definition above shows, is actually a L which can use different classes for keys and values. As seen at the top of the -document, by default it coerces to C for the key and uses a very generic -C for value. +document, by default it coerces the key to C and uses a very +generic C for value. my %any-hash; - say %any-hash.of;# OUTPUT: «(Mu)␤» + say %any-hash.of; # OUTPUT: «(Mu)␤» The value is the first parameter you use when instantiating C with particular classes: @@ -66,12 +67,15 @@ coerced to C by default. This is the class used as second parameter when you use the parameterized version of Associative. my %any-hash; - %any-hash.keyof; #OUTPUT: «(Str(Any))␤» + %any-hash.keyof; # OUTPUT: «(Str(Any))␤» -=head1 Methods that should be provided +=head1 Methods that classes mixing Associative should provide You need to provide these methods if you want your class to implement the -Associative role. +Associative role properly and, thus, use the C<{}> operator for accessing the +value given a key. They are not mandatory, however; on the other hand, if you +simply want objects of a class to use C<{}>, you can implement them without +mixing the C role. =head2 method AT-KEY @@ -79,6 +83,10 @@ Associative role. Should return the value / container at the given key. +=for code +class What { method AT-KEY(\key) { 42 }}; +say What.new{33}; # OUTPUT: «42␤» + =head2 method EXISTS-KEY method EXISTS-KEY(\key) @@ -103,7 +111,8 @@ the object for the first time. Should return the invocant. =head1 See also -See L +See +L for information about additional methods that can be implemented for the C role. diff --git a/doc/Type/Blob.pod6 b/doc/Type/Blob.pod6 index 0aa7ce437..f73024b37 100644 --- a/doc/Type/Blob.pod6 +++ b/doc/Type/Blob.pod6 @@ -71,23 +71,19 @@ Defined as: method Capture(Blob:D:) -Equivalent to calling L«C<.List.Capture>|/type/List#method_Capture» -on the invocant. +Converts the object to a C which is, in turn, coerced to a C. =head2 method elems Defined as: multi method elems(Blob:D:) - multi method elems(Blob:U: --> 1) Returns the number of elements of the buffer. my $blob = Blob.new([1, 2, 3]); say $blob.elems; # OUTPUT: «3␤» -It will also return 1 on the class object. - =head2 method bytes Defined as: @@ -181,6 +177,11 @@ Defined as: multi method subbuf(Int $from, Int $len = self.elems --> Blob:D) multi method subbuf(Range $range --> Blob:D) + multi method subbuf(Blob:D: &From) + multi method subbuf(Blob:D: Int:D $From, &End) + multi method subbuf(Blob:D: &From, &End) + multi method subbuf(Blob:D: \from, Whatever) + multi method subbuf(Blob:D: \from, Numeric \length) Extracts a part of the invocant buffer, starting from the index with elements C<$from>, and taking C<$len> elements (or less if the buffer is diff --git a/doc/Type/Block.pod6 b/doc/Type/Block.pod6 index afa07222f..f79cb1ce9 100644 --- a/doc/Type/Block.pod6 +++ b/doc/Type/Block.pod6 @@ -19,7 +19,7 @@ will inherit the L if ther say $block('hello'); # OUTPUT: «HELLO␤» say {;}.signature; # OUTPUT: «(;; $_? is raw = OUTER::<$_>)␤» -A block can have a L between C<< -> >> or C<< <-> >> +A block can have a L«C|/type/Signature» between C<< -> >> or C<< <-> >> and the block: my $add = -> $a, $b = 2 { $a + $b }; @@ -34,8 +34,8 @@ X«|<->» $swap($a, $b); say $a; # OUTPUT: «4␤» -Blocks that aren't of type C (which is a subclass of C) are -transparent to L. +Blocks that aren't of type L«C|/type/Routine» (which is a subclass of C) are +transparent to L«C|/syntax/return». sub f() { say .map: { return 42 }; diff --git a/doc/Type/CallFrame.pod6 b/doc/Type/CallFrame.pod6 index e91378c32..27d6f9b85 100644 --- a/doc/Type/CallFrame.pod6 +++ b/doc/Type/CallFrame.pod6 @@ -23,7 +23,7 @@ negative number will move downward into the C method and class itself at the point at which they are running to construct this information for you. The frames themselves do not necessarily match only method or subroutine calls. -Perl constructs a frames for blocks and such as well, so if you need a callframe +Raku constructs a frames for blocks and such as well, so if you need a callframe for a particular method call, do not assume it is a fixed number of levels up. Each frame stores L, including the diff --git a/doc/Type/Callable.pod6 b/doc/Type/Callable.pod6 index e98c03641..afe621a07 100644 --- a/doc/Type/Callable.pod6 +++ b/doc/Type/Callable.pod6 @@ -34,7 +34,7 @@ This method is required for the L«C<( )> postcircumfix operator|/language/opera and the L«C<.( )> postcircumfix operator|/language/operators#index-entry-.(_)». It's what makes an object actually call-able and needs to be overloaded to let a given object act like a routine. If the object needs to be stored in a C<&>-sigiled -container, is has to implement Callable. +container, it has to implement Callable. class A does Callable { submethod CALL-ME(|c){ 'called' } diff --git a/doc/Type/Capture.pod6 b/doc/Type/Capture.pod6 index faf80eac1..8bd4738e4 100644 --- a/doc/Type/Capture.pod6 +++ b/doc/Type/Capture.pod6 @@ -17,7 +17,7 @@ For example when you call C, the C<$a, $b> part is a capture. Captures contain a list-like part for positional arguments and a hash-like part for named arguments, thus behaving as L and -L, although it does not actually mixes in those +L, although it does not actually mix in those roles. Like any other data structure, a stand-alone capture can be created, stored, and used later. @@ -68,8 +68,8 @@ arguments. You may re-use the capture as many times as you want, even with different subroutines. =for code :preamble - say greet |$d; # OUTPUT: «Mugen, 19␤» - say greet |$e; # OUTPUT: «Jin, 20␤» +say greet |$d; # OUTPUT: «Mugen, 19␤» +say greet |$e; # OUTPUT: «Jin, 20␤» my $x = \(4, 2, 3, -2); say reverse |$x; # OUTPUT: «(-2 3 2 4)␤» diff --git a/doc/Type/Channel.pod6 b/doc/Type/Channel.pod6 index f3298bad2..659fdf360 100644 --- a/doc/Type/Channel.pod6 +++ b/doc/Type/Channel.pod6 @@ -120,7 +120,7 @@ phaser to enforce the C<.close> call in this case. Defined as: - method list(Channel:D: --> List:D) + method list(Channel:D:) Returns a list based on the C which will iterate items in the queue and remove each item from it as it iterates. This can only terminate once the diff --git a/doc/Type/CompUnit.pod6 b/doc/Type/CompUnit.pod6 index 71b59c1cd..72de4eac8 100644 --- a/doc/Type/CompUnit.pod6 +++ b/doc/Type/CompUnit.pod6 @@ -31,7 +31,7 @@ created (if any). method from(--> Str:D) Returns the name of the language with which the C object was created -(if any). It will be C by default. +(if any). It will be C by default. =head2 method precompiled diff --git a/doc/Type/CompUnit/Repository/FileSystem.pod6 b/doc/Type/CompUnit/Repository/FileSystem.pod6 index d32d7a1cf..464b1ca09 100644 --- a/doc/Type/CompUnit/Repository/FileSystem.pod6 +++ b/doc/Type/CompUnit/Repository/FileSystem.pod6 @@ -61,12 +61,11 @@ matching C<$spec>. =head2 method need =for code :method :preamble - method need( - CompUnit::DependencySpecification $spec, - CompUnit::PrecompilationRepository $precomp = self.precomp-repository(), - CompUnit::PrecompilationStore :@precomp-stores = self!precomp-stores(), - --> CompUnit:D) - +method need( + CompUnit::DependencySpecification $spec, + CompUnit::PrecompilationRepository $precomp = self.precomp-repository(), + CompUnit::PrecompilationStore :@precomp-stores = self!precomp-stores(), + --> CompUnit:D) Loads and returns a L which is mapped to the highest version distribution matching C<$spec> from the first repository in the repository chain that contains diff --git a/doc/Type/Compiler.pod6 b/doc/Type/Compiler.pod6 index 05c0d8ca7..20edd0d93 100644 --- a/doc/Type/Compiler.pod6 +++ b/doc/Type/Compiler.pod6 @@ -45,7 +45,7 @@ Since Rakudo version 2020.02, returns the name of the compiler's backend. Up to Rakudo version 2019.03.1, it returned the date when it was built. - say $*PERL.compiler.build-date; #OUTPUT: «2018-05-05T21:49:43Z␤» + say $*PERL.compiler.build-date; # OUTPUT: «2018-05-05T21:49:43Z␤» =head2 method verbose-config diff --git a/doc/Type/Complex.pod6 b/doc/Type/Complex.pod6 index eb841cd78..7c5f301eb 100644 --- a/doc/Type/Complex.pod6 +++ b/doc/Type/Complex.pod6 @@ -187,11 +187,11 @@ Returns a string representation of the form "1+2i", without internal spaces. say (1-4i).gist; # OUTPUT: «1-4i␤» -=head2 method perl +=head2 method raku Defined as: - method perl(Complex:D: --> Str:D) + method raku(Complex:D: --> Str:D) Returns an implementation-specific string that produces an L object when given to L. diff --git a/doc/Type/ComplexStr.pod6 b/doc/Type/ComplexStr.pod6 index a2c1afa91..731ca57ed 100644 --- a/doc/Type/ComplexStr.pod6 +++ b/doc/Type/ComplexStr.pod6 @@ -4,24 +4,24 @@ =SUBTITLE Dual value complex number and string - class ComplexStr is Complex is Str {} + class ComplexStr is Allomorph is Complex {} -The dual value types (often referred to as L) -allow for the representation of a value as both a string and a numeric type. Typically -they will be created for you when the context is "stringy" but they can be determined -to be numbers, such as in some L: +C is a dual value type, a subclass of both +L«C|/type/Allomorph», hence L«C|/type/Str», and +L«C|/type/Complex». - my $f = <42+0i>; say $f.^name; # OUTPUT: «ComplexStr␤» +See L«C|/type/Allomorph» for further details. -As a subclass of both L«C|/type/Complex» and L«C|/type/Str», -a C will be accepted where either is expected. However, -C does not share object identity with C- or C-only -variants: +=begin code +my $complex-str = <42+0i>; +say $complex-str.^name; # OUTPUT: «ComplexStr␤» - my $complex-str = < 42+0i >; - my Complex $complex = $complex-str; # OK! - my Str $str = $complex-str; # OK! - say 42+0i ∈ <42+0i 55 1>; # False; ∈ operator cares about object identity +my Complex $complex = $complex-str; # OK! +my Str $str = $complex-str; # OK! + +# ∈ operator cares about object identity +say 42+0i ∈ <42+0i 55 1>; # OUTPUT: «False␤» +=end code =head1 Methods @@ -36,17 +36,6 @@ directly the values can be whatever is required: say +$f; # OUTPUT: «42+0i␤» say ~$f; # OUTPUT: «"forty two (but complicated)"␤» -=head2 method Bool - -Defined as: - - multi method Bool(ComplexStr:D: --> Bool:D) - -I. - -Returns C if the invocant is numerically C<±0±0i>, otherwise returns C. String portion -is not considered. - =head2 method Capture Defined as: @@ -85,41 +74,15 @@ coercion L with C. The C<:D> variant returns the result of that coercion. The C<:U> variant issues a warning about using an uninitialized value in numeric context and then returns value C<0e0>. -=head2 method Str - -Returns the string value of the C. - -=head2 method ACCEPTS - -Defined as: - - multi method ACCEPTS(ComplexStr:D: Any:D $value) - -If C<$value> is L (including another -L), checks if invocant's -L part L the C<$value>. -If C<$value> is L, checks if invocant's L part -L the C<$value>. If value is anything else, -checks if both L and L parts C the C<$value>. - - say < 5+0i> ~~ "5.0"; # OUTPUT: «False␤» - say < 5+0i> ~~ 5.0 ; # OUTPUT: «True␤» - say < 5+0i> ~~ <5.0>; # OUTPUT: «True␤» - =head1 Operators -=head2 infix cmp - - multi sub infix:(ComplexStr:D $a, ComplexStr:D $b) +=head2 infix C«===» -Compare two C objects. The comparison is done on the C value first and -then on the C value. If you want to compare in a different order then you would -coerce to the C or C values first: + multi sub infix:<===>(ComplexStr:D $a, ComplexStr:D $b) - my $f = ComplexStr.new(42+0i, "smaller"); - my $g = ComplexStr.new(43+0i, "larger"); - say $f cmp $g; # OUTPUT: «Less␤» - say $f.Str cmp $g.Str; # OUTPUT: «More␤» +C Value identity operator. Returns C if the C +values of C<$a> and C<$b> are L and their C +values are also L. Returns C otherwise. =end pod diff --git a/doc/Type/Cool.pod6 b/doc/Type/Cool.pod6 index 2ae75ad45..d5d42e964 100644 --- a/doc/Type/Cool.pod6 +++ b/doc/Type/Cool.pod6 @@ -112,6 +112,13 @@ what type they coerce to: chomp Str chop Str codes Str + Complex Numeric + FatRat Numeric + Int Numeric + Num Numeric + Rat Numeric + Real Numeric + UInt Numeric =end table @@ -143,7 +150,7 @@ imaginary part negated). say (1+2i).conj; # OUTPUT: «1-2i␤» -=head2 routine EVAL +=head2 method EVAL Defined as: @@ -578,14 +585,16 @@ Returns C if C<$base> is negative. Throws an exception if C<$base> is C<1>. Defined as: - multi sub log10(Cool(Numeric)) multi method log10() + multi sub log10(Numeric $x) + multi sub log10(Cool $x) -Coerces the invocant (or in the sub form, the invocant) to -L, and returns its -L to base 10, that is, a -number that approximately produces the original number when raised to the power -of 10. Returns C for negative arguments and C<-Inf> for C<0>. +Coerces the invocant (or in the sub form, the argument) to +L (or uses it directly if it's already in that form), and +returns its L in base 10, +that is, a number that approximately produces the original number when 10 is +raised to its power. Returns C for negative arguments and +C<-Inf> for C<0>. say log10(1001); # OUTPUT: «3.00043407747932␤» @@ -594,14 +603,19 @@ of 10. Returns C for negative arguments and C<-Inf> for C<0>. Defined as: multi method log2() + multi sub log2(Numeric $x) + multi sub log2(Cool $x) Coerces the invocant to L, and returns its -L to base 2, that is, a -number that approximately produces the original number when raised to the power -of 2. Returns C for negative arguments and C<-Inf> for C<0>. +L in base 2, that is, a +number that approximately (due to computer precision limitations) produces the +original number when 2 is raised to its power. Returns C for +negative +arguments and C<-Inf> for C<0>. say log2(5); # OUTPUT: «2.321928094887362␤» say "4".log2; # OUTPUT: «2␤» + say 4.log2; # OUTPUT: «2␤» =head2 routine exp @@ -634,15 +648,17 @@ the argument (i.e. the second argument in sub form) is the angle. The angle is a Defined as: - multi sub round(Numeric(Cool)) - multi method round(Cool:D: $unit = 1) + multi sub round(Numeric(Cool), $scale = 1) + multi method round(Cool:D: $scale = 1) Coerces the invocant (or in sub form, its argument) to L, and rounds it to the unit of -C<$unit>. If C<$unit> is 1, rounds to the nearest integer. +C<$scale>. If C<$scale> is 1, rounds to the nearest integer; an arbitrary scale will result in the closest +multiple of that number. say 1.7.round; # OUTPUT: «2␤» say 1.07.round(0.1); # OUTPUT: «1.1␤» say 21.round(10); # OUTPUT: «20␤» + say round(1000, 23.01) # OUTPUT: «989.43» Always rounds B if the number is at mid-point: @@ -955,13 +971,13 @@ accepts everything), this title-cases each word: With a matcher: - say "have fun working on perl".wordcase(:where({ .chars > 3 })); - # Have fun Working on Perl + say "have fun working on raku".wordcase(:where({ .chars > 3 })); + # Have fun Working on Raku With a customer filter too: - say "have fun working on perl".wordcase(:filter(&uc), :where({ .chars > 3 })); - # HAVE fun WORKING on PERL + say "have fun working on raku".wordcase(:filter(&uc), :where({ .chars > 3 })); + # HAVE fun WORKING on RAKU =head2 routine samecase @@ -970,18 +986,10 @@ Defined as: sub samecase(Cool $string, Cool $pattern) method samecase(Cool:D: Cool $pattern) -Coerces the invocant (or in sub form, the first argument) to L, -and returns a copy of C<$string> with case information for each individual -character changed according to C<$pattern>. +Coerces the invocant (or in sub form, the +first argument) to L, and calls +L«C|/type/Str#method_samecase» on it. -B: The pattern string can contain -three types of characters, i.e. uppercase, lowercase and caseless. For a given -character in C<$pattern> its case information determines the case of the -corresponding character in the result. - -If C<$string> is longer than -C<$pattern>, the case information from the last character of C<$pattern> is -applied to the remaining characters of C<$string>. say "raKu".samecase("A_a_"); # OUTPUT: «Raku␤» say "rAKU".samecase("Ab"); # OUTPUT: «Raku␤» @@ -1034,13 +1042,13 @@ codepoints, and L for the opposite direction. # Camelia in Unicode say ‘»ö«’.uniname; - # OUTPUT: «"RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK"␤» + # OUTPUT: «RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK␤» say "Ḍ̇".uniname; # Note, doesn't show "COMBINING DOT ABOVE" - # OUTPUT: «"LATIN CAPITAL LETTER D WITH DOT BELOW"␤» + # OUTPUT: «LATIN CAPITAL LETTER D WITH DOT BELOW␤» # Find the char with the longest Unicode name. say (0..0x1FFFF).sort(*.uniname.chars)[*-1].chr.uniname; - # OUTPUT: ««ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA INITIAL FORM␤»␤» + # OUTPUT: «BOX DRAWINGS LIGHT DIAGONAL UPPER CENTRE TO MIDDLE RIGHT AND MIDDLE LEFT TO LOWER CENTRE␤» =head2 routine uninames @@ -1068,7 +1076,7 @@ See L for the opposite direction. Defined as: multi sub unimatch(Str:D $str, |c) - multi unimatch(Int:D $code, Stringy:D $pvalname, Stringy:D $propname = $pvalname) + multi sub unimatch(Int:D $code, Stringy:D $pvalname, Stringy:D $propname = $pvalname) Checks if the given integer codepoint or the first letter of the given string has a unicode property equal to the value you give. If you supply the Unicode @@ -1092,7 +1100,7 @@ Defined as: Coerces the invocant (or in sub form, its argument) to L, and returns it with the last character removed. - say 'perl'.chop; # OUTPUT: «per␤» + say 'raku'.chop; # OUTPUT: «rak␤» =head2 routine chomp @@ -1126,7 +1134,7 @@ Defined as: multi sub substr-rw(|) is rw Coerces the invocant (or in the sub form, the first argument) to -L, and calls L with +L, and calls L with the arguments. =head2 routine ords @@ -1176,23 +1184,23 @@ N routine is a much better choice for many tasks th languages are handled by the C.»> Coerces the invocant (or in the sub form, the second argument) to -L, and splits it into pieces based on delimiters found in the -string. +L, splits it into pieces based on delimiters found in the +string and returns the result as a L«C|/type/Seq». If C<$delimiter> is a string, it is searched for literally and not treated as a regex. You can also provide multiple delimiters by specifying them as a -list; mixing Cool and Regex objects is OK. +list, which can mix C and C objects. - say split(';', "a;b;c").raku; # OUTPUT: «("a", "b", "c")␤» + say split(';', "a;b;c").raku; # OUTPUT: «("a", "b", "c").Seq␤» say split(';', "a;b;c", 2).raku; # OUTPUT: «("a", "b;c").Seq␤» - say split(';', "a;b;c,d").raku; # OUTPUT: «("a", "b", "c,d")␤» - say split(/\;/, "a;b;c,d").raku; # OUTPUT: «("a", "b", "c,d")␤» - say split(/<[;,]>/, "a;b;c,d").raku; # OUTPUT: «("a", "b", "c", "d")␤» + say split(';', "a;b;c,d").raku; # OUTPUT: «("a", "b", "c,d").Seq␤» + say split(/\;/, "a;b;c,d").raku; # OUTPUT: «("a", "b", "c,d").Seq␤» + say split(/<[;,]>/, "a;b;c,d").raku; # OUTPUT: «("a", "b", "c", "d").Seq␤» - say split(['a', /b+/, 4], '1a2bb345').raku; # OUTPUT: «("1", "2", "3", "5")␤» + say split(['a', /b+/, 4], '1a2bb345').raku; # OUTPUT: «("1", "2", "3", "5").Seq␤» -By default, split omits the matches, and returns a list of only those parts of +By default, C omits the matches, and returns a list of only those parts of the string that did not match. Specifying one of the C<:k, :v, :kv, :p> adverbs changes that. Think of the matches as a list that is interleaved with the non-matching parts. @@ -1227,8 +1235,8 @@ to C. Note that empty chunks are not removed from the result list. For that behavior, use the C<:skip-empty> named argument: - say ("f,,b,c,d".split: /","/ ).raku; # OUTPUT: «("f", "", "b", "c", "d")␤» - say ("f,,b,c,d".split: /","/, :skip-empty).raku; # OUTPUT: «("f", "b", "c", "d")␤» + say ("f,,b,c,d".split: /","/ ).raku; # OUTPUT: «("f", "", "b", "c", "d").Seq␤» + say ("f,,b,c,d".split: /","/, :skip-empty).raku; # OUTPUT: «("f", "b", "c", "d").Seq␤» =head2 routine lines @@ -1245,8 +1253,9 @@ the list of lines. say "some\nmore\nlines".lines.elems; # OUTPUT: «3␤» -This method can be used as part of an C to process a file -line-by-line, since C objects inherit from C, e.g.: +This method can be used as part of an L«C|/type/IO::Path» +to process a file line-by-line, since C objects inherit from +C, e.g.: =begin code for 'huge-csv'.IO.lines -> $line { @@ -1258,9 +1267,11 @@ my @lines = 'huge-csv'.IO.lines; =end code Without any arguments, sub C operates on -C<$*ARGFILES>, which defaults to C<$*IN> in the absence of any filenames. +L«C<$*ARGFILES>|/language/variables#$*ARGFILES». -To modify values in place use C to force a writable container. +To modify values in place use L«C|/type/Signature#index-entry-trait_is_copy» to force a writable +container. =for code for $*IN.lines -> $_ is copy { s/(\w+)/{$0 ~ $0}/; .say } @@ -1378,7 +1389,7 @@ a L, and searches for C<$needle> in the string C<$s> starting from C<$pos>. It returns the offset into the string where C<$needle> was found, and C if it was not found. -See L for examples. +See L for examples. =head2 routine rindex @@ -1463,6 +1474,143 @@ Coerces the invocant to L. =for code .say for '.'.IO.dir; # gives a directory listing +=head2 method sprintf + +Defined as: + + method sprintf(*@args) + +Returns a string according to a series L that are common in many languages; +the object will be the format string, while the supplied arguments will be +what's going to be formatted according to it. + +=for code +"% 6s".sprintf('Þor').say; # OUTPUT: « Þor␤» + +=head2 method printf + +Defined as: + + method printf(*@args) + +Uses the object, as long as it is a L, to format and print the arguments + +=for code +"%.8f".printf(now - now ); # OUTPUT: «-0.00004118» + +=head2 method Complex + +Defined as: + + multi method Complex() + +Coerces the invocant to a L«C|/type/Numeric» and calls its +L«C<.Complex>|/routine/Complex» method. L if the +coercion to a C cannot be done. + + say 1+1i.Complex; # OUTPUT: «1+1i␤» + say π.Complex; # OUTPUT: «3.141592653589793+0i␤» + say <1.3>.Complex; # OUTPUT: «1.3+0i␤» + say (-4/3).Complex; # OUTPUT: «-1.3333333333333333+0i␤» + say "foo".Complex.^name; # OUTPUT: «Failure␤» + +=head2 method FatRat + +Defined as: + + multi method FatRat() + +Coerces the invocant to a L«C|/type/Numeric» and calls its +L«C<.FatRat>|/routine/FatRat» method. L if the +coercion to a C cannot be done. + + say 1+0i.FatRat; # OUTPUT: «1␤» + say 2e1.FatRat; # OUTPUT: «20␤» + say 1.3.FatRat; # OUTPUT: «1.3␤» + say (-4/3).FatRat; # OUTPUT: «-1.333333␤» + say "foo".FatRat.^name; # OUTPUT: «Failure␤» + +=head2 method Int + +Defined as: + + multi method Int() + +Coerces the invocant to a L«C|/type/Numeric» and calls its +L«C<.Int>|/routine/Int» method. L if the +coercion to a C cannot be done. + + say 1+0i.Int; # OUTPUT: «1␤» + say <2e1>.Int; # OUTPUT: «20␤» + say 1.3.Int; # OUTPUT: «1␤» + say (-4/3).Int; # OUTPUT: «-1␤» + say "foo".Int.^name; # OUTPUT: «Failure␤» + +=head2 method Num + +Defined as: + + multi method Num() + +Coerces the invocant to a L«C|/type/Numeric» and calls its +L«C<.Num>|/routine/Num» method. L if the +coercion to a C cannot be done. + + say 1+0i.Num; # OUTPUT: «1␤» + say 2e1.Num; # OUTPUT: «20␤» + say (16/9)².Num; # OUTPUT: «3.1604938271604937␤» + say (-4/3).Num; # OUTPUT: «-1.3333333333333333␤» + say "foo".Num.^name; # OUTPUT: «Failure␤» + +=head2 method Rat + +Defined as: + + multi method Rat() + +Coerces the invocant to a L«C|/type/Numeric» and calls its +L«C<.Rat>|/routine/Rat» method. L if the +coercion to a C cannot be done. + + say 1+0i.Rat; # OUTPUT: «1␤» + say 2e1.Rat; # OUTPUT: «20␤» + say (-4/3).Rat; # OUTPUT: «-1.333333␤» + say "foo".Rat.^name; # OUTPUT: «Failure␤» + say (.numerator, .denominator) for π.Rat; # OUTPUT: «(355 113)␤» + +=head2 method Real + +Defined as: + + multi method Real() + +Coerces the invocant to a L«C|/type/Numeric» and calls its +L«C<.Real>|/routine/Real» method. L if the +coercion to a C cannot be done. + + say 1+0i.Real; # OUTPUT: «1␤» + say 2e1.Real; # OUTPUT: «20␤» + say 1.3.Real; # OUTPUT: «1.3␤» + say (-4/3).Real; # OUTPUT: «-1.333333␤» + say "foo".Real.^name; # OUTPUT: «Failure␤» + +=head2 method UInt + +Defined as: + + multi method UInt() + +Coerces the invocant to an L«C|/type/Int». L +if the coercion to an C cannot be done or if the C the invocant +had been coerced to is negative. + + say 1+0i.UInt; # OUTPUT: «1␤» + say 2e1.UInt; # OUTPUT: «20␤» + say 1.3.UInt; # OUTPUT: «1␤» + say (-4/3).UInt.^name; # OUTPUT: «Failure␤» + say "foo".UInt.^name; # OUTPUT: «Failure␤» =end pod diff --git a/doc/Type/Date.pod6 b/doc/Type/Date.pod6 index cf905bb55..a84e49886 100644 --- a/doc/Type/Date.pod6 +++ b/doc/Type/Date.pod6 @@ -28,7 +28,7 @@ an object the current day according to the system clock. say $n - $d; # OUTPUT: «7␤», 7 days between New Years/Christmas Eve say $n + 1; # OUTPUT: «2016-01-01␤» -B since version 6.d, .perl can be called on C. It will also +B since version 6.d, .raku can be called on C. It will also reject synthetic numerics such as 7̈ . =head1 Methods @@ -81,7 +81,7 @@ the invocant if the day value is already the last day of the month. This should allow for much easier ranges like =for code :preamble - $date .. $date.last-date-in-month +$date .. $date.last-date-in-month for all remaining dates in the month. @@ -118,48 +118,6 @@ formatter named parameter. say Date.today; -=head2 method later - -Defined as: - - method later(Date:D: *%unit) - -Returns a C object based on the current one, but with a date delta -applied. The date delta can be passed as a named argument where the argument -name is the unit. - -Allowed units are C, C, C, C, C, C, -C, C. Please note that the plural forms can only be used with -the C method. - -Please note that the special ":2nd" named parameter syntax can be a compact -and self-documenting way of specifying the delta - - say Date.new('2015-12-24').later(:2years); # OUTPUT: «2017-12-24␤» - -Since addition of several different time units is not commutative, only one -unit may be passed. - - my $d = Date.new('2015-02-27'); - say $d.later(month => 1).later(:2days); # OUTPUT: «2015-03-29␤» - say $d.later(days => 2).later(:1month); # OUTPUT: «2015-04-01␤» - say $d.later(days => 2).later(:month); # same, as +True === 1 - -Negative offsets are allowed, though L<#method earlier> is more idiomatic for -that. - -=head2 method earlier - -Defined as: - - method earlier(Date:D: *%unit) - -Returns a C object based on the current one, but with a date delta -towards the past applied. See L<#method later> for usage. - - my $d = Date.new('2015-02-27'); - say $d.earlier(month => 5).earlier(:2days); # OUTPUT: «2014-09-25␤» - =head2 method truncated-to Defined as: diff --git a/doc/Type/DateTime.pod6 b/doc/Type/DateTime.pod6 index 38bee9d8c..702f79b5a 100644 --- a/doc/Type/DateTime.pod6 +++ b/doc/Type/DateTime.pod6 @@ -10,7 +10,7 @@ For handling points in civil time, a C object stores year, month, day, hour, minute (all L), second (potentially fractional) and a time zone. -It provides methods for calculating with date and time. +It provides methods for calculating with date (for the Gregorian calendar) and time. C methods are immutable; if you are tempted to modify one, create a modified copy instead. @@ -56,7 +56,7 @@ multi method new(Int() $year, Int() $month, Int() $day, Int() $hour, Int $minute, $second, Int() :$timezone = 0, :&formatter) multi method new(Instant:D $i, :$timezone=0, :&formatter) -multi method new(Int:D $posix, :$timezone=0, :&formatter) +multi method new(Numeric:D $posix, :$timezone=0, :&formatter) multi method new(Str:D $format, :$timezone=0, :&formatter) Creates a new C object. One option for creating a new DateTime object @@ -64,7 +64,7 @@ is from the components (year, month, day, hour, ...) separately. Another is to pass a L object for the date component, and specify the time component-wise. Yet another is to obtain the time from an L, and only supply the time zone and formatter. Or -instead of an Instant you can supply an L as a UNIX timestamp. +instead of an Instant you can supply an L as a UNIX timestamp. You can also supply a L formatted in ISO 8601 timestamp notation or as a full L @@ -94,7 +94,7 @@ L is thrown. 1, 1, 1); # Hour, minute, second with default time zone $datetime = DateTime.new(now); # Instant. # from a Unix timestamp - say $datetime = DateTime.new(1470853583); # OUTPUT: «2016-08-10T18:26:23Z␤» + say $datetime = DateTime.new(1470853583.3); # OUTPUT: «2016-08-10T18:26:23.300000Z␤» $datetime = DateTime.new("2015-01-01T03:17:30+0500") # Formatted string =head2 method now @@ -252,83 +252,66 @@ Returns an L object based on the invocant. say DateTime.new('2015-12-24T12:23:00+0200').Instant; # OUTPUT: «Instant:1450952616␤» -=head2 method posix +=head2 method day-fraction Defined as: - method posix(Bool:D: $ignore-timezone = False --> Int:D) + method day-fraction(DateTime:D: --> Real:D) -Returns the date and time as a POSIX/UNIX timestamp (seconds since the Epoch, -1st January 1970 UTC). +Returns the instant's time as a fraction of a 24-hour day. -If C<$ignore-timezone> is C, the C object will be treated as if -the time zone offset is zero. + say DateTime.new('2021-12-24T12:23:00.43Z').day-fraction; # OUTPUT: «0.5159772␤» -=for code -say DateTime.new('2015-12-24T12:23:00Z').posix; # OUTPUT: «1450959780␤» +Notice the C value is the same as the fractional part of +the C for the same instant. -=head2 method later +=head2 method julian-date Defined as: - method later(DateTime:D: *%unit) + method julian-date(DateTime:D: --> Real:D) -Returns a DateTime object based on the current one, but with a time delta -applied. The time delta can be passed as a named argument where the argument -name is the unit. +Returns the L (JD) for the UTC date and time. -Unless the given unit is C or C, the given value will be -converted to an L. + say DateTime.new('2021-12-24T12:23:00.43Z').julian-date; # OUTPUT: «2459573.0159772␤» -Allowed units are C, C, C, C, C, -C, C, C, C, C, C, C, C, -C. Please note that the plural forms can only be used with -the C and C methods. +The C starts at zero at the epoch of noon UTC on +I on the L Gregorian calendar (the calendar +in use in much of the world and in international commerce and travel). The JD +is used in astronomy to define times of celestial objects transiting the +Earth's Prime Meridian. For any instant, it is the sum of the number of whole days and +the fraction of a day from that epoch to that instant. -The C<:2nd> form of colonpairs can be used as a compact and self-documenting -way of specifying the delta: +=head2 method modified-julian-date - say DateTime.new('2015-12-24T12:23:00Z').later(:2years); - # OUTPUT: «2017-12-24T12:23:00Z␤» - -Since addition of several different time units is not commutative, only one -unit may be passed. +Defined as: - my $d = DateTime.new(date => Date.new('2015-02-27')); - say $d.later(month => 1).later(:2days); # OUTPUT: «2015-03-29T00:00:00Z␤» - say $d.later(days => 2).later(:1month); # OUTPUT: «2015-04-01T00:00:00Z␤» - say $d.later(days => 2).later(:month); # same, as +True === 1 + method modified-julian-date(DateTime:D: --> Real:D) -If the resultant time has value C<60> for seconds, yet no leap second -actually exists for that time, seconds will be set to C<59>: +Returns the L (MJD) for the UTC date and time. - say DateTime.new('2008-12-31T23:59:60Z').later: :1day; - # OUTPUT: «2009-01-01T23:59:59Z␤» + say DateTime.new('2021-12-24T12:23:00.43Z').modified-julian-date; # OUTPUT: «59572.5159772␤» -Negative offsets are allowed, though L is more -idiomatic for that. +Notice the fractional part of the C is same value as the C for the same instant. +Likewise, the integral part of the I is the same value as the C for the same instant since they +reference the same epoch (November 17, 1858). +The MJD is obtained by subtracting the constant C<2_400_000.5> from the I and is used to simplify +transformations between civil and astronomical time systems. -=head2 method earlier +=head2 method posix Defined as: - method earlier(DateTime:D: *%unit) - -Returns a DateTime object based on the current one, but with a time delta -towards the past applied. Unless the given unit is C or C, the -given value will be converted to an L. See L<#method later> for -usage. - - my $d = DateTime.new(date => Date.new('2015-02-27')); - say $d.earlier(month => 1).earlier(:2days); # OUTPUT: «2015-01-25T00:00:00Z␤» + method posix(Bool:D: $ignore-timezone = False --> Int:D) -If the resultant time has value C<60> for seconds, yet no leap second -actually exists for that time, seconds will be set to C<59>: +Returns the date and time as a POSIX/UNIX timestamp (integral seconds since the POSIX epoch, +1970-01-01T00:00:00Z). - say DateTime.new('2008-12-31T23:59:60Z').earlier: :1day; - # OUTPUT: «2008-12-30T23:59:59Z␤» +If C<$ignore-timezone> is C, the C object will be treated as if +the time zone offset is zero. -Negative offsets are allowed, though L is more idiomatic for that. +=for code +say DateTime.new('2015-12-24T12:23:00Z').posix; # OUTPUT: «1450959780␤» =head2 method truncated-to @@ -428,7 +411,7 @@ C object or the C between the two dates, respectively. When subtracting C, time zone of the original C is preserved in the returned C object. - say perl DateTime.new(:2016year) - DateTime.new(:2015year):; + say raku DateTime.new(:2016year) - DateTime.new(:2015year):; # OUTPUT: «Duration.new(31536001.0)␤» say DateTime.new(:2016year, :3600timezone) - Duration.new(31536001.0); # OUTPUT: «2015-01-01T00:00:00+01:00␤» diff --git a/doc/Type/Dateish.pod6 b/doc/Type/Dateish.pod6 index dc924b453..d5deb073e 100644 --- a/doc/Type/Dateish.pod6 +++ b/doc/Type/Dateish.pod6 @@ -6,9 +6,9 @@ role Dateish { ... } -Both L and L support accessing a -year, month and day-of-month, as well as related functionality such as -calculating the day of the week. +Both L and L support accessing of the +year, month and day-of-month represented in the object, as well as related +functionality such as calculating the day of the week. =head1 Methods @@ -235,12 +235,16 @@ Defined as: method daycount(Dateish:D: --> Int:D) -Returns the number of days from the epoch Nov. 17, 1858 to the +Returns the number of days from the epoch Nov. 17, 1858, to the day of the invocant. The daycount returned by this method is the -MJD, i.e. the L, -which is used routinely by e.g. astronomers, geodesists, scientists +integral part of the L (MJD) +which is used routinely by astronomers, geodesists, scientists, and others. The MJD convention is designed to facilitate simplified -chronological calculations. +chronological calculations. The fractional part of the MJD +consists of the hours, minutes, and seconds of the using DateTime +object converted to the equivalent fraction of 24 hours. +Those two values added define the MJD of that instant. + say Date.new('1995-09-27').daycount; # OUTPUT: «49987␤» @@ -260,6 +264,99 @@ B some operating systems (e.g. Windows) do not permit colons (C<:>) in filenames, which would be present in C created from a L object. -=end pod +=head2 method earlier + +Defined as: + + multi method earlier(Dateish:D: *%unit) + multi method earlier(Dateish:D: @pairs) + +Returns an object based on the current one, but with a date delta +towards the past applied. Unless the given unit is C or C, the +given value will be converted to an L. See L|/type/Dateish#method_later> for +usage. It will generally be used through classes that implement this role, +L|/type/Date> or L|/type/DateTime> + + my $d = Date.new('2015-02-27'); + say $d.earlier(month => 5).earlier(:2days); # OUTPUT: «2014-09-25␤» + my $d = DateTime.new(date => Date.new('2015-02-27')); + say $d.earlier(month => 1).earlier(:2days); # OUTPUT: «2015-01-25T00:00:00Z␤» + +If the resultant time has value C<60> for seconds, yet no leap second +actually exists for that time, seconds will be set to C<59>: + + say DateTime.new('2008-12-31T23:59:60Z').earlier: :1day; + # OUTPUT: «2008-12-30T23:59:59Z␤» + +Negative offsets are allowed, though L is more idiomatic for that. + +If you need to use more than one unit, you will need to build them into a +C of Cs to use the second form of the method: + +=for code +say Date.new('2021-03-31').earlier( ( year => 3, month => 2, day => 8 ) ); # OUTPUT: «2018-01-23␤» + +This feature was introduced in release 2021.02 of the Rakudo compiler. + +=head2 method later + +Defined as: + + multi method later(DateTime:D: *%unit) -# vim: expandtab softtabstop=4 shiftwidth=4 ft=perl6 +Returns an object based on the current one (belonging to any class that mixes +this role in), but with a +time delta +applied. The time delta can be passed as a named argument where the argument +name is the unit. + +Unless the given unit is C or C, the given value will be +converted to an L. + +Allowed units are C, C, C, C, C, +C, C, C, C, C, C, C, C, +C. Please note that the plural forms can only be used with +the C and C methods. + +The C<:2nd> form of colonpairs can be used as a compact and self-documenting +way of specifying the delta: + + say DateTime.new('2015-12-24T12:23:00Z').later(:2years); + # OUTPUT: «2017-12-24T12:23:00Z␤» + +Since addition of several different time units is not commutative, only one +unit may be passed (and the first multi will be used). + + my $d = DateTime.new(date => Date.new('2015-02-27')); + say $d.later(month => 1).later(:2days); # OUTPUT: «2015-03-29T00:00:00Z␤» + say $d.later(days => 2).later(:1month); # OUTPUT: «2015-04-01T00:00:00Z␤» + say $d.later(days => 2).later(:month); # same, as +True === 1 + +You can also (since release 2021.02 of the Rakudo compiler) pass several units +at the same time, but you will have to join them in a C to activate the +second form: + +=for code +say DateTime.new(date => Date.new('2015-02-27')).later( (:1month, :2days) ) +# OUTPUT: «2015-03-29T00:00:00Z␤» + +If the resultant time has value C<60> for seconds, yet no leap second +actually exists for that time, seconds will be set to C<59>: + + say DateTime.new('2008-12-31T23:59:60Z').later: :1day; + # OUTPUT: «2009-01-01T23:59:59Z␤» + +Negative offsets are allowed, though L is more +idiomatic for that. + +Objects of type L|/type/Date> will behave in the same way: + +=begin code +my $d = Date.new('2015-02-27'); +say $d.later(month => 1).later(:2days); # OUTPUT: «2015-03-29␤» +say $d.later(days => 2).later(:1month); # OUTPUT: «2015-04-01␤» +say $d.later(days => 2).later(:month); # same, as +True === 1 +=end code + + +=end pod diff --git a/doc/Type/Distribution/Hash.pod6 b/doc/Type/Distribution/Hash.pod6 index fdbb4c3af..af03912cc 100644 --- a/doc/Type/Distribution/Hash.pod6 +++ b/doc/Type/Distribution/Hash.pod6 @@ -5,7 +5,7 @@ =SUBTITLE Distribution::Hash =for code :preamble - class Distribution::Hash does Distribution::Locally { } +class Distribution::Hash does Distribution::Locally { } A L implementation backed by the filesystem. It does not require a C file, essentially providing a lower level diff --git a/doc/Type/Distribution/Locally.pod6 b/doc/Type/Distribution/Locally.pod6 index fbdbc9e3f..2021b590e 100644 --- a/doc/Type/Distribution/Locally.pod6 +++ b/doc/Type/Distribution/Locally.pod6 @@ -24,7 +24,7 @@ Provides L Returns an C to the file represented by C<$name-path>. C<$name-path> is a relative path as it would be found in the metadata such as C or C, and these paths will be prefixed with -L. +L. =end pod diff --git a/doc/Type/Distribution/Path.pod6 b/doc/Type/Distribution/Path.pod6 index 3ccad87bd..b590da136 100644 --- a/doc/Type/Distribution/Path.pod6 +++ b/doc/Type/Distribution/Path.pod6 @@ -5,7 +5,7 @@ =SUBTITLE Distribution::Path =for code :preamble - class Distribution::Path does Distribution::Locally { } +class Distribution::Path does Distribution::Locally { } A L implementation backed by the filesystem. It requires a C file at its root. diff --git a/doc/Type/Exception.pod6 b/doc/Type/Exception.pod6 index 928e5f510..a357030e6 100644 --- a/doc/Type/Exception.pod6 +++ b/doc/Type/Exception.pod6 @@ -86,7 +86,7 @@ This is different from C in that it preserves the original backtrace. sub f() { die 'Bad' }; - sub g() { try f; CATCH { default { .rethrow } } }; + sub g() { f; CATCH { default { .rethrow } } }; g; CATCH { default { say .backtrace.full } }; diff --git a/doc/Type/Failure.pod6 b/doc/Type/Failure.pod6 index c4ccdb1c8..66662b46c 100644 --- a/doc/Type/Failure.pod6 +++ b/doc/Type/Failure.pod6 @@ -11,10 +11,10 @@ usually generated by calling C<&fail>. It acts as a wrapper around an L object. Sink (void) context causes a C to throw, i.e. turn into a regular -exception. The L pragma|/language/pragmas#index-entry-fatal-fatal> +exception. The L pragma|/language/pragmas#fatal> causes this to happen in all contexts within the pragma's scope. Inside L -blocks|/language/exceptions#index-entry-try_blocks-try>, C +blocks|/language/exceptions#try_blocks>, C is automatically set, and you can I it with C. That means that Failures are generally only useful in cases of @@ -37,7 +37,7 @@ failure to throw. Because a Failure is L|/type/Nil>, which is undefined, a common idiom for safely executing code that may fail uses a -L|/language/control#with,_orwith,_without> statement: +L|/language/control#with_orwith_without> statement: =begin code sub may_fail( --> Numeric:D ) { @@ -59,10 +59,16 @@ with may_fail() -> $value { # defined, so didn't fail Defined as: - method new(Failure:D: $payload --> Failure) + multi method new(Failure:D:) + multi method new(Failure:U:) + multi method new(Failure:U: Exception:D \exception) + multi method new(Failure:U: $payload) + multi method new(Failure:U: |cap (*@msg)) -Returns a new C instance with the given payload. The latter can be -either an L or a payload for an C. A typical payload +Returns a new C instance with payload given as argument. If called +without arguments on a C object, it will throw; on a type value, it +will create an empty C with no payload. The latter can be either an +L or a payload for an C. A typical payload would be a C with an error message. A list of payloads is also accepted. my $e = Failure.new(now.DateTime, 'WELP‼'); @@ -74,14 +80,16 @@ would be a C with an error message. A list of payloads is also accepted. Defined as: - method handled(Failure:D: --> Bool:D) + method handled(Failure:D: --> Bool:D) is rw Returns C for handled failures, C otherwise. sub f() { fail }; my $v = f; say $v.handled; # OUTPUT: «False␤» -The C method is an lvalue, which means you can also use it to set the -handled state: +The C method is an +L, see L«routine trait +C|/type/Routine#trait_is_rw», which means you can also use it +to set the handled state: sub f() { fail } my $v = f; @@ -135,9 +143,11 @@ Defined as: Returns C, and marks the failure as handled. - sub f() { fail }; my $v = f; say $v.handled; $v.Bool; say $v.handled; - # OUTPUT: «False␤ - # True␤» + sub f() { fail }; + my $v = f; + say $v.handled; # OUTPUT: «False␤» + say $v.Bool; # OUTPUT: «False␤» + say $v.handled; # OUTPUT: «True␤» =head2 method Capture @@ -145,8 +155,9 @@ Defined as: method Capture() -Throws C if the invocant is a type object or a L -L. Otherwise, throws the invocant's L. +Throws C if the invocant is a type object or a +L L. Otherwise, throws the +invocant's L. =head2 method defined @@ -157,7 +168,20 @@ Defined as: Returns C (failures are officially undefined), and marks the failure as handled. - sub f() { fail }; my $v = f; say $v.defined; # OUTPUT: «False␤» + sub f() { fail }; + my $v = f; + say $v.handled; # OUTPUT: «False␤» + say $v.defined; # OUTPUT: «False␤» + say $v.handled; # OUTPUT: «True␤» + +=head2 method list + +Defined as: + + multi method list(Failure:D:) + +Marks the failure as handled and throws the invocant's +L. =head2 sub fail diff --git a/doc/Type/FatRat.pod6 b/doc/Type/FatRat.pod6 index 2e1c69aa0..94aaf1720 100644 --- a/doc/Type/FatRat.pod6 +++ b/doc/Type/FatRat.pod6 @@ -21,15 +21,15 @@ object. =head1 Methods -=head2 method perl +=head2 method raku - multi method perl(FatRat:D: --> Str:D) + multi method raku(FatRat:D: --> Str:D) Returns an implementation-specific string that produces an L object when given to L. -=for code :ok-test - say FatRat.new(1, 2).perl; # OUTPUT: «FatRat.new(1, 2)␤» +=for code +say FatRat.new(1, 2).raku; # OUTPUT: «FatRat.new(1, 2)␤» =end pod diff --git a/doc/Type/Grammar.pod6 b/doc/Type/Grammar.pod6 index d2e5eb4ab..867a4562b 100644 --- a/doc/Type/Grammar.pod6 +++ b/doc/Type/Grammar.pod6 @@ -6,7 +6,7 @@ class Grammar is Match {} -Every type declared with C and not explicitly stating its superclass, +Every type declared with C, and not explicitly stating its superclass, becomes a subclass of I. grammar Identifier { @@ -46,14 +46,14 @@ to the starting rule if provided. # 「aaaaaa」 # 「bbbbbb」 -If the C named argument is provided, it will be used as an action +If the C named argument is provided, it will be used as an actions object, that is, for each successful regex match, a method of the same name, -if it exists, is called on the action object, passing the match object as the +if it exists, is called on the actions object, passing the match object as the sole positional argument. my $actions = class { method TOP($/) { say "7" } }; grammar { token TOP { a { say "42" } b } }.parse('ab', :$actions); - # OUTPUT : «42␤7␤» + # OUTPUT: «42␤7␤» Additional named arguments are used as options for matching, so you can for example specify things like C<:pos(4)> to start parsing from the fifth (:pos is zero-based) character. @@ -65,7 +65,7 @@ those adverbs that affect the runtime behavior, such as C<:pos> and C<:continue> =for code :preamble say RepeatChar.parse('bbbbbb', :rule('start'), :args(\('b')), :pos(4)).Str; -# OUTPUT : «bb␤» +# OUTPUT: «bb␤» Method C only succeeds if the cursor has arrived at the end of the target string when the match is over. Use L @@ -135,7 +135,7 @@ are passed on to L. # zoffixznet # MasterDuke17 - # OUTPUT : «TimToady,lizmat,jnthn,moritz,zoffixznet,MasterDuke17␤» + # OUTPUT: «TimToady,lizmat,jnthn,moritz,zoffixznet,MasterDuke17␤» =end pod diff --git a/doc/Type/Hash.pod6 b/doc/Type/Hash.pod6 index 8f690b20f..d5b306d81 100644 --- a/doc/Type/Hash.pod6 +++ b/doc/Type/Hash.pod6 @@ -313,9 +313,9 @@ its return value will be used instead of the original C<@list>'s item: Defined as: - multi method push(Hash:D: *@new) + method push(Hash:D: +new) -Adds the C<@new> elements to the hash with the same semantics as hash +Adds the C elements to the hash with the same semantics as hash assignment, but with three exceptions: =item The hash isn't emptied first, i.e. old pairs are not deleted. @@ -336,15 +336,18 @@ Example: %h.push('c' => 4); # a => [1,1,1,1,1], b => 3, c => 4 push %h, 'd' => 5; # a => [1,1,1,1,1], b => 3, c => 4, d => 5 -Please note that Cs or -L as arguments to push -will be treated as extra named arguments and as such wont end up the C. -The same applies to the sub C. +Please note that literal pairs in the argument list may be interpreted as +L and as such won't end up in the C: my %h .= push(e => 6); - push %h, f => 7; - say %h.raku; - # OUTPUT: «{}␤» + say %h.raku; # OUTPUT: «{}␤» + +Use the corresponding L to +catch this kind of mistake: + + push my %h, f => 7; + CATCH { default { put .message } }; + # OUTPUT: «Unexpected named argument 'f' passed␤» Also note that push can be used as a replacement for assignment during hash initialization very useful ways. Take for instance the case of an inverted @@ -378,7 +381,7 @@ Append the provided Pairs or even sized list to the Hash. If a key already exists, turn the existing value into an L and push new value onto that C. Please note that you can't mix even sized lists and lists of Pairs. Also, bare Cs or colon pairs will be treated as L to C<.append>. +arguments|/type/Signature#Positional_vs._named_arguments> to C<.append>. my %h = a => 1; %h.append('b', 2, 'c', 3); diff --git a/doc/Type/IO/CatHandle.pod6 b/doc/Type/IO/CatHandle.pod6 index a7bf47e39..d0258b307 100644 --- a/doc/Type/IO/CatHandle.pod6 +++ b/doc/Type/IO/CatHandle.pod6 @@ -175,14 +175,14 @@ L to switch to binary mode). All source handles, including the ac will use the provided C<$.encoding> value. =begin code -(my $f1 = 'foo'.IO).spurt: 'I ♥ Perl'; +(my $f1 = 'foo'.IO).spurt: 'I ♥ Raku'; (my $f2 = 'bar'.IO).spurt: 'meow'; with IO::CatHandle.new: $f1, $f2 { # .encoding is 'utf8' by default: - .readchars(5).say; # OUTPUT: «I ♥ P␤» + .readchars(5).say; # OUTPUT: «I ♥ R␤» .encoding: Nil; # switch to binary mode - .slurp.say; # OUTPUT: «Buf[uint8]:0x<72 6c 6d 65 6f 77>␤» + .slurp.say; # OUTPUT: «Buf[uint8]:0x<6B 75 6D 65 6F 77>␤» } =end code @@ -252,10 +252,10 @@ L, resulting in C exception being thrown. =begin code -(my $f1 = 'foo'.IO).spurt: 'I ♥ Perl'; +(my $f1 = 'foo'.IO).spurt: 'I ♥ Raku'; (my $f2 = 'bar'.IO).spurt: 'meow'; my $cat = IO::CatHandle.new: $f1, $f2; -.say while $_ = $cat.getc; # OUTPUT: «I␤ ␤♥␤ ␤P␤e␤r␤l␤m␤e␤o␤w␤» +.say while $_ = $cat.getc; # OUTPUT: «I␤ ␤♥␤ ␤R␤a␤k␤u␤m␤e␤o␤w␤» =end code =head2 method handles @@ -564,11 +564,11 @@ It is B permitted to call this method on handles opened in binary mode and doing so will result in C exception being thrown. =begin code -(my $f1 = 'foo'.IO).spurt: 'Perl loves to'; +(my $f1 = 'foo'.IO).spurt: 'Raku loves to'; (my $f2 = 'bar'.IO).spurt: ' meow'; with IO::CatHandle.new: $f1, $f2 { - say .readchars: 11; # OUTPUT: «Perl loves ␤» + say .readchars: 11; # OUTPUT: «Raku loves ␤» say .readchars: 1000; # OUTPUT: «to meow␤» } =end code @@ -769,7 +769,7 @@ Defined as: The L type overrides this method to throw a C exception. If you have a good idea for how this method should behave, -L! +L! =head2 method nl-out @@ -779,7 +779,7 @@ Defined as: The L type overrides this method to throw a C exception. If you have a good idea for how this method should behave, -L! +L! =head2 method out-buffer @@ -789,7 +789,7 @@ Defined as: The L type overrides this method to throw a C exception. If you have a good idea for how this method should behave, -L! +L! =head2 method print @@ -799,7 +799,7 @@ Defined as: The L type overrides this method to throw a C exception. If you have a good idea for how this method should behave, -L! +L! =head2 method printf @@ -809,7 +809,7 @@ Defined as: The L type overrides this method to throw a C exception. If you have a good idea for how this method should behave, -L! +L! =head2 method print-nl @@ -819,7 +819,7 @@ Defined as: The L type overrides this method to throw a C exception. If you have a good idea for how this method should behave, -L! +L! =head2 method put @@ -829,7 +829,7 @@ Defined as: The L type overrides this method to throw a C exception. If you have a good idea for how this method should behave, -L! +L! =head2 method say @@ -839,7 +839,7 @@ Defined as: The L type overrides this method to throw a C exception. If you have a good idea for how this method should behave, -L! +L! =head2 method write @@ -849,7 +849,7 @@ Defined as: The L type overrides this method to throw a C exception. If you have a good idea for how this method should behave, -L! +L! =head2 method WRITE @@ -859,7 +859,7 @@ Defined as: The L type overrides this method to throw a C exception. If you have a good idea for how this method should behave, -L! +L! =head2 method READ @@ -869,7 +869,7 @@ Defined as: The L type overrides this method to throw a C exception. If you have a good idea for how this method should behave, -L! +L! =head2 method EOF @@ -879,7 +879,7 @@ Defined as: The L type overrides this method to throw a C exception. If you have a good idea for how this method should behave, -L! +L! =end pod diff --git a/doc/Type/IO/Handle.pod6 b/doc/Type/IO/Handle.pod6 index 54a34c9c7..8295a65a7 100644 --- a/doc/Type/IO/Handle.pod6 +++ b/doc/Type/IO/Handle.pod6 @@ -10,8 +10,8 @@ Instances of C encapsulate a I to manipulate input/output resources. Usually there is no need to create directly an C instance, since it will be done by other roles and methods. For instance, an -L object provides an L method that returns an -C: +L object provides an L method that +returns an C: my $fh = '/tmp/log.txt'.IO.open; say $fh.^name; # OUTPUT: IO::Handle @@ -153,7 +153,7 @@ Defined as: One of the attributes that can be set via C<.new> or L. Defaults to C. Takes a L specifying whether the line separators (as defined by L«C<.nl-in>|/type/IO::Handle#method_nl-in») should be removed from content when -using L«C<.get>|/type/IO::Handle#method_get» or +using L«C<.get>|/type/IO::Handle#routine_get» or L«C<.lines>|/type/IO::Handle#routine_lines» methods. =head2 routine get @@ -208,7 +208,7 @@ even a single byte of data. =head3 Waiting for potential combiners -If your handle's encoding allows combining characters to be read, perl6 will +If your handle's encoding allows combining characters to be read, raku will wait for more data to be available before it provides a character. This means that inputting an "e" followed by a combining acute will give you an e with an acute rather than giving an "e" and letting the next reading function give you @@ -305,7 +305,7 @@ ascii The default encoding is utf8, which undergoes normalization into Unicode B (normalization form canonical). In some cases you may want to ensure no normalization is done; for this you can use C. Before using C -please read L +please read L for more information on C and B. As of Rakudo 2018.04 L @@ -395,9 +395,9 @@ file position. =begin code say "The file contains ", - '50GB-file'.IO.open.lines.grep(*.contains: 'Perl').elems, - " lines that mention Perl"; -# OUTPUT: «The file contains 72 lines that mention Perl␤» + '50GB-file'.IO.open.lines.grep(*.contains: 'Raku').elems, + " lines that mention Raku"; +# OUTPUT: «The file contains 72 lines that mention Raku␤» =end code You can use C in C files (from the 6.d version): @@ -405,22 +405,26 @@ You can use C in C files (from the 6.d version): =for code say lines( "/proc/$*PID/statm".IO ); # OUTPUT: «(58455 31863 8304 2 0 29705 0)␤» +X<|File locking> =head2 method lock Defined as: - method lock(IO::Handle:D: Bool:D :$non-blocking = False, Bool:D :$shared = False --> True) - -Places an advisory lock on the filehandle. If C<:$non-blocking> is C -will L«C|/routine/fail» with C if lock could not be -obtained, otherwise will block until the lock can be placed. If C<:$shared> -is C will place a shared (read) lock, otherwise will place an -exclusive (write) lock. On success, returns C; L«fails|/routine/fail» -with C if lock cannot be placed (e.g. when trying to place -a shared lock on a filehandle opened in write mode or trying to +=for code :method +method lock(IO::Handle:D: + Bool:D :$non-blocking = False, Bool:D :$shared = False + --> True) + +Places an advisory lock on the file the filehandle if open for. If +C<:$non-blocking> is C will L«C|/routine/fail» with C +if lock could not be obtained, otherwise will block until the lock can be +placed. If C<:$shared> is C will place a shared (read) lock, otherwise +will place an exclusive (write) lock. On success, returns C; +L«fails|/routine/fail» with C if lock cannot be placed (e.g. when +trying to place a shared lock on a filehandle opened in write mode or trying to place an exclusive lock on a filehandle opened in read mode). -You can use C again to replace an existing lock with another one. +You can use C<.lock> again to replace an existing lock with another one. To remove a lock, L«C|/routine/close» the filehandle or use L«C|/routine/unlock». @@ -432,7 +436,7 @@ L«C|/routine/unlock». given "foo".IO.open(:w) { .lock; .spurt: "I ♥ Raku!"; - .close; # closing the handle unlocks it; we could also use `unlock` method for that + .close; # closing the handle unlocks it; we could also use `unlock` for that } # Reader @@ -449,7 +453,8 @@ Defined as: method unlock(IO::Handle:D: --> True) -Removes a L«C|/routine/lock» from the filehandle. +Removes a L«C|/routine/lock» from the filehandle. It will return +C or fail with an exception if it's not possible. =head2 routine words @@ -568,7 +573,7 @@ Defined as: Formats a string based on the given format and arguments and C<.print>s the result into the filehandle. See -L for details on +L for details on acceptable format directives. Attempting to call this method when the handle is @@ -661,7 +666,7 @@ This method can be called even when the handle is not L. =begin code -(my $file = 'foo'.IO).spurt: 'I ♥ Perl'; +(my $file = 'foo'.IO).spurt: 'I ♥ Raku'; given $file.open { say .read: 6; # OUTPUT: «Buf[uint8]:0x<49 20 e2 99 a5 20>␤» .close; @@ -682,9 +687,9 @@ L will result in C exception being thrown. =begin code -(my $file = 'foo'.IO).spurt: 'I ♥ Perl'; +(my $file = 'foo'.IO).spurt: 'I ♥ Raku'; given $file.open { - say .readchars: 5; # OUTPUT: «I ♥ P␤» + say .readchars: 5; # OUTPUT: «I ♥ R␤» .close; } =end code @@ -764,7 +769,7 @@ Defined as: multi method Supply(IO::Handle:D: :$size = 65536) -Returns a C that will emit the contents of the handle in chunks. +Returns a L«C|/type/Supply» that will emit the contents of the handle in chunks. The chunks will be L«C|/type/Buf» if the handle is in binary mode or, if it isn't, L«C|/type/Str» decoded using same encoding as L«C|/routine/encoding». @@ -1047,7 +1052,7 @@ my $output = $PROCESS::OUT; $PROCESS::OUT = $store; .say for ; $PROCESS::OUT = $output; -say $store.lines(); # OUTPUT «[one␤ two␤ three␤]» +say $store.lines(); # OUTPUT: «[one␤ two␤ three␤]» =end code In this example we are creating a simple C redirection which stores @@ -1116,8 +1121,8 @@ class IO::Store is IO::Handle { my $store := IO::Store.new(); $store.print( $_ ) for ; -say $store.read(3).decode; # OUTPUT «one␤» -say $store.read(3).decode; # OUTPUT «two␤» +say $store.read(3).decode; # OUTPUT: «one␤» +say $store.read(3).decode; # OUTPUT: «two␤» =end code In this case, we have programmed the two C and C methods, as well as diff --git a/doc/Type/IO/Path.pod6 b/doc/Type/IO/Path.pod6 index ab8113d34..1e71e4580 100644 --- a/doc/Type/IO/Path.pod6 +++ b/doc/Type/IO/Path.pod6 @@ -158,9 +158,7 @@ Defined as: method child(IO::Path:D: Str() $childname --> IO::Path:D) -Alias for L«C<.add>|/routine/add». B This method has been deprecated as -of the 6.d version, and will be removed in the future. For any new code, please -use L«C<.add>|/routine/add» +Alias for L«C<.add>|/routine/add». =head2 method cleanup @@ -302,28 +300,29 @@ the empty string. Defined as: - method parts(IO::Path:D: --> Map:D) + method parts(IO::Path:D:) -Returns a L with the keys C, C, C whose values -are the same as available via methods L«C<.volume>|/routine/volume», -L«C<.dirname>|/routine/dirname», and L«C<.basename>|/routine/basename» -respectively. +Returns a L«C|/type/IO::Path::Parts» for the invocant. - say IO::Path::Win32.new("C:/rakudo/perl6.bat").parts.raku; - # OUTPUT: «Map.new((:basename("perl6.bat"),:dirname("/rakudo"),:volume("C:")))␤» + say IO::Path::Win32.new("C:/rakudo/raku.bat").parts.raku; + # OUTPUT: «IO::Path::Parts.new("C:","/rakudo","raku.bat")␤» -=head2 method perl +B: Before Rakudo version 2020.06 a L«C|/type/Map» was +returned, with the keys C, C, C whose values +were the respective invocant parts. + +=head2 method raku Defined as: - method perl(IO::Path:D: --> Str:D) + method raku(IO::Path:D: --> Str:D) Returns a string that, when given passed through L«C|/routine/EVAL» gives the original invocant back. -=for code :ok-test - "foo/bar".IO.perl.say; - # OUTPUT: IO::Path.new("foo/bar", :SPEC(IO::Spec::Unix), :CWD("/home/camelia")) +=for code +"foo/bar".IO.raku.say; +# OUTPUT: IO::Path.new("foo/bar", :SPEC(IO::Spec::Unix), :CWD("/home/camelia")) Note that this string includes the value of the C<.CWD> attribute that is set to L«C<$*CWD>|/language/variables#Dynamic_variables» when the path @@ -497,7 +496,7 @@ last part of the path does B have to exist to C<:$completely> resolve the path. NOTE: Currently (April 2017) this method doesn't work correctly on all -platforms, e.g. Windows, since it assumes POSIX semantics. +platforms, e.g. Windows, since C assumes POSIX semantics. =head2 routine dir @@ -566,13 +565,13 @@ starting from the current directory: =for code my @stack = '.'.IO; -my $perl-files = gather while @stack { +my $raku-files = gather while @stack { with @stack.pop { when :d { @stack.append: .dir } .take when .extension.lc eq 'p6' } } -.put for $perl-files[^3]; +.put for $raku-files[^3]; =head2 File test operators @@ -659,7 +658,7 @@ which case the reported size is dependent on the operating system. The method will L«C|/routine/fail» with C if the path points to a non-existent filesystem entity. - say $*EXECUTABLE.IO.s; # OUTPUT : «467␤» + say $*EXECUTABLE.IO.s; # OUTPUT: «467␤» =head2 method l @@ -767,7 +766,7 @@ Opens the invocant and returns its L«words|/type/IO::Handle#routine_words». The behavior is equivalent to L the file specified by the invocant, forwarding the C<:$chomp>, C<:$enc>, and C<:$nl-in> arguments to -L«C|/type/IO::Handle#routine_open», then calling +L«C|/type/IO::Handle#method_open», then calling L«C|/type/IO::Handle#routine_words» on that handle, forwarding any of the remaining arguments to that method, and returning the resultant L. @@ -793,7 +792,7 @@ Opens the invocant and returns its L«lines|/type/IO::Handle#routine_lines». The behavior is equivalent to L the file specified by the invocant, forwarding the C<:$chomp>, C<:$enc>, and C<:$nl-in> arguments to -L«C|/type/IO::Handle#routine_open», then calling +L«C|/type/IO::Handle#method_open», then calling L«C|/type/IO::Handle#routine_lines» on that handle, forwarding any of the remaining arguments to that method, and returning the resultant L. @@ -806,9 +805,9 @@ L«C<$limit> argument|/type/IO::Handle#routine_lines») =begin code say "The file contains ", - '50GB-file'.IO.lines.grep(*.contains: 'Perl').elems, - " lines that mention Perl"; -# OUTPUT: «The file contains 72 lines that mention Perl␤» + '50GB-file'.IO.lines.grep(*.contains: 'Raku').elems, + " lines that mention Raku"; +# OUTPUT: «The file contains 72 lines that mention Raku␤» =end code =head2 routine slurp @@ -828,8 +827,8 @@ Defined as: method spurt(IO::Path:D: $data, :$enc, :$append, :$createonly) -Opens the file path for writing, and writes all of the C<$data> into it. File -will be closed, afterwards. Will L«C|/routine/fail» if it cannot succeed +Opens the path for writing, and writes all of the C<$data> into it. File +will be closed afterwards. Will L«C|/routine/fail» if it cannot succeed for any reason. The C<$data> can be any L«C|/type/Cool» type or any L«C|/type/Blob» type. Arguments are as follows: @@ -846,13 +845,9 @@ contents, and appending data to the end of the file. Defined as: + multi method chdir(IO::Path:D: IO $path, |c) multi method chdir(IO::Path:D: Str() $path, :$d = True, :$r, :$w, :$x) -B this method will be deprecated in C<6.d> language and -removed in C<6.e>. Do not use it for new code. Instead, create a new path or use -L«C|/routine/add» method. For altering current working directory see -L«C<&chdir>|/routine/chdir» and L«C<&*chdir>|/routine/&*chdir» subroutines. - Contrary to the name, the C<.chdir> method does not change any directories, but merely concatenates the given C<$path> to the invocant and returns the resultant C. Optional file tests can be performed by providing @@ -987,13 +982,19 @@ X<|symlink (method)> Defined as: - method symlink(IO::Path:D $target: IO() $link --> Bool:D) - sub symlink( IO() $target, IO() $link --> Bool:D) + method symlink(IO::Path:D $target: IO() $link, Bool :$absolute = True --> Bool:D) + sub symlink( IO() $target, IO() $link, Bool :$absolute = True --> Bool:D) Create a new I link C<$link> to existing C<$target>. Returns C on success; L with L if the symbolic link could not be created. If C<$target> does not exist, creates a dangling symbolic link. + +C creates a symbolic link using an absolute path +by default. To create a relative symlink set the C +parameter to C e.g. C<:!absolute>. This flag was +introduced in Rakudo version 2020.11. + To create a hard link, see L«C|/routine/link». B on Windows, creation of symbolic links may require escalated diff --git a/doc/Type/IO/Path/Cygwin.pod6 b/doc/Type/IO/Path/Cygwin.pod6 index 4f46b689d..73f0ee4d5 100644 --- a/doc/Type/IO/Path/Cygwin.pod6 +++ b/doc/Type/IO/Path/Cygwin.pod6 @@ -18,18 +18,18 @@ C<:$SPEC> cannot be set and defaults to L«C|/type/IO::Spec::Cygwin», regardless of the operating system the code is being run on. -=head2 method perl +=head2 method raku Defined as: - method perl(IO::Path::Cygwin:D: --> Str:D) + method raku(IO::Path::Cygwin:D: --> Str:D) Returns a string that, when given passed through L«C|/routine/EVAL» gives the original invocant back. -=for code :ok-test - IO::Path::Cygwin.new("foo/bar").perl.say; - # OUTPUT: IO::Path::Cygwin.new("foo/bar", :CWD("/home/camelia")) +=for code +IO::Path::Cygwin.new("foo/bar").raku.say; +# OUTPUT: IO::Path::Cygwin.new("foo/bar", :CWD("/home/camelia")) Note that this string includes the value of the C<.CWD> attribute that is set to L«C<$*CWD>|/language/variables#Dynamic_variables» when the path diff --git a/doc/Type/IO/Path/Parts.pod6 b/doc/Type/IO/Path/Parts.pod6 new file mode 100644 index 000000000..c461cd6fc --- /dev/null +++ b/doc/Type/IO/Path/Parts.pod6 @@ -0,0 +1,82 @@ +=begin pod :kind("Type") :subkind("class") :category("domain-specific") + +=TITLE class IO::Path::Parts + +=SUBTITLE IO::Path parts encapsulation + +=begin code :skip-test +class IO::Path::Parts does Positional does Associative does Iterable { } +=end code + +An C object is a container for the parts of an +L«C|/type/IO::Path» object. It is usually created with +a call to the method L«C<.parts>|/type/IO::Path#method_parts» on a +C object. It can also be created with a call to the method +L«C<.split>|/routine/split» on a object of one of the low-level path +operations sub-classes of L«C|/type/IO::Spec». + +The parts of an C are: + +=item the volume, see L«C<.volume>|/type/IO::Path#method_volume» +=item the directory name, see L«C<.dirname>|/type/IO::Path#method_dirname» +=item the basename, see L«C<.basename>|/type/IO::Path#method_basename» + +=head1 Methods + +=head2 method new + + method new(\volume, \dirname, \basename) + +Create a new C object with C<\volume>, C<\dirname> +and C<\basename> as respectively the volume, directory name and basename +parts. + +=head2 attribute volume + +Read-only. Returns the volume of the C object. + +=begin code +IO::Path::Parts.new('C:', '/some/dir', 'foo.txt').volume.say; +# OUTPUT: «C:␤» +=end code + +=head2 attribute dirname + +Read-only. Returns the directory name part of the C +object. + +=begin code +IO::Path::Parts.new('C:', '/some/dir', 'foo.txt').dirname.say; +# OUTPUT: «/some/dir␤» +=end code + +=head2 attribute basename + +Read-only. Returns the basename part of the C object. + +=begin code +IO::Path::Parts.new('C:', '/some/dir', 'foo.txt').basename.say; +# OUTPUT: «foo.txt␤» +=end code + +=head1 Previous implementations + +Before Rakudo 2020.06 the C<.parts> method of C returned +a L«C|/type/Map» and the C<.split> routine of the C +sub-classes returned a L«C|/type/List» of L«C|/type/Pair». +The C class maintains compatibility with these +previous implementations by doing L«C|/type/Positional», +L«C|/type/Associative» and L«C|/type/Iterable». + +=begin code +my $parts = IO::Path::Parts.new('C:', '/some/dir', 'foo.txt'); +say $parts; # OUTPUT: «C:␤» +say $parts[0]; # OUTPUT: «volume => C:␤» +say $parts[0].^name; # OUTPUT: «Pair␤» +.say for $parts[]; +# OUTPUT: «volume => C:␤dirname => /some/dir␤basename => foo.txt␤» +=end code + +=end pod + +# vim: expandtab shiftwidth=4 ft=perl6 diff --git a/doc/Type/IO/Path/QNX.pod6 b/doc/Type/IO/Path/QNX.pod6 index f41aacf4d..67b74fa15 100644 --- a/doc/Type/IO/Path/QNX.pod6 +++ b/doc/Type/IO/Path/QNX.pod6 @@ -18,18 +18,18 @@ C<:$SPEC> cannot be set and defaults to L«C|/type/IO::Spec::QNX», regardless of the operating system the code is being run on. -=head2 method perl +=head2 method raku Defined as: - method perl(IO::Path::QNX:D: --> Str:D) + method raku(IO::Path::QNX:D: --> Str:D) Returns a string that, when given passed through L«C|/routine/EVAL» gives the original invocant back. -=for code :ok-test - IO::Path::QNX.new("foo/bar").perl.say; - # OUTPUT: IO::Path::QNX.new("foo/bar", :CWD("/home/camelia")) +=for code +IO::Path::QNX.new("foo/bar").raku.say; +# OUTPUT: IO::Path::QNX.new("foo/bar", :CWD("/home/camelia")) Note that this string includes the value of the C<.CWD> attribute that is set to L«C<$*CWD>|/language/variables#Dynamic_variables» when the path diff --git a/doc/Type/IO/Path/Unix.pod6 b/doc/Type/IO/Path/Unix.pod6 index 08a7d3e7c..134360fb8 100644 --- a/doc/Type/IO/Path/Unix.pod6 +++ b/doc/Type/IO/Path/Unix.pod6 @@ -18,18 +18,18 @@ C<:$SPEC> cannot be set and defaults to L«C|/type/IO::Spec::Unix», regardless of the operating system the code is being run on. -=head2 method perl +=head2 method raku Defined as: - method perl(IO::Path::Unix:D: --> Str:D) + method raku(IO::Path::Unix:D: --> Str:D) Returns a string that, when given passed through L«C|/routine/EVAL» gives the original invocant back. -=for code :ok-test - IO::Path::Unix.new("foo/bar").perl.say; - # OUTPUT: IO::Path::Unix.new("foo/bar", :CWD("/home/camelia")) +=for code +IO::Path::Unix.new("foo/bar").raku.say; +# OUTPUT: IO::Path::Unix.new("foo/bar", :CWD("/home/camelia")) Note that this string includes the value of the C<.CWD> attribute that is set to L«C<$*CWD>|/language/variables#Dynamic_variables» when the path diff --git a/doc/Type/IO/Path/Win32.pod6 b/doc/Type/IO/Path/Win32.pod6 index 0ed34f1e6..cb0b196f0 100644 --- a/doc/Type/IO/Path/Win32.pod6 +++ b/doc/Type/IO/Path/Win32.pod6 @@ -18,17 +18,17 @@ C<:$SPEC> cannot be set and defaults to L«C|/type/IO::Spec::Win32», regardless of the operating system the code is being run on. -=head2 method perl +=head2 method raku Defined as: - method perl(IO::Path::Win32:D: --> Str:D) + method raku(IO::Path::Win32:D: --> Str:D) Returns a string that, when given passed through L«C|/routine/EVAL» gives the original invocant back. -=for code :ok-test -IO::Path::Win32.new("foo/bar").perl.say; +=for code +IO::Path::Win32.new("foo/bar").raku.say; # OUTPUT: IO::Path::Win32.new("foo/bar", :CWD("C:\\Users\\camelia")) Note that this string includes the value of the C<.CWD> attribute that is set diff --git a/doc/Type/IO/Spec.pod6 b/doc/Type/IO/Spec.pod6 index bb0b620b7..d6de5ae23 100644 --- a/doc/Type/IO/Spec.pod6 +++ b/doc/Type/IO/Spec.pod6 @@ -7,18 +7,20 @@ class IO::Spec { } Objects of this class are not used directly but as a sub-class specific to -the platform perl is running on via the C<$*SPEC> variable which will contain +the platform Raku is running on via the C<$*SPEC> variable which will contain an object of the appropriate type. The sub-classes are documented separately, with the platform-specific differences documented in L, L, L and L. -B the C classes provide low-level path operations. Unless +=head1 About sub-classes IO::Spec::* + +The C classes provide low-level path operations. Unless you're creating your own high-level path manipulation routines, you don't need to use C. Use L«C|/type/IO::Path» instead. -B no special validation is done by these classes (e.g. check whether +Beware that no special validation is done by these classes (e.g. check whether path contains a null character). It is the job of higher-level classes, like L«C|/type/IO::Path», to do that. diff --git a/doc/Type/IO/Spec/Cygwin.pod6 b/doc/Type/IO/Spec/Cygwin.pod6 index 871430827..3fb7f599c 100644 --- a/doc/Type/IO/Spec/Cygwin.pod6 +++ b/doc/Type/IO/Spec/Cygwin.pod6 @@ -4,18 +4,13 @@ =SUBTITLE Platform specific operations on file and directory paths for Cygwin - class IO::Spec::QNX is IO::Spec { } + class IO::Spec::Cygwin is IO::Spec::Unix { } -This sub-class of L will be available from the -C<$*SPEC> variable for a perl running on C . +An object of this type is available via the variable C<$*SPEC> if the +Raku interpreter is running on C. -B the C classes provide low-level path operations. Unless -you're creating your own high-level path manipulation routines, you don't -need to use C. Use L«C|/type/IO::Path» instead. - -B no special validation is done by these classes (e.g. check whether -path contains a null character). It is the job of higher-level classes, like -L«C|/type/IO::Path», to do that. +About this class and its related classes also see +L. =head1 Methods @@ -58,8 +53,8 @@ Concatenates multiple path fragments and returns the canonical representation of the resultant path as a string. The C<@parts> are L«C|/type/Str» objects and are allowed to contain path separators. - IO::Spec::Cygwin.catdir().say; - # OUTPUT: «foo/bar/ber/perl␤» + IO::Spec::Cygwin.catdir().say; + # OUTPUT: «foo/bar/ber/raku␤» =head2 method catpath @@ -119,10 +114,11 @@ except replaces backslashes with slashes in the final result. Defined as: - method split(IO::Spec::Cygwin: |c --> List:D) + method split(IO::Spec::Cygwin: Cool:D $path) -Same as L«C|/type/IO::Spec::Win32#method_split», except -replaces backslashes with slashes in all the values of the final result. +Same as L«C|/type/IO::Spec::Win32#method_split», +except it replaces backslashes with slashes in all the values of the +final result. =head2 method splitpath diff --git a/doc/Type/IO/Spec/QNX.pod6 b/doc/Type/IO/Spec/QNX.pod6 index aba9508b4..2335ba181 100644 --- a/doc/Type/IO/Spec/QNX.pod6 +++ b/doc/Type/IO/Spec/QNX.pod6 @@ -4,18 +4,13 @@ =SUBTITLE Platform specific operations on file and directory paths QNX - class IO::Spec::QNX is IO::Spec { } + class IO::Spec::QNX is IO::Spec::Unix { } -This sub-class of L specific to QNX will be -available via C<$*SPEC> if the perl is running on QNX. +An object of this type is available via the variable C<$*SPEC> if the +Raku interpreter is running on a C platform. -B the C classes provide low-level path operations. Unless -you're creating your own high-level path manipulation routines, you don't -need to use C. Use L«C|/type/IO::Path» instead. - -B no special validation is done by these classes (e.g. check whether -path contains a null character). It is the job of higher-level classes, like -L«C|/type/IO::Path», to do that. +About this class and its related classes also see +L. =head1 Methods diff --git a/doc/Type/IO/Spec/Unix.pod6 b/doc/Type/IO/Spec/Unix.pod6 index f9dab3eee..d12e6cb4c 100644 --- a/doc/Type/IO/Spec/Unix.pod6 +++ b/doc/Type/IO/Spec/Unix.pod6 @@ -9,14 +9,8 @@ An object of this type is available via the variable C<$*SPEC> if the Raku interpreter is running on a Unix-like platform. -The C classes provide low-level path operations. Unless -you're creating your own high-level path manipulation routines, you -don't need to use C. Use L«C|/type/IO::Path» -instead. - -Beware that no special validation is done by these classes (e.g. check -whether path contains a null character). It is the job of higher-level -classes, like L«C|/type/IO::Path», to do that. +About this class and its related classes also see +L. =head1 Methods @@ -73,7 +67,7 @@ Concatenates multiple path fragments and returns the canonical representation of the resultant path as a string. The C<@parts> are L«C|/type/Str» objects and are allowed to contain path separators. - IO::Spec::Unix.catdir().say; # OUTPUT: «foo/bar/ber/perl␤» + IO::Spec::Unix.catdir().say; # OUTPUT: «foo/bar/ber/raku␤» =head2 method catfile @@ -87,7 +81,7 @@ Defined as: Takes two path fragments and concatenates them, adding or removing a path separator, if necessary. The first argument is ignored (it exists -to maintain consistent interface with other C types for +to maintain consistent interface with other L«C|/type/IO::Spec» types for systems that have volumes). IO::Spec::Unix.catpath($, 'some/dir', 'and/more').say; @@ -109,17 +103,28 @@ Defined as: method curupdir() -Returns a L«C|/routine/none» L of strings representing -the current directory and the "one directory up": +Returns a L«C|/type/Block» taking an argument. This block +returns C if its argument is neither the string representing the +current directory nor the string representing the directory one up from +the current one. It returns C otherwise. +This block is intended to be used with +L. + +=begin code +say $*SPEC.curupdir; +# OUTPUT: «-> str $dir { #`(Block|65335808) ... }␤» -=for code -say $*SPEC.curupdir; # OUTPUT: «none(., ..)␤» my @dirs = <. foo .. bar>; -say @dirs.grep(* eq $*SPEC.curupdir); # OUTPUT: «(foo bar)␤» +say @dirs.grep: { $_ ~~ $*SPEC.curupdir }; +# OUTPUT: «(foo bar)␤» +=end code Neither C nor C are equal to the representation of the current or parent directory, that is why they are returned by C. +B: Before Rakudo version 2020.06 a L«C|/routine/none» +L was returned instead of a C. + =head2 method devnull Defined as: @@ -249,33 +254,35 @@ Returns string C<'/'>, representing root directory. Defined as: - method split(IO::Spec::Unix: Cool:D $path --> List:D) + method split(IO::Spec::Unix: Cool:D $path) -Splits the given C<$path> into "volume", "dirname", and "basename" and -returns the result as a L of three L, in that order. -The "volume" is always an empty string and exists for consistency with other -L classes. +Creates a L«C|/type/IO::Path::Parts» for C<$path>, +with an empty string as its C attribute's value. =begin code IO::Spec::Unix.split('C:/foo/bar.txt').raku.say; -# OUTPUT: «(:volume(""), :dirname("C:/foo"), :basename("bar.txt"))␤» +# OUTPUT: «IO::Path::Parts.new("","C:/foo","bar.txt")␤» IO::Spec::Unix.split('/foo/').raku.say; -# OUTPUT: «(:volume(""), :dirname("/"), :basename("foo"))␤» +# OUTPUT: «IO::Path::Parts.new("","/","foo")␤» IO::Spec::Unix.split('///').raku.say; -# OUTPUT: «(:volume(""), :dirname("/"), :basename("/"))␤» +# OUTPUT: «IO::Path::Parts.new("","/","/")␤» IO::Spec::Unix.split('./').raku.say; -# OUTPUT: «(:volume(""), :dirname("."), :basename("."))␤» +# OUTPUT: «IO::Path::Parts.new("",".",".")␤» IO::Spec::Unix.split('.').raku.say; -# OUTPUT: «(:volume(""), :dirname("."), :basename("."))␤» +# OUTPUT: «IO::Path::Parts.new("",".",".")␤» IO::Spec::Unix.split('').raku.say; -# OUTPUT: «(:volume(""), :dirname(""), :basename(""))␤» +# OUTPUT: «IO::Path::Parts.new("","","")␤» =end code +B: Before Rakudo version 2020.06 this method split the given +C<$path> into "volume", "dirname", and "basename" and returned the result +as a L of three L, in that order. + =head2 method splitdir Defined as: diff --git a/doc/Type/IO/Spec/Win32.pod6 b/doc/Type/IO/Spec/Win32.pod6 index 3ea7dbabc..03eb5c9a1 100644 --- a/doc/Type/IO/Spec/Win32.pod6 +++ b/doc/Type/IO/Spec/Win32.pod6 @@ -4,20 +4,13 @@ =SUBTITLE Platform specific operations on file and directory paths for Windows - class IO::Spec::Win32 is IO::Spec { } + class IO::Spec::Win32 is IO::Spec::Unix { } -Objects of this class are used not directly but as a sub-class specific -to the platform Raku is running on via the C<$*SPEC> variable, which -will contain an object of the appropriate type. +An object of this type is available via the variable C<$*SPEC> if the +Raku interpreter is running on a Windows-like platform. -B the C classes provide low-level path operations. -Unless you're creating your own high-level path manipulation routines, -you don't need to use C. Use L«C|/type/IO::Path» -instead. - -B no special validation is done by these classes (e.g. check -whether path contains a null character). It is the job of higher-level -classes, like L«C|/type/IO::Path», to do that. +About this class and its related classes also see +L. =head1 Methods @@ -64,8 +57,8 @@ Concatenates multiple path fragments and returns the canonical representation of the resultant path as a string. The C<@parts> are L«C|/type/Str» objects and are allowed to contain path separators. - IO::Spec::Win32.catdir().say; - # OUTPUT: «foo\bar\ber\perl␤» + IO::Spec::Win32.catdir().say; + # OUTPUT: «foo\bar\ber\raku␤» =head2 method catfile @@ -214,33 +207,34 @@ Returns string C<「\」>, representing root directory. Defined as: - method split(IO::Spec::Win32: Cool:D $path --> List:D) + method split(IO::Spec::Win32: Cool:D $path) -Splits the given C<$path> into "volume", "dirname", and "basename" and -returns the result as a L of three L, in that order. -The "volume" is always an empty string and exists for consistency with other -L classes. +Creates a L«C|/type/IO::Path::Parts» for C<$path>. =begin code IO::Spec::Win32.split('C:/foo/bar.txt').raku.say; -# OUTPUT: «(:volume("C:"), :dirname("/foo"), :basename("bar.txt"))␤» +# OUTPUT: «IO::Path::Parts.new("C:","/foo","bar.txt")␤» IO::Spec::Win32.split('/foo/').raku.say; -# OUTPUT: «(:volume(""), :dirname("/"), :basename("foo"))␤» +# OUTPUT: «IO::Path::Parts.new("","/","foo")␤» IO::Spec::Win32.split('///').raku.say; -# OUTPUT: «(:volume(""), :dirname("/"), :basename("\\"))␤» +# OUTPUT: «IO::Path::Parts.new("","/","\\")␤» IO::Spec::Win32.split('./').raku.say; -# OUTPUT: «(:volume(""), :dirname("."), :basename("."))␤» +# OUTPUT: «IO::Path::Parts.new("",".",".")␤» IO::Spec::Win32.split('.').raku.say; -# OUTPUT: «(:volume(""), :dirname("."), :basename("."))␤» +# OUTPUT: «IO::Path::Parts.new("",".",".")␤» IO::Spec::Win32.split('').raku.say; -# OUTPUT: «(:volume(""), :dirname(""), :basename(""))␤» +# OUTPUT: «IO::Path::Parts.new("","","")␤» =end code +B: Before Rakudo version 2020.06 this method split the given +C<$path> into "volume", "dirname", and "basename" and returned the result +as a L of three L, in that order. + =head2 method splitdir Defined as: diff --git a/doc/Type/IO/Special.pod6 b/doc/Type/IO/Special.pod6 index 2054ffde4..d4e13d7fc 100644 --- a/doc/Type/IO/Special.pod6 +++ b/doc/Type/IO/Special.pod6 @@ -7,7 +7,7 @@ =for code class IO::Special does IO { } -Used as a L«C<$.path>|/type/IO::Handle#method_path>» attribute in filehandles +Used as a L«C<$.path>|/type/IO::Handle#method_path» attribute in filehandles for special standard input C<$*IN> and output C<$*OUT> and C<$*ERR>. Provides a bridged interface of L«C|/type/IO::Handle», mostly file tests and stringification. diff --git a/doc/Type/Int.pod6 b/doc/Type/Int.pod6 index 63f8e33c4..40857ddbe 100644 --- a/doc/Type/Int.pod6 +++ b/doc/Type/Int.pod6 @@ -12,7 +12,7 @@ C objects store integral numbers of arbitrary size. Cs are immutable. There are two main syntax forms for C literals 123; # Int in decimal notation - :16; # Int in radix notations + :16; # Int in radix notation For your convenience common radix forms come with a prefix shortcut. @@ -43,7 +43,7 @@ These notations allow you to use variables, too: =head1 Methods -=head method new +=head2 method new Defined as: diff --git a/doc/Type/IntStr.pod6 b/doc/Type/IntStr.pod6 index 09dfb2880..b3e8060bc 100644 --- a/doc/Type/IntStr.pod6 +++ b/doc/Type/IntStr.pod6 @@ -4,23 +4,24 @@ =SUBTITLE Dual value integer and string - class IntStr is Int is Str { } + class IntStr is Allomorph is Int { } -The dual value types (often referred to as L) -allow for the representation of a value as both a string and a numeric type. Typically -they will be created for you when the context is "stringy" but they can be determined -to be numbers, such as in some L: +C is a dual value type, a subclass of both +L«C|/type/Allomorph», hence L«C|/type/Str», and +L«C|/type/Int». - my $f = <42>; say $f.^name; # OUTPUT: «IntStr␤» +See L«C|/type/Allomorph» for further details. -As a subclass of both L«C|/type/Int» and L«C|/type/Str», an C -will be accepted where either is expected. However, C does not share -object identity with C- or C-only variants: +=begin code +my $int-str = <42>; +say $int-str.^name; # OUTPUT: «IntStr␤» - my $int-str = <42>; - my Int $int = $int-str; # OK! - my Str $str = $int-str; # OK! - say 42 ∈ <42 55 1>; # False; ∈ operator cares about object identity +my Int $int = $int-str; # OK! +my Str $str = $int-str; # OK! + +# ∈ operator cares about object identity +say 42 ∈ <42 55 1>; # OUTPUT: «False␤» +=end code =head1 Methods @@ -35,17 +36,6 @@ directly the values can be whatever is required: say +$f; # OUTPUT: «42␤» say ~$f; # OUTPUT: «"forty two"␤» -=head2 method Bool - -Defined as: - - multi method Bool(IntStr:D: --> Bool:D) - -I. - -Returns C if the invocant is numerically C<0>, otherwise returns C. String portion -is not considered. - =head2 method Int method Int @@ -72,41 +62,15 @@ Defined as: The C<:D> variant returns the numeric portion of the invocant. The C<:U> variant issues a warning about using an uninitialized value in numeric context and then returns value C<0>. -=head2 method Str - -Returns the string value of the C. - -=head2 method ACCEPTS - -Defined as: - - multi method ACCEPTS(IntStr:D: Any:D $value) - -If C<$value> is L (including another -L), checks if invocant's -L part L the C<$value>. If -C<$value> is L, checks if invocant's L part -L the C<$value>. If value is anything else, -checks if both L and L parts C the C<$value>. - - say <5> ~~ "5.0"; # OUTPUT: «False␤» - say <5> ~~ 5.0 ; # OUTPUT: «True␤» - say <5> ~~ <5.0>; # OUTPUT: «True␤» - =head1 Operators -=head2 infix cmp - - multi sub infix:(IntStr:D $a, IntStr:D $b) +=head2 infix C«===» -Compare two C objects. The comparison is done on the C value first and -then on the C value. If you want to compare in a different order then you would -coerce to an C or C value first: + multi sub infix:<===>(IntStr:D $a, IntStr:D $b) - my $f = IntStr.new(42, "smaller"); - my $g = IntStr.new(43, "larger"); - say $f cmp $g; # OUTPUT: «Less␤» - say $f.Str cmp $g.Str; # OUTPUT: «More␤» +C Value identity operator. Returns C if the C +values of C<$a> and C<$b> are L and their C +values are also L. Returns C otherwise. =end pod diff --git a/doc/Type/Iterable.pod6 b/doc/Type/Iterable.pod6 index c7d6f4f89..7d488508d 100644 --- a/doc/Type/Iterable.pod6 +++ b/doc/Type/Iterable.pod6 @@ -34,7 +34,7 @@ my $a := DNA.new('GAATCC'); This example mixes in the Iterable role to offer a new way of iterating over what is essentially a string (constrained by -L|/type/Signature#index-entry-where_clause_(Signature)> to just +L|/type/Signature#index-entry-where_clause> to just the four DNA letters). In the last statement, C actually hooks to the C role printing the letters in groups of 3. @@ -76,7 +76,7 @@ itemized sublists: say ($('a', 'b'), 'c').raku; # OUTPUT: «($("a", "b"), "c")␤» -You can use the L to +You can use the L«hyper method call|/language/operators#index-entry-methodop_>>.» to call the L«C<.List>|/routine/List» method on all the inner itemized sublists and so de-containerize them, so that C can flatten them: @@ -154,7 +154,7 @@ Returns another Iterable that is potentially iterated in parallel, with a given batch size and degree of parallelism (number of parallel workers). Unlike L«C|/routine/hyper», C does not preserve the order of -elements. +elements (mnemonic: in a race, you never know who will arrive first). say ([1..100].race.map({ $_ +1 }).list); diff --git a/doc/Type/Iterator.pod6 b/doc/Type/Iterator.pod6 index b54196963..ad2946882 100644 --- a/doc/Type/Iterator.pod6 +++ b/doc/Type/Iterator.pod6 @@ -8,10 +8,11 @@ constant IterationEnd role Iterator { } -A C is an object that can generate or provide elements of a -sequence. Users usually don't have to care about iterators, their usage -is hidden behind iteration APIs such as C, L, -L, L, L, L and list indexing with C<.[$idx]>. +A C is an object that can generate or provide elements of a sequence. +Users usually don't have to care about iterators, their usage is hidden behind +iteration APIs such as C, L, +L, L, L, +L and list indexing with C<.[$idx]>. The main API is the C method, which either returns the next value, or the sentinel value C if no more elements are @@ -26,11 +27,11 @@ Iterator role. X<|IterationEnd> =head1 IterationEnd -Iterators only allow one iteration over the entire sequence. It's -forbidden to make attempts to fetch more data, once C has -been generated, and behavior for doing so is undefined. For example, the -following L will not cause the L to be called under normal -use, because L will never be called after it returns +Iterators only allow one iteration over the entire sequence. It's forbidden to +make attempts to fetch more data, once C has been generated, and +behavior for doing so is undefined. For example, the following L +will not cause the L to be called under normal use, because +L will never be called after it returns C: =begin code @@ -60,10 +61,10 @@ for @a -> $a, $b { =end code The only valid use of the sentinel value C in a program is -identity comparison (using C<=:=>) with the result of a method in the -iterator API. Any other behavior is undefined and implementation -dependent. For instance, using it as part of a list that's going to be -iterated over might result in the loop ending, or not. +identity comparison (using L«C<=:=>|/routine/=:=») with the result of a method +in the iterator API. Any other behavior is undefined and implementation +dependent. For instance, using it as part of a list that's going to be iterated +over might result in the loop ending, or not. =for code .say for ["foo",IterationEnd, "baz"]; # OUTPUT: «foo␤» @@ -276,8 +277,8 @@ Should produce all elements from the iterator and push them to C<$target>. my @array; say (1 .. 1000).iterator.push-all(@array); # All 1000 values are pushed -The Iterator role implements this method in terms of C. As in the -case of the other C methods, it is mainly intended for developers +The C role implements this method in terms of C. As in +the case of the other C methods, it is mainly intended for developers implementing this role. C is called when assigning an object with this role to an array, for instance, like in this example: diff --git a/doc/Type/Junction.pod6 b/doc/Type/Junction.pod6 index 5317d8085..06c332f79 100644 --- a/doc/Type/Junction.pod6 +++ b/doc/Type/Junction.pod6 @@ -98,7 +98,7 @@ if a() | b() | c() { } =end code -Junctions are meant to be used as matchers in Boolean context; introspection +Junctions are meant to be used as matchers in a Boolean context; introspection of junctions is not supported. If you feel the urge to introspect a junction, use a L or a related type instead. @@ -197,7 +197,7 @@ just compute the values that work while ignoring exceptions: say try calc $j; # OUTPUT: «Nil␤» Only one value above causes an exception, but the result of the L«C -block|/language/exceptions#index-entry-try_blocks-try» is still a +block|/language/exceptions#try_blocks» is still a L. A possible way around it is to cheat and evaluate the values of the C individually and then re-create the C from the result: @@ -231,12 +231,16 @@ Defined as: multi method new(Junction: \values, Str :$type!) multi method new(Junction: Str:D \type, \values) -Constructor to define a new Junction from the type that defines a Junction and -a set of values. +These constructors build a new junction from the type that defines it and a +set of values. my $j = Junction.new(<Þor Oðinn Loki>, type => "all"); my $n = Junction.new( "one", 1..6 ) +The main difference between the two multis is how the type of the C +is passed as an argument; either positionally as the first argument, or as a +named argument using C. + =head2 method defined Defined as: @@ -291,6 +295,14 @@ L. Output methods that use C<.Str> method (L and L) are special-cased to autothread junctions, despite being able to accept a L type. +=head2 method iterator + +Defined as: + + multi method iterator(Junction:D:) + +Returns an iterator over the C converted to a C. + =head2 method gist Defined as: @@ -302,14 +314,14 @@ of the type of the junction and the L of its components: .all.say; # OUTPUT: «all(a, 42, c)␤» -=head2 method perl +=head2 method raku Defined as: - multi method perl(Junction:D:) + multi method raku(Junction:D:) Collapses the L and returns a L composed -of L of its components that L to +of L of its components that L to the equivalent L with equivalent components: .all.raku.put; # OUTPUT: «all("a", IntStr.new(42, "42"), "c")␤» @@ -331,14 +343,14 @@ my $odd = 1|3|5; my $even = 2|4|6; my $merged = $odd ~ $even; -say $merged; #OUTPUT: «any(12, 14, 16, 32, 34, 36, 52, 54, 56)␤» +say $merged; # OUTPUT: «any(12, 14, 16, 32, 34, 36, 52, 54, 56)␤» -say "Found 34!" if 34 == $merged; #OUTPUT: «Found 34!␤» +say "Found 34!" if 34 == $merged; # OUTPUT: «Found 34!␤» my $prefixed = "0" ~ $odd; -say "Found 03" if "03" == $prefixed; #OUTPUT: «Found 03!␤» +say "Found 03" if "03" == $prefixed; # OUTPUT: «Found 03!␤» my $postfixed = $odd ~ "1"; -say "Found 11" if 11 == $postfixed; #OUTPUT: «Found 11!␤» +say "Found 11" if 11 == $postfixed; # OUTPUT: «Found 11!␤» =end code On the other hand, the versions of C<~> that use a string as one argument will diff --git a/doc/Type/Label.pod6 b/doc/Type/Label.pod6 index 421274ac1..05bca8f1e 100644 --- a/doc/Type/Label.pod6 +++ b/doc/Type/Label.pod6 @@ -6,10 +6,11 @@ class Label {} -Labels are used in Raku to tag loops so that you can specify the one you want -to jump to with statements such as C. You can use it to jump out of loops -and get to outer ones, instead of just exiting the current loop or going to the -statement before. +Labels are used in Raku to tag loops so that you can specify +the one you want to jump to with L«statements such as +C|/language/control#LABELs». You can use it to jump out of loops +and get to outer ones, instead of just exiting the current loop or going +to the statement before. =begin code :skip-test USERS: # the label @@ -39,7 +40,7 @@ A: while $x++ < 2 { last A } } -say $t; # OUTPUT: «A1B1A1A2» +say $t; # OUTPUT: «A1B1A1A2␤» =end code Putting them on the line before the loop or the same line is optional. C.rotate(2); # - .rotate(-1); # + say .rotate(2); # OUTPUT: (c d e a b) + say .rotate(-1); # OUTPUT: (e a b c d) + +B: Before Rakudo version 2020.06 a new C was returned instead +of a C. =head2 routine sort diff --git a/doc/Type/Lock.pod6 b/doc/Type/Lock.pod6 index 5ba22fa86..3517e659f 100644 --- a/doc/Type/Lock.pod6 +++ b/doc/Type/Lock.pod6 @@ -53,8 +53,15 @@ Any C performed while a C is held will behave in a blocking manner; the standard non-blocking behavior of C relies on the code following the `await` resuming on a different C from the pool, which is incompatible with the requirement that a C be -unlocked by the same thread that locked it. See L -for an alternative mechanism that does not have this shortcoming. +unlocked by the same thread that locked it. See +L|/type/Lock::Async> +for an alternative mechanism that does not have this shortcoming. Other than +that, the main difference is that C mainly maps to operating system +mechanisms, while C uses Raku primitives to achieve similar +effects. If you're doing low-level stuff (native bindings) and/or actually +want to block real OS threads, use C. However, if you want a +non-blocking mutual exclusion and don't need recursion and are running code +on the Raku thread pool, use Lock::Async. By their nature, Cs are not composable, and it is possible to end up with hangs should circular dependencies on locks occur. Prefer @@ -62,13 +69,14 @@ to structure concurrent programs such that they communicate results rather than modify shared data structures, using mechanisms like L, L and L. + =head1 Methods =head2 method protect Defined as: - method protect(Lock:D: &code) + multi method protect(Lock:D: &code) Obtains the lock, runs C<&code>, and releases the lock afterwards. Care is taken to make sure the lock is released even if the code is left through @@ -154,23 +162,58 @@ calling C and C. Failing that, use a C phaser. Defined as: -=begin code :skip-test -my class ConditionVariable { - method wait(); - method signal(); - method signal_all(); -} + method condition(Lock:D: ) -method condition(Lock:D: --> ConditionVariable:D) -=end code - -Returns a condition variable. Compare -L or -L for background. +Returns a L object|/type/Lock::ConditionVariable>. +Check +L or +L +for background on condition variables and how they relate to locks and mutexes. my $l = Lock.new; $l.condition; +You should use a condition over a lock when you want an interaction with it +that is a bit more complex than simply acquiring or releasing the lock. + +=begin code +constant ITEMS = 100; +my $lock = Lock.new; +my $cond = $lock.condition; +my $todo = 0; +my $done = 0; +my @in = 1..ITEMS; +my @out = 0 xx ITEMS; + +loop ( my $i = 0; $i < @in; $i++ ) { + my $in := @in[$i]; + my $out := @out[$i]; + Thread.start( { + my $partial = $in² +1; + if $partial.is-prime { + $out = $partial but "Prime"; + } else { + $out = $partial; + } + $lock.protect( { + $done++; + $cond.signal if $done == $todo; + } ); + } ); + $todo++; +} +$lock.protect( { + $cond.wait({ $done == $todo } ); +}); + +say @out.map: { $_.^roles > 2 ?? $_.Num ~ "*" !! $_ }; +# OUTPUT: «2* 5* 10 17* 26 37* 50 65 82 101* … » +=end code + +In this case, we use the condition variable C<$cond> to wait until all +numbers have been generated and checked and also to C<.signal> to another +thread to wake up when the particular thread is done. + =end pod # vim: expandtab softtabstop=4 shiftwidth=4 ft=perl6 diff --git a/doc/Type/Lock/Async.pod6 b/doc/Type/Lock/Async.pod6 index 30a68a2f6..04cde42e6 100644 --- a/doc/Type/Lock/Async.pod6 +++ b/doc/Type/Lock/Async.pod6 @@ -6,18 +6,18 @@ class Lock::Async {} -A C instance provides a mutual exclusion mechanism: when the -lock is held, any other code wishing to C must wait until the holder -calls C, which helps against all kinds of issues resulting from -data being read and modified simultaneously from different threads. +A C instance provides a mutual exclusion mechanism: when the lock +is held, any other code wishing to C must wait until the holder calls +C on it, which helps against all kinds of issues resulting from data +being read and modified simultaneously from different threads. Unlike L, which provides a traditional OS-backed mutual exclusion mechanism, C works with the high-level concurrency -features of Raku. The C method returns a C, which will -be kept when the lock is available. This C can be used with -non-blocking C. This means that a thread from the thread pool need -not be consumed while waiting for the C to be available, -and the code trying to obtain the lock will be resumed once it is available. +features of Raku. The C method returns a L|/type/Promise>, +which will be kept when the lock is available. This C can be used with +non-blocking C. This means that a thread from the thread pool need not be +consumed while waiting for the C to be available, and the code +trying to obtain the lock will be resumed once it is available. The result is that it's quite possible to have many thousands of outstanding C lock requests, but just a small number of threads in the @@ -107,30 +107,30 @@ protect the code we want to protect. Modifying an Array I from different in the second example is not safe and leads to memory errors. =begin code :preamble - # Compute how many prime numbers there are in first 10 000 of them - # using 50 threads - my @primes = 0 .. 10_000; - my @results; - my @threads; - - # Right: $lock is instantiated outside the portion of the - # code that will get threaded and be in need of protection, - # so all threads share the lock - my $lock = Lock::Async.new; - for ^50 -> $thread { - @threads.push: start { - $lock.protect: { - my $from = $thread * 200; - my $to = ($thread + 1) * 200; - @results.append: @primes[$from..$to].map(*.is-prime); - } +# Compute how many prime numbers there are in first 10 000 of them +# using 50 threads +my @primes = 0 .. 10_000; +my @results; +my @threads; + +# Right: $lock is instantiated outside the portion of the +# code that will get threaded and be in need of protection, +# so all threads share the lock +my $lock = Lock::Async.new; +for ^50 -> $thread { + @threads.push: start { + $lock.protect: { + my $from = $thread * 200; + my $to = ($thread + 1) * 200; + @results.append: @primes[$from..$to].map(*.is-prime); } } +} - # await for all threads to finish calculation - await Promise.allof(@writers); - # say how many prime numbers we found - say "We found " ~ @results.grep(*.value).elems ~ " prime numbers"; +# await for all threads to finish calculation +await Promise.allof(@writers); +# say how many prime numbers we found +say "We found " ~ @results.grep(*.value).elems ~ " prime numbers"; =end code The example below demonstrates the wrong approach: without proper locking @@ -138,19 +138,19 @@ this code will work most of the time, but occasionally will result in bogus error messages or low-level memory errors: =begin code :preamble - # !!! WRONG !!! Lock::Async is instantiated inside threaded area, - # so all the 20 threads use 20 different locks, not syncing with - # each other - for ^50 -> $thread { - @threads.push: start { - my $lock = Lock::Async.new; - $lock.protect: { - my $from = $thread * 200; - my $to = ($thread + 1) * 200; - @results.append: @primes[$from..$to].map(*.is-prime); - } +# !!! WRONG !!! Lock::Async is instantiated inside threaded area, +# so all the 20 threads use 20 different locks, not syncing with +# each other +for ^50 -> $thread { + @threads.push: start { + my $lock = Lock::Async.new; + $lock.protect: { + my $from = $thread * 200; + my $to = ($thread + 1) * 200; + @results.append: @primes[$from..$to].map(*.is-prime); } } +} =end code =head2 method protect-or-queue-on-recursion @@ -206,7 +206,7 @@ Defined as: Temporarily resets the Lock::Async recursion list so that it no longer includes the lock this method is called on and runs the given C<&code> immediately if the call to the method occurred in a caller chain where -L +L has already been called and the lock has been placed on the recursion list. my Lock::Async $lock .= new; diff --git a/doc/Type/Lock/ConditionVariable.pod6 b/doc/Type/Lock/ConditionVariable.pod6 new file mode 100644 index 000000000..df3a12ce3 --- /dev/null +++ b/doc/Type/Lock/ConditionVariable.pod6 @@ -0,0 +1,109 @@ +=begin pod :kind("Type") :subkind("class") :category("domain-specific") + +=TITLE class Lock::ConditionVariable + +=SUBTITLE Condition variables used in locks + + class Lock::ConditionVariable {} + +Condition variables are used in Ls|/type/Lock> to wait for a +particular condition to become true. You will normally not create one from +scratch, but call L|/type/Lock#method_condition> to acquire +one on a particular C. + +=head1 Methods + +=head2 method wait + +Defined as: + + multi method wait( --> Nil ) + multi method wait( &predicate --> Nil ) + +Without any predicate, it waits on the condition variable itself; with a +predicate, waits until the code returns a truish value. + +=begin code + my $times = 100; + my $tried; + my $failed; + for ^$times { + my $l = Lock.new; + my $c = $l.condition; + my $now1; + my $now2; + my $counter = 0; + my $t1 = Thread.start({ + $l.protect({ + $c.wait( { $counter != 0 } ); + $now1 = now; + }); + }); + + my $t2 = Thread.start({ + $l.protect({ + $counter++; + $c.signal(); + }); + }); + + $t1.join(); + $now2 = now; + $t2.join(); + + $tried++; + last if $failed = ( !$now1.defined or $now1 > $now2 ); + } +=end code + +The condition we obtain from the C<$l> lock is awaited using a predicate, in +this case, check if the counter is still zero. When it takes another value, +the program flow continues in the next instruction. + +=head2 method signal + +Defined as: + + method signal() + +If and only if there are any threads that have previously waited on the +condition variable, it unblocks at least one of them. Let's see how it works +in this example: + +=begin code +constant ITEMS = 100; +for 1..15 -> $iter { + my $lock = Lock.new; + my $cond = $lock.condition; + my $todo = 0; + my $done = 0; + my @in = 1..ITEMS; + my @out = 0 xx ITEMS; + + for 1..ITEMS -> $i { + my $in = $i; + my $out := @out[$i]; + Thread.start( { + $out = $in * 10; + $lock.protect( { + $done++; + $cond.signal if $done == $todo; + } ); + } ); + $todo++; + } + $lock.protect( { + $cond.wait({ $done == $todo } ); + }); + say @out; +} +=end code + +We are repeating 15 times the same operation: start 100 threads, every one of +which modify a single element in an array. We C the modification of +a global variable, C<$done>, and use C to wake a up another thread to +do its thing. This outputs the first elements of the generated arrays. + +=end pod + +# vim: expandtab softtabstop=4 shiftwidth=4 ft=perl6 diff --git a/doc/Type/Map.pod6 b/doc/Type/Map.pod6 index 08d4abe87..dda92b152 100644 --- a/doc/Type/Map.pod6 +++ b/doc/Type/Map.pod6 @@ -44,7 +44,7 @@ a C has been initialized: $m{ 'c' } = 'foo'; # WRONG! # Cannot modify an immutable Str -Unlike its mutable companion type L, Map cannot be parameterized by key or value types. +Unlike its mutable companion type L, a Map cannot be parameterized by key or value types. =head1 Methods @@ -56,17 +56,21 @@ Defined as: Creates a new Map from a list of alternating keys and values, with L as described -in the L documentation, B -for literal pair handling. To ensure pairs correctly get passed, add -extra parentheses around all the arguments. +in the L documentation, but also +accepts Cs instead of separate keys and values. Use the +L or quote the key to +ensure that a literal pair is not interpreted as a named argument. my %h = Map.new('a', 1, 'b', 2); # WRONG: :b(2) interpreted as named argument - say Map.new('a', 1, :b(2) ).keys; # OUTPUT: «(a)␤» + say Map.new('a', 1, :b(2)).keys; # OUTPUT: «(a)␤» - # RIGHT: :b(2) interpreted as part of Map's contents - say Map.new( ('a', 1, :b(2)) ).keys; # OUTPUT: «(a b)␤» + # RIGHT: :b(2) interpreted as Pair because of extra parentheses + say Map.new( ('a', 1, :b(2)) ).keys.sort; # OUTPUT: «(a b)␤» + + # RIGHT: 'b' => 2 always creates a Pair + say Map.new('a', 1, 'b' => 2).keys.sort; # OUTPUT: «(a b)␤» A shorthand syntax for creating Maps is provided: @@ -193,9 +197,9 @@ Returns a C of keys and values interleaved. Defined as: - method list(Map:D: --> List:D) + multi method list(Map:D: --> List:D) -Returns a C of all keys and values in the Map. +Returns a C of L objects of all keys and values in the Map. my $m = Map.new('a' => (2, 3), 'b' => 17); say $m.list; # OUTPUT: «(b => 17 a => (2 3))␤» diff --git a/doc/Type/Match.pod6 b/doc/Type/Match.pod6 index c0c665942..67a2ff4cb 100644 --- a/doc/Type/Match.pod6 +++ b/doc/Type/Match.pod6 @@ -160,7 +160,7 @@ operates, by default, on C<$/>, that example is equivalent to: This is typically used in a L's actions class methods, where a piece of data is stored by one method and then later retrieved by another. It's up to you what data you store. It could be a tree node, L, a type object, or a list of +of a calculation|/language/grammars#Proto_regexes>, a type object, or a list of values. The sub form operates on the current Match C<$/>, which can be a convenient shortcut: diff --git a/doc/Type/Metamodel/AttributeContainer.pod6 b/doc/Type/Metamodel/AttributeContainer.pod6 index 809f8788a..f8cd304c5 100644 --- a/doc/Type/Metamodel/AttributeContainer.pod6 +++ b/doc/Type/Metamodel/AttributeContainer.pod6 @@ -16,7 +16,7 @@ attributes is implemented by this role. =head2 method add_attribute - method add_attribute(Metamodel::AttributeContainer: $obj, $attribute) + method add_attribute($obj, $attribute) Adds an attribute. C<$attribute> must be an object that supports the methods C, C and C, which are called without arguments. @@ -24,14 +24,14 @@ It can for example be of L. =head2 method attributes - method attributes(Metamodel::AttributeContainer: $obj) + method attributes($obj) Returns a list of attributes. For most Raku types, these will be objects of L. =head2 method set_rw - method set_rw(Metamodel::AttributeContainer: $obj) + method set_rw($obj) Marks a type whose attributes default to having a write accessor. For example in @@ -51,7 +51,7 @@ $p.x = 42; =head2 method rw - method rw(Metamodel::AttributeContainer: $obj) + method rw($obj) Returns a true value if L has been called on this object, that is, if new public attributes are writable by default. diff --git a/doc/Type/Metamodel/ClassHOW.pod6 b/doc/Type/Metamodel/ClassHOW.pod6 index bd5d17374..4c3243089 100644 --- a/doc/Type/Metamodel/ClassHOW.pod6 +++ b/doc/Type/Metamodel/ClassHOW.pod6 @@ -41,7 +41,7 @@ C is the metaclass behind the C keyword. =head2 method add_fallback - method add_fallback(Metamodel::ClassHOW:D: $obj, $condition, $calculator) + method add_fallback($obj, $condition, $calculator) Installs a method fallback, that is, add a way to call methods that weren't statically added. @@ -63,7 +63,7 @@ method C instead. =head2 method can - method can(Metamodel::ClassHOW:D: $obj, $method-name) + method can($obj, $method-name) Given a method name, it returns a L of methods that are available with this name. @@ -83,7 +83,7 @@ C<$a>). =head2 method lookup - method lookup(Metamodel::ClassHOW:D: $obj, $method-name --> Method:D) + method lookup($obj, $method-name --> Method:D) Returns the first matching L with the provided name. If no method was found, returns a VM-specific sentinel value (typically a low-level @@ -91,6 +91,7 @@ NULL value) that can be tested for with a test for L. It is potentially faster than C<.^can> but does not provide a full list of all candidates. +=begin code :solo say Str.^lookup('Int').raku; # OUTPUT: «method Int (Str:D $: *%_) { #`(Method|39910024) ... }␤» for { @@ -100,10 +101,11 @@ not provide a full list of all candidates. # OUTPUT: # method `upper-case` not found # FOO +=end code =head2 method compose - method compose(Metamodel::ClassHOW:D: $obj) + method compose($obj) A call to C brings the metaobject and thus the class it represents into a fully functional state, so if you construct or modify a class, you must diff --git a/doc/Type/Metamodel/Finalization.pod6 b/doc/Type/Metamodel/Finalization.pod6 index 8f759c961..107aaa206 100644 --- a/doc/Type/Metamodel/Finalization.pod6 +++ b/doc/Type/Metamodel/Finalization.pod6 @@ -18,7 +18,7 @@ exist) when an object is garbage-collected. =head2 method setup_finalization - method setup_finalization(Metamodel::Finalization:D: $obj) + method setup_finalization($obj) Collects the C submethods from this class and all its superclasses, and marks the class as needing action on garbage @@ -29,7 +29,7 @@ this method at type composition time. =head2 method destroyers - method destroyers(Metamodel::Finalization:D: $obj --> List:D) + method destroyers($obj --> List:D) Returns a list of all finalization methods. diff --git a/doc/Type/Metamodel/MROBasedMethodDispatch.pod6 b/doc/Type/Metamodel/MROBasedMethodDispatch.pod6 index 489db1f7b..473e96b3a 100644 --- a/doc/Type/Metamodel/MROBasedMethodDispatch.pod6 +++ b/doc/Type/Metamodel/MROBasedMethodDispatch.pod6 @@ -23,13 +23,15 @@ in the method resolution order (MRO). If no method can be found, it returns a VM-specific sentinel value (typically a low-level NULL value) that can be tested for with a test for L: - for { - Str.^find_method: $^meth andthen .("foo").say - orelse "method `$meth` not found".say - } - # OUTPUT: - # method `upper-case` not found - # FOO +=begin code :solo +for { + Str.^find_method: $^meth andthen .("foo").say + orelse "method `$meth` not found".say +} +# OUTPUT: +# method `upper-case` not found +# FOO +=end code If C<:no_fallback> is supplied, fallback methods are not considered. diff --git a/doc/Type/Metamodel/MethodContainer.pod6 b/doc/Type/Metamodel/MethodContainer.pod6 index 43b823379..0a4345959 100644 --- a/doc/Type/Metamodel/MethodContainer.pod6 +++ b/doc/Type/Metamodel/MethodContainer.pod6 @@ -23,14 +23,14 @@ the API around storing and introspecting them. =head2 method add_method - method add_method(Metamodel::MethodContainer: $obj, $name, $code) + method add_method($obj, $name, $code) Adds a method to the metaclass, to be called with name C<$name>. This should only be done before a type is composed. =head2 method methods - method methods(Metamodel::MethodContainer: $obj, :$all, :$local) + method methods($obj, :$all, :$local) Returns a list of public methods available on the class (which includes methods from superclasses and roles). By default this stops at the classes @@ -53,7 +53,7 @@ at the grammar level and will likely remain so for bootstrap reasons. =head2 method method_table - method method_table(Metamodel::MethodContainer:D: $obj --> Hash:D) + method method_table($obj --> Hash:D) Returns a hash where the keys are method names, and the values are L. Note that the keys are the names by which the methods @@ -61,7 +61,7 @@ can be called, not necessarily the names by which the methods know themselves. =head2 method lookup - method lookup(Metamodel::MethodContainer: $obj, $name --> Method) + method lookup($obj, $name --> Method) Returns the first matching L object of the provided C<$name> or C<(Mu)> if no method object was found. The search for a matching method object diff --git a/doc/Type/Metamodel/MultipleInheritance.pod6 b/doc/Type/Metamodel/MultipleInheritance.pod6 index c4dfd06b8..645d2af8c 100644 --- a/doc/Type/Metamodel/MultipleInheritance.pod6 +++ b/doc/Type/Metamodel/MultipleInheritance.pod6 @@ -22,13 +22,13 @@ ignores it. This can come in two flavors: methods from a class marked as C, but hides it from the method resolution order, -so that L skips it. +so that L skips it. =head1 Methods =head2 method add_parent - method add_parent(Metamodel::MultipleInheritance:D: $Obj, $parent, :$hides) + method add_parent($obj, $parent, :$hides) Adds C<$parent> as a parent type. If C<$hides> is set to a true value, the parent type is added as a hidden parent. @@ -40,7 +40,7 @@ is thrown. =head2 method parents - method parents(Metamodel::MultipleInheritance:D: $obj, :$all, :$tree) + method parents($obj, :$all, :$tree) Returns the list of parent classes. By default it stops at L, L or L, which you can suppress by supplying the C<:all> adverb. With C<:tree>, @@ -59,20 +59,20 @@ a nested list is returned. =head2 method hides - method hides(Metamodel::MultipleInheritance:D: $obj) + method hides($obj) Returns a list of all hidden parent classes. =head2 method hidden - method hidden(Metamodel::MultipleInheritance:D: $obj) + method hidden($obj) Returns a true value if (and only if) the class is marked with the trait C); # OUTPUT: «Int␤» +Please note that the main difference between methods defined within and +without a class is the need to use `&` to invoke them in the latter case. In +case any other sigil is used in the definition, as in the first example, that +sigil can also be used. + X<|extra named arguments> Methods automatically capture extra named arguments into the special variable C<%_>, where other types of C will throw at runtime. So @@ -44,8 +49,8 @@ is actually equivalent to method x(*%_) {} -Extra arguments will be forwarded by -L and friends. +Extra arguments will be forwarded by L«C and +friends|/language/functions#Re-dispatching». class A { multi method m(:$a, :$b) { say "2 named" } @@ -57,51 +62,6 @@ L and friends. B.m( :1a, :2b ); # OUTPUT: «1 named␤2 named␤» -=head2 sub lastcall - - sub lastcall(--> True) - -Truncates the current dispatch chain, which means any calls to -C, C, C, and C will not -find any of the next candidates. Note that since C -restarts the dispatch from the start, it's not affected by the -truncation of current chain with C. - -Consider example below. C uses C -when C hasn't been called, and so it reaches the C -candidate. C calls C as well, but since -C was called first, the dispatch chain was truncated and -the C candidate was not reached. The last call, C, -calls C too, however, it then uses C, which -isn't affected by it, and so the dispatch re-starts from scratch, -hits the C candidate with the new argument C<6>, and then -proceeds to the C candidate via C (which -isn't affected by the C that was used before the -C was called): - - multi foo (Int $_) { - say "Int: $_"; - lastcall when *.is-prime; - nextsame when * %% 2; - samewith 6 when * !%% 2; - } - multi foo (Any $x) { say "Any $x" } - - foo 6; say '----'; - foo 2; say '----'; - foo 1; - - # OUTPUT: - # Int: 6 - # Any 6 - # ---- - # Int: 2 - # ---- - # Int: 1 - # Int: 6 - # Any 6 - - =end pod # vim: expandtab softtabstop=4 shiftwidth=4 ft=perl6 diff --git a/doc/Type/Mix.pod6 b/doc/Type/Mix.pod6 index df0c24085..cce45894c 100644 --- a/doc/Type/Mix.pod6 +++ b/doc/Type/Mix.pod6 @@ -150,6 +150,15 @@ I: This method is inherited from L, however, Ces do not have an inherent order and you should not trust it returning a consistent output. +=head2 method total + + method total(Mix:D: --> Real) + +Returns the sum of all the weights + + say mix('a', 'b', 'c', 'a', 'a', 'd').total == 6; # OUTPUT: «True␤» + say %(a => 5.6, b => 2.4).Mix.total == 8; # OUTPUT: «True␤» + =head2 Note on order Same as the other elements in the L, diff --git a/doc/Type/Mixy.pod6 b/doc/Type/Mixy.pod6 index dc7624bfc..dee3e2793 100644 --- a/doc/Type/Mixy.pod6 +++ b/doc/Type/Mixy.pod6 @@ -12,15 +12,6 @@ C are Ls rather than Ls. =head1 Methods -=head2 method total - - method total(--> Real) - -Returns the sum of all the weights - - say mix('a', 'b', 'c', 'a', 'a', 'd').total == 6; # OUTPUT: «True␤» - say %(a => 5.6, b => 2.4).Mix.total == 8; # OUTPUT: «True␤» - =head2 method roll method roll($count = 1) diff --git a/doc/Type/Mu.pod6 b/doc/Type/Mu.pod6 index 3bad889a5..ef476020c 100644 --- a/doc/Type/Mu.pod6 +++ b/doc/Type/Mu.pod6 @@ -158,7 +158,7 @@ Returns a string representation of the invocant, optimized for fast recognition by humans. As such lists will be truncated at 100 elements. Use C<.raku> to get all elements. -The default C method in C re-dispatches to the L +The default C method in C re-dispatches to the L method for defined invocants, and returns the type name in parenthesis for type object invocants. Many built-in classes override the case of instances to something more specific that may truncate output. @@ -171,14 +171,11 @@ $something> and C generally produce the same output. =head2 method perl - multi method perl(Mu: --> Str) + multi method perl(Mu:) -Returns a Raku-ish representation of the object (i.e., can usually be -re-evaluated with L to regenerate the object). The exact -output of C is implementation specific, since there are generally many -ways to write a Raku expression that produces a particular value. Since the -change of name to Raku, this method is deprecated and might disappear in the -near future. Use C<.raku> instead. +Calls L«C<.raku>|/routine/raku» on the invocant. Since the change of the +language name to Raku, this method is deprecated and might disappear in +the near future. Use C<.raku> instead. =head2 method raku @@ -186,12 +183,12 @@ near future. Use C<.raku> instead. multi method raku(Mu:D:) For type objects, returns its name if C<.raku> has not been redefined from -Mu, or calls C<.raku> on the name of the type object otherwise. +C, or calls C<.raku> on the name of the type object otherwise. say Str.raku; # OUTPUT: «Str␤» For plain objects, it will conventionally return a representation of the object -that can be used via EVAL to reconstruct the value of the object. +that can be used via L«C|/routine/EVAL» to reconstruct the value of the object. say (1..3).Set.raku; # OUTPUT: «Set.new(1,2,3)␤» diff --git a/doc/Type/Nil.pod6 b/doc/Type/Nil.pod6 index e5204fd7d..9820ce095 100644 --- a/doc/Type/Nil.pod6 +++ b/doc/Type/Nil.pod6 @@ -36,7 +36,7 @@ that use a bare C statement. In a list, C takes the space of one value. Iterating C behaves like iteration of any non-iterable value, producing a sequence of one C. (When you need the other meaning, the special value -L is available to take no spaces when inserted into +L is available to take no spaces when inserted into list, and to return no values when iterated.) (1, Nil, 3).elems.say; # OUTPUT: «3␤» diff --git a/doc/Type/Num.pod6 b/doc/Type/Num.pod6 index a313aa81a..6be891afa 100644 --- a/doc/Type/Num.pod6 +++ b/doc/Type/Num.pod6 @@ -79,8 +79,8 @@ Defined as multi method new() multi method new($n) -C without argument will create a Num with the value C<0e0>. With an -argument, it will be coerced to Num and then returned. +C without argument will create a C with the value C<0e0>. With an +argument, it will be coerced to C and then returned. say Num.new(⅓); # OUTPUT: «0.3333333333333333␤» @@ -95,7 +95,7 @@ Returns a pseudo random number between 0 and the invocant. sub srand(Int $seed --> Int:D) -Seeds the pseudo random number generator used by L with +Seeds the pseudo random number generator used by L with the provided value. Note that C is called with a platform dependent value when a Raku program is started. @@ -107,7 +107,7 @@ Defined as: Throws C. -=head2 Int +=head2 method Int method Int(Num:D:) @@ -115,7 +115,7 @@ Converts the number to an L. L with C if the invocant L«is a C|/routine/isNaN» or C/C<-Inf>. No L is performed. -=head2 Rat +=head2 method Rat method Rat(Num:D: Real $epsilon = 1e-6) @@ -123,7 +123,7 @@ Converts the number to a L with C<$epsilon> precision. If the inv is a C, C<-Inf>, or a C, converts them to a L with C<0> L and C<1>, C<-1>, or C<0> L, respectively. -=head2 FatRat +=head2 method FatRat method FatRat(Num:D: Real $epsilon = 1e-6) @@ -131,6 +131,25 @@ Converts the number to a L with the precision C<$epsilon>. is a C, C<-Inf>, or a C, converts them to a L with C<0> L and C<1>, C<-1>, or C<0> L, respectively. +=head2 method Num + + method Num() + +Returns the invocant. + +=head2 method Str + + method Str(Int:D) + +Returns a string representation of the number. + + say π.Str; # OUTPUT: «3.141592653589793␤» + +L«C|/type/Cool» being a parent class of C, an explicit call +to the C method is seldom needed. + + say π.Str.comb == π.comb; # OUTPUT: «True␤» + =head2 method Bridge Defined as: diff --git a/doc/Type/NumStr.pod6 b/doc/Type/NumStr.pod6 index 2342df92f..a3f680137 100644 --- a/doc/Type/NumStr.pod6 +++ b/doc/Type/NumStr.pod6 @@ -4,23 +4,24 @@ =SUBTITLE Dual value floating-point number and string - class NumStr is Num is Str { } + class NumStr is Allomorph is Num { } -The dual value types (often referred to as L) -allow for the representation of a value as both a string and a numeric type. Typically -they will be created for you when the context is "stringy" but they can be determined -to be numbers, such as in some L: +C is a dual value type, a subclass of both +L«C|/type/Allomorph», hence L«C|/type/Str», and +L«C|/type/Num». - my $f = <42.1e0>; say $f.^name; # OUTPUT: «NumStr␤» +See L«C|/type/Allomorph» for further details. -As a subclass of both L«C|/type/Num» and L«C|/type/Str», a C -will be accepted where either is expected. However, C does not share -object identity with C- or C-only variants: +=begin code +my $num-str = <42.1e0>; +say $num-str.^name; # OUTPUT: «NumStr␤» - my $num-str = <42e10>; - my Num $num = $num-str; # OK! - my Str $str = $num-str; # OK! - say 42e10 ∈ <42e10 55 1>; # False; ∈ operator cares about object identity +my Num $num = $num-str; # OK! +my Str $str = $num-str; # OK! + +# ∈ operator cares about object identity +say 42e10 ∈ <42e10 55 1>; # OUTPUT: «False␤» +=end code =head1 Methods @@ -35,17 +36,6 @@ directly the values can be whatever is required: say +$f; # OUTPUT: «42.1␤» say ~$f; # OUTPUT: «"forty two and a bit"␤» -=head2 method Bool - -Defined as: - - multi method Bool(NumStr:D: --> Bool:D) - -I. - -Returns C if the invocant is numerically C<±0e0>, otherwise returns C. String portion -is not considered. - =head2 method Num method Num @@ -72,41 +62,15 @@ Defined as: The C<:D> variant returns the numeric portion of the invocant. The C<:U> variant issues a warning about using an uninitialized value in numeric context and then returns value C<0e0>. -=head2 method Str - -Returns the string value of the C. - -=head2 method ACCEPTS - -Defined as: - - multi method ACCEPTS(NumStr:D: Any:D $value) - -If C<$value> is L (including another -L), checks if invocant's -L part L the C<$value>. If -C<$value> is L, checks if invocant's L part -L the C<$value>. If value is anything else, -checks if both L and L parts C the C<$value>. - - say <5e0> ~~ "5.0"; # OUTPUT: «False␤» - say <5e0> ~~ 5.0 ; # OUTPUT: «True␤» - say <5e0> ~~ <5.0>; # OUTPUT: «True␤» - =head1 Operators -=head2 infix cmp - - multi sub infix:(NumStr:D $a, NumStr:D $b) +=head2 infix C«===» -Compare two C objects. The comparison is done on the C value first and -then on the C value. If you want to compare in a different order then you would -coerce to a C or C value first: + multi sub infix:<===>(NumStr:D $a, NumStr:D $b) - my $f = NumStr.new(42.1e0, "smaller"); - my $g = NumStr.new(43.1e0, "larger"); - say $f cmp $g; # OUTPUT: «Less␤» - say $f.Str cmp $g.Str; # OUTPUT: «More␤» +C Value identity operator. Returns C if the C +values of C<$a> and C<$b> are L and their C +values are also L. Returns C otherwise. =end pod diff --git a/doc/Type/Numeric.pod6 b/doc/Type/Numeric.pod6 index 555949888..202bb33e0 100644 --- a/doc/Type/Numeric.pod6 +++ b/doc/Type/Numeric.pod6 @@ -35,29 +35,6 @@ Defined as: The C<:D> variant simply returns the invocant. The C<:U> variant issues a warning about using an uninitialized value in numeric context and then returns C. -=head2 method Int - - method Int(Numeric:D: --> Int:D) - -If this C is equivalent to a C, return the equivalent of -calling C on that C to get an C. Fail with -C otherwise. - -=head2 method Rat - - method Rat(Numeric:D: Real $epsilon = 1.0e-6 --> Rat:D) - -If this C is equivalent to a C, return a C which is -within C<$epsilon> of that C's value. Fail with C -otherwise. - -=head2 method Num - - method Num(Numeric:D: --> Num:D) - -If this C is equivalent to a C, return that C as a C -as accurately as is possible. Fail with C otherwise. - =head2 method narrow method narrow(Numeric:D --> Numeric:D) diff --git a/doc/Type/Pair.pod6 b/doc/Type/Pair.pod6 index 536f3efc5..8f9b17339 100644 --- a/doc/Type/Pair.pod6 +++ b/doc/Type/Pair.pod6 @@ -176,9 +176,9 @@ Defined as: Returns a new C object with key and value exchanged. - my $p = (6 => 'Perl').antipair; - say $p.key; # OUTPUT: «Perl␤» - say $p.value; # OUTPUT: «6␤» + my $p = (d => 'Raku').antipair; + say $p.key; # OUTPUT: «Raku␤» + say $p.value; # OUTPUT: «d␤» =head2 method key @@ -188,8 +188,8 @@ Defined as: Returns the I part of the C. - my $p = (Perl => 6); - say $p.key; # OUTPUT: «Perl␤» + my $p = (Raku => "d"); + say $p.key; # OUTPUT: «Raku␤» =head2 method value @@ -199,8 +199,8 @@ Defined as: Returns the I part of the C. - my $p = (Perl => 6); - say $p.value; # OUTPUT: «6␤» + my $p = (Raku => "d"); + say $p.value; # OUTPUT: «d␤» =head2 infix cmp @@ -241,9 +241,9 @@ C, in that order. This method is a special case of the same-named method on C, which returns all its entries as a list of keys and values. - my $p = (Perl => 6); - say $p.kv[0]; # OUTPUT: «Perl␤» - say $p.kv[1]; # OUTPUT: «6␤» + my $p = (Raku => "d"); + say $p.kv[0]; # OUTPUT: «Raku␤» + say $p.kv[1]; # OUTPUT: «d␤» =head2 method pairs @@ -253,9 +253,9 @@ Defined as: Returns a list of one C, namely this one. - my $p = (Perl => 6); + my $p = (Raku => "d"); say $p.pairs.^name; # OUTPUT: «List␤» - say $p.pairs[0]; # OUTPUT: «Perl => 6␤» + say $p.pairs[0]; # OUTPUT: «Raku => d␤» =head2 method antipairs @@ -266,9 +266,9 @@ Defined as: Returns a L containing the L of the invocant. - my $p = (6 => 'Perl').antipairs; + my $p = (d => 'Raku').antipairs; say $p.^name; # OUTPUT: «List␤» - say $p.first; # OUTPUT: «Perl => 6␤» + say $p.first; # OUTPUT: «Raku => d␤» say $p.first.^name; # OUTPUT: «Pair␤» =head2 method invert @@ -289,8 +289,8 @@ will contain the same number of Ls as items in the C<.value>, w of those items a C<.key> of a pair and the C<.key> of the invocant the C<.value> of that pair: - :foo.invert.raku.say; - # OUTPUT: «(:Perl("foo"), :is("foo"), :great("foo")).Seq» + :foo.invert.raku.say; + # OUTPUT: «(:Raku("foo"), :is("foo"), :great("foo")).Seq» :foo{ :42a, :72b }.invert.raku.say; # OUTPUT: «((:a(42)) => "foo", (:b(72)) => "foo").Seq» @@ -307,7 +307,7 @@ Defined as: Returns a L containing the L of the invocant. - say ('Perl' => 6).keys; # OUTPUT: «(Perl)␤» + say (Raku => "d").keys; # OUTPUT: «(Raku)␤» =head2 method values @@ -318,7 +318,7 @@ Defined as: Returns a L containing the L of the invocant. - say ('Perl' => 6).values; # OUTPUT: «(6)␤» + say (Raku => "d").values; # OUTPUT: «(d)␤» =head2 method freeze diff --git a/doc/Type/Parameter.pod6 b/doc/Type/Parameter.pod6 index 62108ce18..0db2e7c74 100644 --- a/doc/Type/Parameter.pod6 +++ b/doc/Type/Parameter.pod6 @@ -22,14 +22,49 @@ on what most of the concepts related to parameters mean. =head2 method name -Returns the variable name, which includes all sigils and twigils. +Defined as: + + method name(Parameter:D: --> Str:D) + +Returns the parameter name, which includes +all L and +L. This name is used internally when applied to code, or in a declaration to determine the declared the name. This name is not necessarily usable by a caller – if it is, it will also appear as an L. Often, the name will be chosen descriptively as a form of self-documentation. -If the parameter is anonymous, C will be returned. +If the parameter is anonymous, an empty string will be returned. + +B Before Rakudo version 2020.08 the return value for an anonymous +parameter was C. + +=for code +my Signature $sig = :(Str $x, Bool); +say $sig.params[0].name; # OUTPUT: «$x␤» +say $sig.params[1].name; # OUTPUT: «␤» + +=head2 method usage-name + +Defined as: + + method usage-name(Parameter:D: --> Str:D) + +Returns the parameter name without any +L and +L. + +If the parameter is anonymous, an empty string will be returned. + +B Before Rakudo version 2020.08 the return value for an anonymous +parameter was C. + +=for code +my Signature $sig = :(Str $x, Str @*l, Bool); +say $sig.params[0].usage-name; # OUTPUT: «x␤» +say $sig.params[1].usage-name; # OUTPUT: «l␤» +say $sig.params[2].usage-name; # OUTPUT: «␤» =head2 method sigil @@ -39,7 +74,7 @@ Defined as: Returns a string containing the parameter's sigil, for a looser definition of "sigil" than what is considered part of -the variable's C. Still returns a sigil even +the parameter's L«C|#method name». Still returns a sigil even if the parameter is anonymous. This "sigil" is actually an introspection used to help determine @@ -114,7 +149,7 @@ Defined as: method slurpy(Parameter:D: --> Bool:D) Returns C for -L. +L. =head2 method twigil @@ -131,7 +166,7 @@ Defined as: method optional(Parameter:D: --> Bool:D) Returns C for -L. +L. =head2 method raw @@ -147,7 +182,7 @@ Returns C for raw parameters. say $sig.params[$_].raw; } } - f(17, "4711", 42); OUTPUT: «False␤True␤True␤» + f(17, "4711", 42); # OUTPUT: «False␤True␤True␤» Raw parameters bind either a variable or a value passed to it, with no decontainerization taking place. That means that if a variable was passed @@ -167,7 +202,7 @@ as it is only used on the parameter. # OUTPUT: «X::Assignment::RO: Cannot modify an immutable Int␤» Other parameters may become raw through use of the 'C' -L. These still use +L. These still use their sigil in code. sub f($x is raw) { @@ -208,7 +243,7 @@ Defined as: method rw(Parameter:D: --> Bool:D) -Returns C for L|/type/Signature#Parameter_Traits_and_Modifiers> +Returns C for L|/type/Signature#Parameter_traits_and_modifiers> parameters. my Signature $sig = :(Str $x is rw, Bool :$is-named); @@ -221,7 +256,7 @@ Defined as: method copy(Parameter:D: --> Bool:D) -Returns C for L|/type/Signature#Parameter_Traits_and_Modifiers> +Returns C for L|/type/Signature#Parameter_traits_and_modifiers> parameters. my Signature $sig = :(Str $x, Bool :$is-named is copy); @@ -255,9 +290,21 @@ L. =head2 method default +Defined as: + + method default(Parameter:D: --> Code:_) + Returns a closure that upon invocation returns the -L for -this parameter, or C if no default was provided. +L for +this parameter, or C if no default was provided. + +B Before Rakudo version 2020.08 the return value for a parameter +with no default value was C. + +=for code +my $sig = :($a, $b = 12); +say $sig.params[0].default; # OUTPUT: «(Code)␤» +say $sig.params[1].default.(); # OUTPUT: «12␤» =head2 method type_captures @@ -265,7 +312,7 @@ Defined as: method type_captures(Parameter:D: --> List:D) -Returns a list of variable names of type captures associated with this +Returns a list of variable names of L associated with this parameter. Type captures define a type name within the attached code, which is an alias to the type gleaned from the argument during a call. @@ -279,27 +326,53 @@ The type used may change from call to call. Once they are defined, type captures can be used wherever you would use a type, even later in the same signature: -=for code +=begin code sub c(::T $x, T $y, $z) { my T $zz = $z }; c(4, 5, 6); # OK -c(4, 5, "six"); # Fails when assigning to $zz, wants Int not Str -c("four", 5, "six"); # Fails when binding $y, wants Str, not Int + +try c(4, 5, "six"); +given $! { .message.say }; +# OUTPUT: «Type check failed in assignment to $zz; expected Int but got Str ("six")␤» + +try c("four", 5, "six"); +given $! { .message.say }; +# OUTPUT: «Type check failed in binding to parameter '$y'; expected Str but got Int (5)␤» +=end code Type captures may be used at the same time as L. -=for code +=begin code sub d(::T Numeric $x, T $y) {}; d(4, 5); # OK d(4e0, 5e0); # OK -d(4e0, 5); # Fails when binding $y -d("four", "five"); # Fails when binding $x + +try d(4e0, 5); +given $! { .message.say }; +# OUTPUT: «Type check failed in binding to parameter '$y'; expected Num but got Int (5)␤» + +try d("four", "five"); +given $! { .message.say }; +# OUTPUT: «Type check failed in binding to parameter '$x'; expected Numeric but got Str ("four")␤» +=end code =head2 method sub_signature +Defined as: + + method sub_signature(Parameter:D: --> Signature:_) + If the parameter has a -L, -returns a C object for it. Otherwise returns C. +L, +returns a C object for it. Otherwise returns C. + +B Before Rakudo version 2020.08 the return value for a parameter +with no sub-signature was C. + +=for code +my Signature $sig = :(@array ($first, *@rest), @other); +say $sig.params[0].sub_signature; # OUTPUT:«($first, *@rest)␤» +say $sig.params[1].sub_signature; # OUTPUT:«(Signature)␤» =head2 method prefix @@ -307,20 +380,20 @@ Defined as: method prefix(Parameter:D: --> Str:D) -If the parameter is L«slurpy|/type/Signature#Slurpy_(A.K.A._variadic)_parameters», +If the parameter is L«slurpy|/type/Signature#Slurpy_parameters», returns the marker (e.g., C«*», C«**», or C«+») the parameter was declared with. Otherwise, returns an empty string. my Signature $flat-slurpy = :($a, *@b); - say $flat-slurpy.params[0].prefix; # OUTPUT:«""␤» + say $flat-slurpy.params[0].prefix; # OUTPUT:«␤» say $flat-slurpy.params[1].prefix; # OUTPUT:«*␤» my Signature $unflat-slurpy = :($a, **@b); - say $unflat-slurpy.params[0].prefix; # OUTPUT:«""␤» + say $unflat-slurpy.params[0].prefix; # OUTPUT:«␤» say $unflat-slurpy.params[1].prefix; # OUTPUT:«**␤» my Signature $sar-slurpy = :($a, +@b); - say $sar-slurpy.params[0].prefix; # OUTPUT:«""␤» + say $sar-slurpy.params[0].prefix; # OUTPUT:«␤» say $sar-slurpy.params[1].prefix; # OUTPUT:«+␤» =head2 method suffix @@ -333,12 +406,12 @@ Returns the C«?» or C«!» marker a parameter was declared with, if any. Other returns the empty string. my Signature $pos-sig = :($a, $b?); - say $pos-sig.params[0].suffix; # OUTPUT: «""␤» + say $pos-sig.params[0].suffix; # OUTPUT: «␤» say $pos-sig.params[1].suffix; # OUTPUT: «?␤» my Signature $named-sig = :(:$a!, :$b); say $named-sig.params[0].suffix; # OUTPUT: «!␤» - say $named-sig.params[1].suffix; # OUTPUT: «""␤» + say $named-sig.params[1].suffix; # OUTPUT: «␤» =head1 Runtime creation of Parameter objects (6.d, 2019.03 and later) @@ -351,7 +424,7 @@ with the following named parameters: =item name -Optional. The name of the variable, if any. Can be specified in the same +Optional. The name of the parameter, if any. Can be specified in the same way as in a C. So it may contain specific additional information, such as a sigil (C<$>, C<@>, C<%> or C<&>), a C<:> prefix to indicate a named parameter, a twigil (C<.> or C) to indicate public / private attribute diff --git a/doc/Type/Positional.pod6 b/doc/Type/Positional.pod6 index 87d9337c9..66f56c95f 100644 --- a/doc/Type/Positional.pod6 +++ b/doc/Type/Positional.pod6 @@ -4,11 +4,13 @@ =SUBTITLE Object that supports looking up values by index - role Positional { ... } + role Positional[::T = Mu] { ... } -Role for objects which support indexing them using C -(usually list-like objects). Example types with Positional role -include L, L, L, and L. +Role for objects which support indexing them using the +L«C< [ ] > postcircumfix operator|/language/operators#postcircumfix_[_]» +(usually list-like objects). Example types with Positional role +include L, L, L, +and L. =head1 Methods @@ -16,10 +18,18 @@ include L, L, L, and L. +Returns the type constraint for elements of the positional container, that +is, the C in the definition above, which, as it can be seen, defaults +to L. It is returned as a type object. -=head1 Methods that should be provided +=for code +my @þ; +say @þ.of.^name; # OUTPUT: «Mu␤ +my Str @þð; +say @þð.of.raku; # OUTPUT: «Str␤» +say (my int @).of; # OUTPUT: «(int)␤» + +=head1 Methods that should be provided by classes that mix in this role =head2 method elems diff --git a/doc/Type/PositionalBindFailover.pod6 b/doc/Type/PositionalBindFailover.pod6 index 154b4ce71..ed4101f90 100644 --- a/doc/Type/PositionalBindFailover.pod6 +++ b/doc/Type/PositionalBindFailover.pod6 @@ -56,7 +56,7 @@ Subsequent calls to C always return the same C object. =head2 method list - method list(PositionalBindFailover:D: --> List:D) + multi method list(::?CLASS:D:) Returns a L based on the C method without caching it. diff --git a/doc/Type/Proc.pod6 b/doc/Type/Proc.pod6 index 5e7e73bd7..5116eeeb8 100644 --- a/doc/Type/Proc.pod6 +++ b/doc/Type/Proc.pod6 @@ -8,7 +8,7 @@ C is a representation of an invocation of an external process. It provides access to the input, output and error stream as well as -the exit code. It is typically created through the C subroutine: +the exit code. It is typically created through the X|sub_run> subroutine: =for code my $proc = run 'echo', 'Hallo world', :out; @@ -83,7 +83,8 @@ one of the C<:out>, C<:err> or C<:merge> options. In this scenario, it can happen that your Raku script blocks reading from the external program's output while it waits for input, and vice versa. -In this scenario, switching to L is the most robust solution. +In this scenario, switching to L|/type/Proc::Async> is the most +robust solution. =head1 Methods @@ -157,7 +158,7 @@ $*OUT.put: "1. standard output before doing anything weird"; $*OUT.put: "3. everything should be back to normal"; # OUTPUT # 1. standard output before doing anything weird -# /tmp/program.p6: This goes to standard output +# /tmp/program.raku: This goes to standard output # 3. everything should be back to normal # /tmp/out.txt will contain: @@ -201,11 +202,15 @@ shell 'ls /qqq'; =head2 method spawn - method spawn(*@args ($, *@), :$cwd = $*CWD, Hash() :$env = %*ENV, :$win-verbatim-args = False --> Bool:D) + method spawn(*@args ($, *@), :$cwd = $*CWD, Hash() :$env = %*ENV, :$arg0, + :$win-verbatim-args = False --> Bool:D) Runs the C object with the given command, argument list, working directory, and environment. +If C<:arg0> is set to a value, that value is passed as arg0 to the process +instead of the program name. + On Windows the flag C<$win-verbatim-args> disables all automatic quoting of process arguments. See L for more information on windows command quoting. The flag is ignored on all diff --git a/doc/Type/Proc/Async.pod6 b/doc/Type/Proc/Async.pod6 index 134197b4d..7bf47de25 100644 --- a/doc/Type/Proc/Async.pod6 +++ b/doc/Type/Proc/Async.pod6 @@ -116,10 +116,10 @@ An example of piping several commands like C: =head2 method new - multi method new(*@ ($path, *@args), :$w, :$enc, :$translate-nl, + multi method new(*@ ($path, *@args), :$w, :$enc, :$translate-nl, :$arg0, :$win-verbatim-args = False, :$started = False --> Proc::Async:D) - multi method new( :$path, :@args, :$w, :$enc, :$translate-nl, + multi method new( :$path, :@args, :$w, :$enc, :$translate-nl, :$arg0, :$win-verbatim-args = False, :$started = False --> Proc::Async:D) @@ -138,6 +138,9 @@ If C<:translate-nl> is set to C (default value), OS-specific newline terminators (e.g. C<\r\n> on Windows) will be automatically translated to C<\n>. +If C<:arg0> is set to a value, that value is passed as arg0 to the process +instead of the program name. + The C<:started> attribute is set by default to C, so that you need to start the command afterwards using L|/type/Proc::Async#method_start>. You probably don't want to do this @@ -395,7 +398,7 @@ will the thrown. C must have been called before calling method print, otherwise an L exception is thrown. -=head2 method method put +=head2 method put Defined as: diff --git a/doc/Type/Promise.pod6 b/doc/Type/Promise.pod6 index 6482ce046..4c8385147 100644 --- a/doc/Type/Promise.pod6 +++ b/doc/Type/Promise.pod6 @@ -130,7 +130,7 @@ C<$seconds> can be fractional or negative. Negative values are treated as C<0> (i.e. L the returned L right away). Please note that situations like these are often more clearly handled with -a L. +a L. =head2 method at @@ -148,7 +148,7 @@ If the given time is in the past, it will be treated as L (i.e L the returned L right away). Please note that situations like these are often more clearly handled with -a L. +a L. =head2 method kept @@ -220,8 +220,8 @@ creates a chained promise. my $timer = Promise.in(2); my $after = $timer.then({ say "2 seconds are over!"; 'result' }); - say $after.result; # 2 seconds are over - # result + say $after.result; + # OUTPUT: «2 seconds are over␤result␤» =head2 method keep diff --git a/doc/Type/Proxy.pod6 b/doc/Type/Proxy.pod6 index 1db16280b..aba85dd2b 100644 --- a/doc/Type/Proxy.pod6 +++ b/doc/Type/Proxy.pod6 @@ -14,16 +14,18 @@ break behavior, e.g. in C keys. To create a container that returns twice what was stored in it, you do something like this: - sub double() is rw { - my $storage = 0; - Proxy.new( - FETCH => method () { $storage * 2 }, - STORE => method ($new) { $storage = $new }, - ) - } - my $doubled := double(); - $doubled = 4; - say $doubled; # OUTPUT: «8␤» +=begin code :method +sub double() is rw { + my $storage = 0; + Proxy.new( + FETCH => method () { $storage * 2 }, + STORE => method ($new) { $storage = $new }, + ) +} +my $doubled := double(); +$doubled = 4; +say $doubled; # OUTPUT: «8␤» +=end code =head1 Methods diff --git a/doc/Type/PseudoStash.pod6 b/doc/Type/PseudoStash.pod6 index 118ed9ce6..1a7949e21 100644 --- a/doc/Type/PseudoStash.pod6 +++ b/doc/Type/PseudoStash.pod6 @@ -17,7 +17,7 @@ hash. my $a = 42; my $b = q/$a/; say MY::{$b}; -#OUTPUT: «42␤» +# OUTPUT: «42␤» This shows how you can use a C to look up variables, by name, at runtime. diff --git a/doc/Type/QuantHash.pod6 b/doc/Type/QuantHash.pod6 index 268c63012..e88309eb9 100644 --- a/doc/Type/QuantHash.pod6 +++ b/doc/Type/QuantHash.pod6 @@ -44,6 +44,23 @@ L or L for L roles. Returns the type of value a key of this subclass of C may have. This is typically L, which is also the default for punned QuantHashes. +=head2 method Capture + +Defined as + + method Capture() + +Returns the object as a C by previously coercing it to a C. + +=head2 method list + +Defined as: + + multi method list(QuantHash:D:) + +Returns a list of L objects of all keys and values in the +QuantHash. + =head2 method Setty method Setty(--> Setty:D) diff --git a/doc/Type/Range.pod6 b/doc/Type/Range.pod6 index 3d447969a..d68238b99 100644 --- a/doc/Type/Range.pod6 +++ b/doc/Type/Range.pod6 @@ -32,13 +32,13 @@ the start point, and then the generated elements. Ranges always go from small to larger elements; if the start point is bigger than the end point, the range is considered empty. - for 1..5 { .say }; # OUTPUT: «1␤2␤3␤4␤5␤» - ('a' ^..^ 'f').list; # OUTPUT: «'b', 'c', 'd', 'e'» - 5 ~~ ^5; # OUTPUT: «False» - 4.5 ~~ 0..^5; # OUTPUT: «True» - (1.1..5).list; # OUTPUT: «(1.1, 2.1, 3.1, 4.1)» + for 1..5 { .say }; # OUTPUT: «1␤2␤3␤4␤5␤» + say ('a' ^..^ 'f').list; # OUTPUT: «(b c d e)␤» + say 5 ~~ ^5; # OUTPUT: «False␤» + say 4.5 ~~ 0..^5; # OUTPUT: «True␤» + say (1.1..5).list; # OUTPUT: «(1.1 2.1 3.1 4.1)␤» -Use the L<...|/language/operators#infix_...> sequence operator to produce lists +Use the L«C<...>|/language/operators#infix_...» sequence operator to produce lists of elements that go from larger to smaller values, or to use offsets other than increment-by-1 and other complex cases. @@ -154,9 +154,9 @@ ones: say 'a'..'j' ~~ 'b'..'c'; # OUTPUT: «False␤» say 'b'..'c' ~~ 'a'..'j'; # OUTPUT: «True␤» - say 'perl' ~~ -∞^..^∞; # OUTPUT: «True␤» - say 'perl' ~~ -∞..∞; # OUTPUT: «True␤» - say 'perl' ~~ 1..*; # OUTPUT: «True␤» + say 'raku' ~~ -∞^..^∞; # OUTPUT: «True␤» + say 'raku' ~~ -∞..∞; # OUTPUT: «True␤» + say 'raku' ~~ 1..*; # OUTPUT: «True␤» When smartmatching a C of integers with a L (string) @@ -250,7 +250,7 @@ Returns C if both end points are C values. If the C is an integer range (as indicated by L), then this method returns a list with the first and last value it will iterate over (taking into account L and L). Returns a -Failure if it is not an integer range. +L«C|/type/Failure» if it is not an integer range. say (2..5).int-bounds; # OUTPUT: «(2 5)␤» say (2..^5).int-bounds; # OUTPUT: «(2 4)␤» @@ -307,7 +307,7 @@ either end point was specified as C<*>. =head2 method list - method list(Range:D: --> List:D) + multi method list(Range:D:) Generates the list of elements that the range represents. @@ -316,9 +316,10 @@ Generates the list of elements that the range represents. =head2 method flat - method flat(Range:D: --> List:D) + method flat(Range:D:) -Generates the list of elements that the range represents. +Generates a L«C|/type/Seq» containing the elements that the +range represents. =head2 method pick @@ -389,7 +390,7 @@ Defined as multi method EXISTS-POS(Range:D: int \pos) multi method EXISTS-POS(Range:D: Int \pos) -Returns C if C is greater or equal than zero and lower than +Returns C if C is greater than or equal to zero and lower than C. Returns C otherwise. say (6..10).EXISTS-POS(2); # OUTPUT: «True␤» @@ -407,17 +408,17 @@ element in that position. say (1..4).AT-POS(2) # OUTPUT: «3␤» -=head2 method perl +=head2 method raku Defined as - multi method perl(Range:D:) + multi method raku(Range:D:) Returns an implementation-specific string that produces an L object when given to L. -=for code :ok-test - say (1..2).perl # OUTPUT: «1..2␤» +=for code +say (1..2).raku # OUTPUT: «1..2␤» =head2 method fmt @@ -428,7 +429,7 @@ Defined as Returns a string where C and C in the L have been formatted according to C<|c>. -For more information about formats strings, see L. +For more information about parameters, see L. say (1..2).fmt("Element: %d", ",") # OUTPUT: «Element: 1,Element: 2␤» @@ -493,9 +494,13 @@ of the L object by that number. multi sub infix:(Positional \a, Range:D \b --> Order:D) multi sub infix:(Range:D \a, Positional \b --> Order:D) -Compares two L objects. If you use a L|/type/Real>, -it will be compared to the L C. If you use a -L. +Compares two L objects. A L«C|/type/Real» +operand will be considered as both the starting point and the ending +point of a L to be compared with the other operand. +A L«C|/type/Positional» operand will be compared with the +list returned by the L«C<.list> method|/type/Range#method_list» +applied to the other operand. +See L«C<< List infix: >>|/type/List#infix_cmp» say (1..2) cmp (1..2); # OUTPUT: «Same␤» say (1..2) cmp (1..3); # OUTPUT: «Less␤» diff --git a/doc/Type/Rat.pod6 b/doc/Type/Rat.pod6 index 066863463..13e723112 100644 --- a/doc/Type/Rat.pod6 +++ b/doc/Type/Rat.pod6 @@ -43,16 +43,16 @@ C objects are immutable. =head1 Methods -=head2 method perl +=head2 method raku - multi method perl(Rat:D: --> Str:D) + multi method raku(Rat:D: --> Str:D) Returns an implementation-specific string that produces an L object when given to L. -=for code :ok-test - say (1/3).perl; # OUTPUT: «<1/3>␤» - say (2/4).perl; # OUTPUT: «0.5␤» +=for code +say (1/3).raku; # OUTPUT: «<1/3>␤» +say (2/4).raku; # OUTPUT: «0.5␤» =end pod diff --git a/doc/Type/RatStr.pod6 b/doc/Type/RatStr.pod6 index 86ce69d6c..04c9a5a94 100644 --- a/doc/Type/RatStr.pod6 +++ b/doc/Type/RatStr.pod6 @@ -4,23 +4,24 @@ =SUBTITLE Dual value rational number and string - class RatStr is Rat is Str {} + class RatStr is Allomorph is Rat {} -The dual value types (often referred to as L) -allow for the representation of a value as both a string and a numeric type. Typically -they will be created for you when the context is "stringy" but they can be determined -to be numbers, such as in some L: +C is a dual value type, a subclass of both +L«C|/type/Allomorph», hence L«C|/type/Str», and +L«C|/type/Rat». - my $f = <42.1>; say $f.^name; # OUTPUT: «RatStr␤» +See L«C|/type/Allomorph» for further details. -As a subclass of both L«C|/type/Rat» and L«C|/type/Str», a C -will be accepted where either is expected. However, C does not share -object identity with C- or C-only variants: +=begin code +my $rat-str = <42.1>; +say $rat-str.^name; # OUTPUT: «RatStr␤» - my $rat-str = <42.1>; - my Rat $rat = $rat-str; # OK! - my Str $str = $rat-str; # OK! - say 42.1 ∈ <42.1 55 1>; # False; ∈ operator cares about object identity +my Rat $rat = $rat-str; # OK! +my Str $str = $rat-str; # OK! + +# ∈ operator cares about object identity +say 42.1 ∈ <42.1 55 1>; # OUTPUT: «False␤» +=end code =head1 Methods @@ -35,18 +36,6 @@ directly the values can be whatever is required: say +$f; # OUTPUT: «42.1␤» say ~$f; # OUTPUT: «"forty two and a bit"␤» -=head2 method Bool - -Defined as: - - multi method Bool(RatStr:D: --> Bool:D) - -I. - -Returns C if the L of the numeric portion is C<0>, otherwise returns C. -This applies for C«< 0/0 >» zero-denominator L as well, despite C«?< 0/0 >.Num» being -C. String portion is not considered. - =head2 method Capture Defined as: @@ -81,41 +70,15 @@ Defined as: The C<:D> variant returns the numeric portion of the invocant. The C<:U> variant issues a warning about using an uninitialized value in numeric context and then returns value C<0.0>. -=head2 method Str - -Returns the string value of the C. - -=head2 method ACCEPTS - -Defined as: - - multi method ACCEPTS(RatStr:D: Any:D $value) - -If C<$value> is L (including another -L), checks if invocant's -L part L the C<$value>. If -C<$value> is L, checks if invocant's L part -L the C<$value>. If value is anything else, -checks if both L and L parts C the C<$value>. - - say <5.0> ~~ "5"; # OUTPUT: «False␤» - say <5.0> ~~ 5 ; # OUTPUT: «True␤» - say <5.0> ~~ <5>; # OUTPUT: «True␤» - =head1 Operators -=head2 infix cmp - - multi sub infix:(RatStr:D $a, RatStr:D $b) +=head2 infix C«===» -Compare two C objects. The comparison is done on the C value first and -then on the C value. If you want to compare in a different order then you would -coerce to the C or C values first: + multi sub infix:<===>(RatStr:D $a, RatStr:D $b) - my $f = RatStr.new(42.1, "smaller"); - my $g = RatStr.new(43.1, "larger"); - say $f cmp $g; # OUTPUT: «Less␤» - say $f.Str cmp $g.Str; # OUTPUT: «More␤» +C Value identity operator. Returns C if the C +values of C<$a> and C<$b> are L and their C +values are also L. Returns C otherwise. =end pod diff --git a/doc/Type/Rational.pod6 b/doc/Type/Rational.pod6 index 23ff7791c..1025df383 100644 --- a/doc/Type/Rational.pod6 +++ b/doc/Type/Rational.pod6 @@ -26,8 +26,9 @@ both do the C role. =head2 method new - =for code :preamble + =begin code :preamble method new(NuT:D $numerator, DeT:D $denominator --> Rational:D) + =end code Creates a new rational object from numerator and denominator, which it normalizes to the lowest terms. The C<$denominator> can be zero, in which @@ -100,15 +101,17 @@ Number>. That is both its numerator and denominator are zero. =head2 method numerator - =for code :preamble + =begin code :preamble method numerator(Rational:D: --> NuT:D) + =end code Returns the numerator. =head2 method denominator - =for code :preamble + =begin code :preamble method denominator(Rational:D: --> DeT:D) + =end code Returns the denominator. diff --git a/doc/Type/Real.pod6 b/doc/Type/Real.pod6 index f9e32a9a7..0188c6a82 100644 --- a/doc/Type/Real.pod6 +++ b/doc/Type/Real.pod6 @@ -68,11 +68,20 @@ it is an L when we instantiated C with an L with the number converted to a C as its real part and 0e0 as the imaginary part. +=head2 method Int + + method Int(Real:D:) + +Calls the L«C method|/routine/Bridge» on the invocant and then +the L«C method|/routine/Int» on its return value. + =head2 method Rat method Rat(Real:D: Real $epsilon = 1e-6) -Converts the number to a C with the precision C<$epsilon>. +Calls the L«C method|/routine/Bridge» on the invocant and then +the L«C method|/routine/Rat» on its return value with the +C<$epsilon> argument. =head2 method Real @@ -85,6 +94,20 @@ The C<:D> variant simply returns the invocant. The C<:U> variant issues a warning about using an uninitialized value in numeric context and then returns C. +=head2 method Str + + multi method Str(Real:D:) + +Calls the L«C method|/routine/Bridge» on the invocant and then +the L«C method|/routine/Str» on its return value. + +=head2 method Num + + method Num(Real:D:) + +Calls the L«C method|/routine/Bridge» on the invocant and then +the L«C method|/routine/Num» on its return value. + =head2 routine rand sub term: (--> Num:D) diff --git a/doc/Type/Routine.pod6 b/doc/Type/Routine.pod6 index 4d50145d4..435f7e48e 100644 --- a/doc/Type/Routine.pod6 +++ b/doc/Type/Routine.pod6 @@ -16,14 +16,14 @@ Routines serve as a scope limiter for C (i.e. a C returns from the innermost outer Routine). The routine level is also the one at which -L (multi subs and multi methods) +L (multi subs and multi methods) are handled. Subroutines can also be declared C. See the L declarator|/language/variables#The_anon_declarator> for more information. Routines are the lowest objects in the C hierarchy that can introspect through the -L variable|/language/variables#index-entry-&%3FROUTINE>, which +L variable|/language/variables#%26%3FROUTINE>, which is defined automatically, and contains the corresponding C object. =for code diff --git a/doc/Type/Scalar.pod6 b/doc/Type/Scalar.pod6 index 3f82a7a76..434aea2c3 100644 --- a/doc/Type/Scalar.pod6 +++ b/doc/Type/Scalar.pod6 @@ -6,12 +6,12 @@ class Scalar {} -A C is an internal indirection which is for most purposes -invisible during ordinary use of Raku. It is the default container -type associated with the C<$> sigil. A literal C may be -placed around a literal value by enclosing the value in C<$(…)>. -This notation will appear in the output of a C<.raku> method in -certain places where it is important to note the presence of Cs. +A C is an internal indirection, that is, a way to refer indirectly to a +value, which is, for most purposes, invisible during ordinary use of Raku. It is +the default container type associated with the C<$> sigil. A literal C +may be placed around any literal by enclosing the value in C<$(…)>. This +notation will appear in the output of a C<.raku> method in certain places where +it is important to note the presence of Cs. When a value is assigned to a C<$>-sigiled variable, the variable will actually bind to a C, which in turn will bind to the value. @@ -19,11 +19,21 @@ When a C is assigned to a C<$>-sigiled variable, the value bound to by that C will be bound to the C which that variable was bound to (a new one will be created if necessary.) -In addition, Cs delegate all method calls to the value which -they contain. As such, Cs are for the most part invisible. -There is, however, one important place where Cs have a visible -impact: a C will shield its content from flattening by most -Raku core list operations. +In addition, Cs delegate all method calls to the value which they +contain. As such, Cs are for the most part invisible. There is, however, +one important place where Cs have a visible impact: a C +container will shield its content from +L by most Raku core list +operations. + +=for code +say |(1,2,$(3,4)); # OUTPUT: «12(3 4)␤» + +These C containers can also be created on the fly by assigning to a +bare sigil: + +=for code +say |(1,2,my $ = (3,4)); # OUTPUT: «12(3 4)␤» A C<$>-sigiled variable may be bound directly to a value with no intermediate C using the binding operator C<:=>. You can @@ -69,11 +79,12 @@ alter the value of both variables by altering only one of them: $a.say; # OUTPUT: «2␤» X<|\ (sigilless scalar)> -SSA-style constants bind directly to their value with no -intervening C, even when assignment (C<=>) is used. They may -be forced to use a C by assigning a C<$>-sigiled variable -to them, at which point, they behave entirely like C<$>-sigiled -variables. +Raku allows the use of constants with a +L +style which bind directly to their value with no intervening C +container, even when assignment (C<=>) is used. They may be forced to use a +C by assigning a C<$>-sigiled variable to them, at which point, they +behave entirely like C<$>-sigiled variables. my \c = 1; c.^name.say; # OUTPUT: «Int␤» @@ -201,8 +212,8 @@ never terminate. Defined as: - multi sub cas($target is rw, $expected, $value) - multi sub cas($target is rw, &operation) + multi sub cas(Mu $target is rw, Mu \expected, Mu \value) + multi sub cas(Mu $target is rw, &operation) Performs an atomic compare and swap of the value in the C C<$target>. The first form has semantics like: @@ -238,7 +249,7 @@ C. The second form, taking a code object, will first do an atomic fetch of the current value and invoke the code object with it. It will then try to do an atomic compare and swap of the target, using the value passed to the code -object as C<$expected> and the result of the code object as C<$value>. If +object as C and the result of the code object as C. If this fails, it will read the latest value, and retry, until a CAS operation succeeds. @@ -259,6 +270,9 @@ manner as follows: This will reliably build up a linked list of 4000 items, with 4 nodes with each value ranging from 0 up to 999. +B: Before Rakudo version 2020.12, C<$target>, C and +C had an L«C|/type/Any» type constraint. + =head1 Operators =head2 infix ⚛= diff --git a/doc/Type/Scheduler.pod6 b/doc/Type/Scheduler.pod6 index 962d4908a..75af24509 100644 --- a/doc/Type/Scheduler.pod6 +++ b/doc/Type/Scheduler.pod6 @@ -8,13 +8,14 @@ has &.uncaught_handler is rw } -Common role for schedulers. A scheduler is a piece of code that determines -which resources to use to run which task, and when. +A scheduler is a piece of code that determines which resources to use to run +which task, and when. This role contains code that will be the same for all +kinds of schedulers. -Some operations for example on L, L, -L allow you to specify a scheduler explicitly; they -generally expect those schedulers to follow the interface defined by -C +Some operations for example on L, +L, L allow you to specify a +scheduler explicitly; they generally expect those schedulers to follow the +interface defined by C. =head1 Methods @@ -30,28 +31,31 @@ code that is being scheduled and run. method cue(&code, Instant :$at, :$in, :$every, :$times = 1; :&catch --> Cancellation) Schedules a callable (C<&code>) for execution and returns an instantiated -C object to cancel the scheduling of the code for execution -(which is especially important if you specify the C time> named -parameter. The adverbs control when and how the code is run: +L|/type/Cancellation> object to cancel the scheduling of the +code for execution (which is especially important if you specify the C<:every +( time )> named parameter). The adverbs control when and how the code is run: -C<$at> can be an L before which the code won't be run. +=item C<$at> can be an L before which the code won't be +run. Alternatively C<$in> is the number of seconds (possibly fractional) to wait before running the code. If C<$at> is in the past or C<$in> is negative, the delay is treated as zero. Implementations may equate to zero very small values (e.g. lower than 0.001s) of C<$in> or result of C<$at> - L. -If C<$every> is specified, it is interpreted as the number of seconds +=item If C<$every> is specified, it is interpreted as the number of seconds (possibly fractional) to wait before re-executing the code. Implementations may treat too-small values as lowest resolution they support, possibly warning in such situations; e.g. treating C<0.0001> as C<0.001>. -C<$times> tells the scheduler how many times to run the code. +=item C<$times> tells the scheduler how many times to run the code. -C<&catch> is called with the L as its sole argument +=item C<&catch> is called with the L as its sole +argument if C<&code> dies. -If C<$at> or C<$in> are C, C<&code> will never be run; if C<$every> is +=item If C<$at> or C<$in> are C, C<&code> will never be run; if +C<$every> is C, C<&code> will only be run once. If any of the three are C<-Inf>, C<&code> will be run immediately. If any of the three are C, an L exception @@ -60,6 +64,14 @@ will be thrown. This only applies to releases 2019.05 and later. One should call the C method on the returned C object to cancel the (possibly repeated) cueing of the code. +=head2 method loads + +Defined as: + + method loads() + +This is a method stub, should be re-implemented when subclassing. + =end pod # vim: expandtab softtabstop=4 shiftwidth=4 ft=perl6 diff --git a/doc/Type/Seq.pod6 b/doc/Type/Seq.pod6 index 27323384b..0adcc196f 100644 --- a/doc/Type/Seq.pod6 +++ b/doc/Type/Seq.pod6 @@ -87,13 +87,17 @@ leading to possibly infinite loops, so be sure to limit search somehow. =head2 method new - method new(Iterator:D $iter --> Seq:D) +=for code +proto method new(Seq: |) {*} +multi method new(Seq: Iterator:D $iter) +multi method new(Seq:) -Creates a new C object from the iterator passed as the single argument. +Creates a new C object from the supplied iterator passed as the single +argument. Creates an empty C if called with no argument. =head2 method iterator - method iterator(Seq:D: --> Iterator:D) + method iterator(Seq:D:) If the C is not cached, returns the underlying iterator and marks the invocant as consumed. If called on an already consumed sequence, @@ -103,12 +107,29 @@ Otherwise returns an iterator over the cached list. =head2 method is-lazy - method is-lazy(Seq:D: --> Bool:D) + method is-lazy(Seq:D:) Returns C if and only if the underlying iterator or cached list considers itself lazy. If called on an already consumed sequence, throws an error of type L. +=head2 method Seq + +Defined as + + multi method Seq(Seq:D:) + +Clones the object. + + +=head2 method Capture + +Defined as + + method Capture() + +Coerces the object to a C, which is in turn coerced into a C + =head2 method elems method elems(Seq:D:) @@ -122,24 +143,25 @@ L with L. =head2 method from-loop - multi method from-loop(&body --> Seq:D) - multi method from-loop(&body, &cond, :$repeat --> Seq:D) - multi method from-loop(&body, &cond, &afterward --> Seq:D) + multi method from-loop(&body, :$label) + multi method from-loop(&body, &cond, :$repeat!, :$label) + multi method from-loop(&body, &cond, :$label) + multi method from-loop(&body, &cond, &afterwards, :$label) These methods create new C-based callbacks. -The first form produces an infinite C by calling C<&body> each time a new +In general, it produces an infinite C by calling C<&body> each time a new element is requested, using the return value from C<&body> as the item. This emulates (or implements) a C construct. -The second form calls C<&cond> before each call to C<&body>, and terminates +When the multi includes C<&cond>, it's invoked before each call to +C<&body>, and terminates the sequence if C<&cond> returns a false value. If C<$repeat> is set to a true value, the first call to C<&cond> is omitted, and C<&body> called right away. This emulates (or implements) C and C loops. -The third form enables C-style looping by calling a third callback, -C<&afterward>, after each call to C<&body>. +If present, C<&afterward> will be called after each call to C<&body>. =head2 method sink diff --git a/doc/Type/Set.pod6 b/doc/Type/Set.pod6 index c02736695..c11a8a58e 100644 --- a/doc/Type/Set.pod6 +++ b/doc/Type/Set.pod6 @@ -71,7 +71,9 @@ of the C, to specify which type of values are acceptable: my $fruits = Set[Int].new( ); # Type check failed in binding; expected Int but got Str ("peach") -Finally, you can create Set masquerading as a hash by using the C trait: +Finally, you can create C masquerading as a hash (actually, declare a +variable C by using the corresponding sigil) by using the C +trait: my %s is Set = ; say %s; # True diff --git a/doc/Type/Signature.pod6 b/doc/Type/Signature.pod6 index ea16b29ef..31654ae7f 100644 --- a/doc/Type/Signature.pod6 +++ b/doc/Type/Signature.pod6 @@ -160,12 +160,13 @@ Type constraints can have any compile-time defined value =begin code subset Positive-integer of Int where * > 0; sub divisors(Positive-integer $n) { $_ if $n %% $_ for 1..$n }; +CATCH { default { put .^name, ': ', .Str; .resume } }; + divisors 2.5; -# ERROR «Type check failed in binding to parameter '$n'; -# expected Positive-integer but got Rat (2.5) $n)» +# OUTPUT: «X::TypeCheck::Binding::Parameter: Type check failed in binding to parameter '$n'; expected Positive-integer but got Rat (2.5)␤» + divisors -3; -# ERROR: «Constraint type check failed in binding to parameter '$n'; -# expected Positive-integer but got Int (-3)» +# OUTPUT: «X::TypeCheck::Binding::Parameter: Constraint type check failed in binding to parameter '$n'; expected Positive-integer but got Int (-3)␤» =end code Please note that in the code above type constraints are enforced at two @@ -256,7 +257,7 @@ against undefined values within the C clause. =head3 Constraining slurpy arguments -L can not have type +L can not have type constraints. A C-clause in conjunction with a L can be used to that effect. @@ -504,8 +505,8 @@ Typed L also work with constrained callable parameters. =for code :preamble - say apply -> Int:D \x --> Int:D { 2 * x }, 3; # OUTPUT: «6␤» - say apply -> Int:D \x --> Int:D { x ** 3 }, 3; # OUTPUT: «27␤» +say apply -> Int:D \x --> Int:D { 2 * x }, 3; # OUTPUT: «6␤» +say apply -> Int:D \x --> Int:D { x ** 3 }, 3; # OUTPUT: «27␤» Note that this shorthand syntax is available only for parameters with the C<&> sigil. For others, you need to use the long version: @@ -648,14 +649,20 @@ directly apply string methods, such as the number of characters. X<|parameter,*@> X<|parameter,*%> X<|slurpy argument> -=head2 Slurpy (A.K.A. variadic) parameters +=head2 Slurpy parameters A function is X if it can take a varying number of arguments; that is, -its arity is not fixed. Therefore, optional, named, and slurpy parameters are -variadic. An array or hash parameter can be marked as I by leading -single (*) or double asterisk (**) or a leading plus (+). A slurpy parameter can -bind to an arbitrary number of arguments (zero or more), and it will result in a -type that is compatible with the sigil. +its arity is not fixed. Therefore, +L, +named, and slurpy parameters +make routines that use them I, and by extension are called variadic +arguments. Here we will focus on slurpy parameters, or simply I. + +An array or hash parameter can be +marked as I by leading single (*) or double asterisk (**) or a +leading plus (+). A slurpy parameter can bind to an arbitrary number of +arguments (zero or more), and it will result in a type that is compatible +with the sigil. These are called "slurpy" because they slurp up any remaining arguments to a function, like someone slurping up noodles. @@ -694,7 +701,8 @@ say combined-slurpy(one => 1, two => 2, 3, 4, five => 5, 6); # OUTPUT: «{array => [3 4 6], hash => {five => 5, one => 1, two => 2}}␤» =end code -Note that positional parameters aren't allowed after slurpy parameters: +Note that positional parameters aren't allowed after slurpy (or, in +fact, after any type of variadic) parameters: =begin code :skip-test :(*@args, $last); @@ -1081,6 +1089,7 @@ designers. X<|trait, is raw> The L trait|/type/Parameter#method_raw> is automatically applied to parameters declared with a L +or a L as a "sigil", and may also be used to make normally sigiled parameters behave like these do. In the special case of slurpies, which normally produce an C full of Cs as described above, C will instead cause @@ -1153,7 +1162,7 @@ L C<$topic>: 42 ~~ :(Int); # OUTPUT: «False» (Int.Capture throws) set() ~~ :(:$a, :$b); # OUTPUT: «True» -Since L«C clauses|/type/Signature#index-entry-where_clause_(Signature)» +Since L«C clauses|/type/Signature#index-entry-where_clause» are not introspectable, the method cannot determine whether two signatures L the same sort of C-constrained parameters. Such comparisons will return C. This includes signatures with @@ -1172,7 +1181,7 @@ Throws C. =head1 Runtime creation of Signature objects (6.d, 2019.03 and later) =for code :preamble -Signature.new(params => (...), returns => Type, arity => 1, count => 1) +Signature.new(params => (...), returns => Type, arity => 1, count => 1.Num) In some situations, specifically when working with the MetaObject Protocol, it makes sense to create C objects programmatically. For this @@ -1199,6 +1208,12 @@ The I number of positional arguments which can be bound to the signature. Defaults to the C if not specified. Specify C if there is a slurpy positional parameter. +I: although the logical type of the C parameter is integer, +the value assigned to it must explicitly be of type C. If any other +type is used, the C method silently fails and returns an empty signature. +The same trouble occurs when the value assigned to the C parameter is +not of type C. + =end pod # vim: expandtab softtabstop=4 shiftwidth=4 ft=perl6 diff --git a/doc/Type/Slip.pod6 b/doc/Type/Slip.pod6 index be22933f2..e5edea0c3 100644 --- a/doc/Type/Slip.pod6 +++ b/doc/Type/Slip.pod6 @@ -28,21 +28,23 @@ C method, or use the C subroutine: take slip(1, 2); } -A C may also be created by using the C> operator. This differs +A C may also be created by using the L«C>|/language/operators#prefix_|» operator. This differs from the C subroutine in both precedence and treatment of single arguments. In fact, C> only takes a single argument, so in that way, it behaves closer to the C<.Slip> method than the C subroutine. =for code my $l = (1, 2, 3); -say (1, slip 2, 3).raku; # says (1, 2, 3) , slips 2, 3 into (1, …) -say (0, slip $l).raku; # says (0, $(1, 2, 3)), $l does not break apart -say (0, $l.Slip).raku; # says (0, 1, 2, 3) , slips from $l into (0, …) -say (|$l).raku; # says slip(1, 2, 3) , breaks apart $l -say (0, (|$l, 4), 5); # says (0 (1 2 3 4) 5), slips from $l into (…, 4) -say (0, ($l.Slip, 4), 5); # says (0 (1 2 3 4) 5), slips from $l into (…, 4) -say (0, (slip $l, 4), 5); # says (0 (1 2 3) 4 5), slips ($l, 4) into (0, …, 5) -say (0, ($l, 4).Slip, 5); # says (0 (1 2 3) 4 5), slips ($l, 4) into (0, …, 5) +say (1, slip 2, 3).raku; # says (1, 2, 3) , slips 2, 3 into (1, …) +say (0, slip $l, 4).raku; # says (0, $(1, 2, 3), 4) , $l does not break apart +say (0, slip $l).raku; # says (0, 1, 2, 3) , slips from $l into (0, …) +say (0, $l.Slip).raku; # says (0, 1, 2, 3) , slips from $l into (0, …) +say (0, $l.Slip, 4).raku; # says (0, 1, 2, 3, 4) , slips from $l into (0, …, 4) +say (|$l).raku; # says slip(1, 2, 3) , breaks apart $l +say (0, (|$l, 4), 5); # says (0 (1 2 3 4) 5) , slips from $l into (…, 4) +say (0, ($l.Slip, 4), 5); # says (0 (1 2 3 4) 5) , slips from $l into (…, 4) +say (0, (slip $l, 4), 5); # says (0 (1 2 3) 4 5) , slips ($l, 4) into (0, …, 5) +say (0, ($l, 4).Slip, 5); # says (0 (1 2 3) 4 5) , slips ($l, 4) into (0, …, 5) Loops that do not want to produce a value for an iteration use C, rather than empty Cs to do so, as do C statements that do not run their @@ -77,7 +79,7 @@ Defined as: Creates a L from its arguments by calling L|/routine/Slip> on the object formed by them. Returns -L|/type/Slip#index-entry-Empty-Empty> if called with void arguments. +L|/type/Slip#constant_Empty> if called with void arguments. =head1 Constants diff --git a/doc/Type/Str.pod6 b/doc/Type/Str.pod6 index 8f1a46d32..b9bf70e9e 100644 --- a/doc/Type/Str.pod6 +++ b/doc/Type/Str.pod6 @@ -431,6 +431,22 @@ C. +, - and the Unicode MINUS SIGN − are all allowed. =for code " −33".Numeric; # OUTPUT: «-33␤» +=head2 method Num + +Defined as: + + method Num(Str:D: --> Num:D) + +Coerces the string to L«C|/type/Num», using the same rules as +L«C|/type/Str#method_Numeric» and handling negative zero, +C<-0e0>, and positive zero, C<0e0>. + +=begin code +my Str $s = "-0/5"; +say (.self, .^name) given $s.Numeric; # OUTPUT: «(0 Rat)␤» +say (.self, .^name) given $s.Num; # OUTPUT: «(-0 Num)␤» +=end code + =head2 method Int Defined as: @@ -473,7 +489,7 @@ for the specified base. 'Raku'.parse-base(36).say; # OUTPUT: «1273422␤» 'FF.DD'.parse-base(16).say; # OUTPUT: «255.863281␤» -See also: L«:16 syntax for number literals|/syntax/Number%20literals» +See also: L«syntax for number literals|/syntax/Number%20literals» =head2 routine parse-names @@ -506,6 +522,25 @@ convert those: I before being standardized in 2017.12, this routine was known under its working name of L. This denomination will be removed in the 6.e version. +=head2 method samecase + + multi method samecase(Str:D: Str:D $pattern --> Str:D) + +Returns a copy of the invocant with case information for each individual +character changed according to C<$pattern>. + +B: The pattern string can contain three types of characters, +i.e. uppercase, lowercase and caseless. For a given character in +C<$pattern> its case information determines the case of the corresponding +character in the result. + +If the invocant is longer than C<$pattern>, the case information from +the last character of C<$pattern> is applied to the remaining characters +of the invocant. + + say "raKu".samecase("A_a_"); # OUTPUT: «Raku␤» + say "rAKU".samecase("Ab"); # OUTPUT: «Raku␤» + =head2 routine split =for code :method @@ -692,7 +727,7 @@ Returns the string reversed character by character. Examples: - "Perl".flip; # OUTPUT: «lreP» + "Raku".flip; # OUTPUT: «ukaR» "ABBA".flip; # OUTPUT: «ABBA» =head2 method starts-with @@ -1026,7 +1061,7 @@ Examples: say 'åäö'.samemark('aäo'); # OUTPUT: «aäo␤» say 'åäö'.samemark('a'); # OUTPUT: «aao␤» - say samemark('Pêrl', 'a'); # OUTPUT: «Perl␤» + say samemark('Räku', 'a'); # OUTPUT: «Raku␤» say samemark('aöä', ''); # OUTPUT: «aöä␤» =head2 method succ @@ -1281,12 +1316,12 @@ part of the String say val("−42"); # OUTPUT: «−42␤» -While characters belonging to the Unicode categories C (number letters) -and C (other numbers) can be used as numeric literals in the language, -they will not be converted to a number by C, by design, and using C - on them will produce a failure. The same will happen with synthetic numerics - (such as 7̈ )See L«unival|/routine/unival» if you need to convert such - characters to +While characters belonging to the Unicode categories C (number +letters) and C (other numbers) can be used as numeric literals +in the language, they will not be converted to a number by C, +by design, and using C on them will produce a failure. The +same will happen with synthetic numerics (such as 7̈ ). See +L«unival|/routine/unival» if you need to convert such characters to C. =head2 method Version diff --git a/doc/Type/StrDistance.pod6 b/doc/Type/StrDistance.pod6 index 50b278034..2e0f84b12 100644 --- a/doc/Type/StrDistance.pod6 +++ b/doc/Type/StrDistance.pod6 @@ -60,10 +60,11 @@ Defined as: Returns an C string value. - =for code :preamble + =begin code :preamble my $str-dist = ($str ~~ tr/old/new/); say $str-dist.Str; # OUTPUT: «fnew␤» say ~$str-dist; # OUTPUT: «fnew␤» + =end code =end pod diff --git a/doc/Type/Sub.pod6 b/doc/Type/Sub.pod6 index 51dcec588..43eec0761 100644 --- a/doc/Type/Sub.pod6 +++ b/doc/Type/Sub.pod6 @@ -54,7 +54,7 @@ L. X<|trait_mod (declarator)> A C is a sub that is applied at compile time to various objects like -classes, routines or L. It +classes, routines or L. It is declared with the C declarator followed by a colon and a string literal containing the name of the trait. A single positional parameter defines the type of the object that the trait is applied to. A single named argument @@ -72,7 +72,7 @@ language object names or parameter lists. bar(); # OUTPUT: «⟨is foo⟩ has been called with ⟨oi‽⟩ on Sub|47563000␤start␤bar has been called␤» -Use L to call traits +Use L to call traits with complex arguments. multi trait_mod:(Variable $a, :@foo [$firstpos, *@restpos, :$named, *%restnameds]) { diff --git a/doc/Type/Supply.pod6 b/doc/Type/Supply.pod6 index 46b1a8cd7..73768e736 100644 --- a/doc/Type/Supply.pod6 +++ b/doc/Type/Supply.pod6 @@ -187,7 +187,7 @@ the exception that was passed to C). =head2 method list - method list(Supply:D: --> List:D) + multi method list(Supply:D:) Taps the C it is called on, and returns a lazy list that will be reified as the C emits values. The list will be terminated once the C is @@ -371,10 +371,15 @@ C<&mapper> and emits it to the new supply. method batch(Supply:D: :$elems, :$seconds --> Supply:D) Creates a new supply that batches the values of the given supply by either -the number of elements in the batch (using C<:elems>) or the maximum number of -seconds (using the C<:seconds>) or both. Any remaining values are emitted in +the number of elements in the batch (using C<:elems>) or a duration +(using C<:seconds>) or both. Any remaining values are emitted in a final batch when the supply is done. +B: Since Rakudo version 2020.12, the C<:seconds> parameter has +a millisecond granularity: for example a 1 millisecond duration could +be specified as C<:seconds(0.001)>. Before Rakudo version 2020.12, +the C<:seconds> parameter had a second granularity. + =head2 method elems method elems(Supply:D: $seconds? --> Supply:D) @@ -460,6 +465,19 @@ L«C<.head>|#method head». my $s = $words.split(/ /, 2, :skip-empty); $s.tap(&say); # OUTPUT: «Hello␤World␤» +=head2 method rotate + + method rotate(Supply:D: $rotate = 1) + +Creates a supply with elements rotated to the left when C<$rotate> +is positive or to the right otherwise, in which case the invocant is +tapped on before a new supply is returned. + + my $supply = Supply.from-list().rotate(2); + $supply.tap(&say); # OUTPUT: «c␤d␤e␤a␤b␤» + +B: Available since Rakudo 2020.06. + =head2 method rotor method rotor(Supply:D: @cycle --> Supply:D) @@ -762,7 +780,7 @@ Creates a supply that only emits values from the given supply if they are larger than any value seen before. In other words, from a continuously ascending supply it will emit all the values. From a continuously descending supply it will only emit the first value. The optional parameter specifies -the comparator, just as with L. +the comparator, just as with L. =head2 method min @@ -772,7 +790,7 @@ Creates a supply that only emits values from the given supply if they are smaller than any value seen before. In other words, from a continuously descending supply it will emit all the values. From a continuously ascending supply it will only emit the first value. The optional parameter specifies -the comparator, just as with L. +the comparator, just as with L. =head2 method minmax @@ -780,7 +798,7 @@ the comparator, just as with L. Creates a supply that emits a Range every time a new minimum or maximum values is seen from the given supply. The optional parameter specifies -the comparator, just as with L. +the comparator, just as with L. =head2 method skip @@ -870,7 +888,7 @@ AAPL: 111.6 method merge(Supply @*supplies --> Supply:D) Creates a supply to which any value seen from the given supplies, is emitted. -The resulting supply is done Only when all given supplies are done. Can also +The resulting supply is done only when all given supplies are done. Can also be called as a class method. =head2 method zip diff --git a/doc/Type/Test.pod6 b/doc/Type/Test.pod6 index 80ae65344..730270d34 100644 --- a/doc/Type/Test.pod6 +++ b/doc/Type/Test.pod6 @@ -8,6 +8,8 @@ This module provides a testing framework, and is used in the official suite that tests the specification. All its functions emit output conforming to the L. +Also see L. + =head1 Methods =head2 sub plan @@ -56,10 +58,10 @@ ok 42; # this will run everywhere and isn't affected by skip-all inside subtest Note that C with C<:skip-all> is to avoid performing any tests without marking the test run as failed (i.e. the plan is to not run anything and that's all good). Use -L«C|/language/testing#index-entry-skip-rest-skip-rest($reason?)» to +L«C|#skip-rest» to skip all further tests, once the run has started (i.e. planned to run some tests, maybe even ran some, but now we're skipping all the rest of them). Use -L«C|/language/testing#index-entry-bail-out-bail-out($reason?)» to fail +L«C|#bail-out» to fail the test run without running any further tests (i.e. things are so bad, there's no point in running anything else; we've failed). @@ -79,12 +81,12 @@ test failures otherwise not reported because tests were accidentally skipped due to bugs in the tests or bugs in the compiler. For example: =for code :preamble - sub do-stuff {@}; - use Test; - ok .is-prime for do-stuff; - done-testing; - # output: - 1..0 +sub do-stuff {@}; +use Test; +ok .is-prime for do-stuff; +done-testing; +# output: +1..0 The above example is where a C fails. C returned nothing and tested nothing, even though it should've returned results to test. @@ -94,39 +96,40 @@ passes. Adding C gives a true picture of the test: =for code :preamble - sub do-stuff {@}; - use Test; - plan 1; - ok .is-prime for do-stuff; - # output: - 1..1 - # Looks like you planned 1 test, but ran 0 +sub do-stuff {@}; +use Test; +plan 1; +ok .is-prime for do-stuff; +# output: +1..1 +# Looks like you planned 1 test, but ran 0 Note that leaving the C in place will have no effect on the new test results, but it should be removed for clarity. +The C function returns C if any test has failed or +less tests were run than planned, it returns C otherwise. + =head2 sub ok Defined as: multi sub ok(Mu $cond, $desc = '') -The C function marks a test as passed if the given C<$value> evaluates to -C. The C function marks a test as passed if the given value evaluates -to C. Both functions accept an optional description of the test as second -parameter. +The C function marks a test as passed if the given C<$cond> evaluates to +C. It also accepts an optional description of the test as second +argument. =for code :preamble - my $response; my $query; ...; - ok $response.success, 'HTTP response was successful'; - nok $query.error, 'Query completed without error'; +my $response; my $query; ...; +ok $response.success, 'HTTP response was successful'; In principle, you could use C for every kind of comparison test, by -including the comparison in the expression passed to C<$value>: +including the comparison in the expression passed to C<$cond>: =for code :preamble - sub factorial($x) { ... }; - ok factorial(6) == 720, 'Factorial - small integer'; +sub factorial($x) { ... }; +ok factorial(6) == 720, 'Factorial - small integer'; However, where possible it's better to use one of the specialized comparison test functions below, because they can print more helpful diagnostics output in @@ -138,15 +141,13 @@ Defined as: multi sub nok(Mu $cond, $desc = '') -The C function marks a test as passed if the given value evaluates to +The C function marks a test as passed if the given C<$cond> evaluates to C. It also accepts an optional description of the test as second argument. =for code :preamble - my $response; my $query; ...; - ok $response.success, 'HTTP response was successful'; - nok $query.error, 'Query completed without error'; - +my $response; my $query; ...; +nok $query.error, 'Query completed without error'; =head2 sub is @@ -155,23 +156,23 @@ Defined as multi sub is(Mu $got, Mu:U $expected, $desc = '') multi sub is(Mu $got, Mu:D $expected, $desc = '') -Marks a test as passed if C<$value> and C<$expected> compare positively with the -L, unless C<$expected> is a type object, in which case -C<===> operator will be used instead; accepts an optional description of the +Marks a test as passed if C<$got> and C<$expected> compare positively with the +L«C operator|/routine/eq», unless C<$expected> is a type object, in which case +L«C<===> operator|/routine/===» will be used instead; accepts an optional description of the test as the last argument. -B C operator the C uses stringifies, which means C is not +B the C operator stringifies its operands, which means C is not a good function for testing more complex things, such as lists: C passes the test, even though the operands are vastly different. For those cases, use -L«C routine|/language/testing#index-entry-is-deeply-is-deeply($value,_$expected,_$description?)» +L«C routine|#sub_is-deeply» =for code :preamble - my $pdf-document; sub factorial($x) { ... }; ...; - is $pdf-document.author, "Joe", 'Retrieving the author field'; - is factorial(6), 720, 'Factorial - small integer'; - my Int $a; - is $a, Int, 'The variable $a is an unassigned Int'; +my $pdf-document; sub factorial($x) { ... }; ...; +is $pdf-document.author, "Joe", 'Retrieving the author field'; +is factorial(6), 720, 'Factorial - small integer'; +my Int $a; +is $a, Int, 'The variable $a is an unassigned Int'; B if I whitespace differs between the values, C will output failure message differently, to show the whitespace in each values. For example, @@ -189,15 +190,15 @@ Defined as: multi sub isnt(Mu $got, Mu:U $expected, $desc = '') multi sub isnt(Mu $got, Mu:D $expected, $desc = '') -Marks a test as passed if C<$value> and C<$expected> are B equal using +Marks a test as passed if C<$got> and C<$expected> are B equal using the same rules as C. The function accepts an optional description of the test. =for code :preamble - isnt pi, 3, 'The constant π is not equal to 3'; - my Int $a = 23; - $a = Nil; - isnt $a, Nil, 'Nil should not survive being put in a container'; +isnt pi, 3, 'The constant π is not equal to 3'; +my Int $a = 23; +$a = Nil; +isnt $a, Nil, 'Nil should not survive being put in a container'; =head2 sub is_approx @@ -242,7 +243,7 @@ multi sub is-approx(Numeric $got, Numeric $expected, $desc = '', Numeric :$rel-tol is required, Numeric :$abs-tol is required) -Marks a test as passed if the C<$value> and C<$expected> numerical values +Marks a test as passed if the C<$got> and C<$expected> numerical values are approximately equal to each other. The subroutine can be called in numerous ways that let you test using relative tolerance (C<$rel-tol>) or absolute tolerance (C<$abs-tol>) of different values. @@ -252,38 +253,36 @@ value of C<$expected>: if it's smaller than C<1e-6>, use absolute tolerance of C<1e-5>; if it's larger, use relative tolerance of C<1e-6>. =begin code :preamble +my Numeric ($value, $expected, $abs-tol, $rel-tol) = ... - my Numeric ($value, $expected, $abs-tol, $rel-tol) = ... - - is-approx $value, $expected; - is-approx $value, $expected, 'test description'; +is-approx $value, $expected; +is-approx $value, $expected, 'test description'; - is-approx $value, $expected, $abs-tol; - is-approx $value, $expected, $abs-tol, 'test description'; +is-approx $value, $expected, $abs-tol; +is-approx $value, $expected, $abs-tol, 'test description'; - is-approx $value, $expected, :$rel-tol; - is-approx $value, $expected, :$rel-tol, 'test description'; +is-approx $value, $expected, :$rel-tol; +is-approx $value, $expected, :$rel-tol, 'test description'; - is-approx $value, $expected, :$abs-tol; - is-approx $value, $expected, :$abs-tol, 'test description'; +is-approx $value, $expected, :$abs-tol; +is-approx $value, $expected, :$abs-tol, 'test description'; - is-approx $value, $expected, :$abs-tol, :$rel-tol; - is-approx $value, $expected, :$abs-tol, :$rel-tol, 'test description'; +is-approx $value, $expected, :$abs-tol, :$rel-tol; +is-approx $value, $expected, :$abs-tol, :$rel-tol, 'test description'; =end code =head3 Absolute tolerance -When an absolute tolerance is set, it's used as the actual maximum value by -which the C<$value> and C<$expected> can differ. For example: +When an absolute tolerance is set, it's used as the actual maximum value +by which the first and the second parameters can differ. For example: =begin code :preamble +is-approx 3, 4, 2; # success +is-approx 3, 6, 2; # fail - is-approx 3, 4, 2; # success - is-approx 3, 6, 2; # fail - - is-approx 300, 302, 2; # success - is-approx 300, 400, 2; # fail - is-approx 300, 600, 2; # fail +is-approx 300, 302, 2; # success +is-approx 300, 400, 2; # fail +is-approx 300, 600, 2; # fail =end code Regardless of values given, the difference between them cannot be more @@ -298,11 +297,11 @@ larger the value they can differ by can be. For example: =begin code :preamble - is-approx 10, 10.5, :rel-tol<0.1>; # success - is-approx 10, 11.5, :rel-tol<0.1>; # fail +is-approx 10, 10.5, :rel-tol<0.1>; # success +is-approx 10, 11.5, :rel-tol<0.1>; # fail - is-approx 100, 105, :rel-tol<0.1>; # success - is-approx 100, 115, :rel-tol<0.1>; # fail +is-approx 100, 105, :rel-tol<0.1>; # success +is-approx 100, 115, :rel-tol<0.1>; # fail =end code Both versions use C<0.1> for relative tolerance, yet the first can differ @@ -329,7 +328,9 @@ tested independently, and the C test will succeed only if both pass. Defined as: - sub is-approx-calculate ($got,$expected,$abs-tol where { !.defined or $_ >= 0 },$rel-tol where { !.defined or $_ >= 0 },$desc) +=for code :method +sub is-approx-calculate($got, $expected, $abs-tol where { !.defined or $_ >= 0 }, + $rel-tol where { !.defined or $_ >= 0 }, $desc) This is the actual routine called by L when absolute and relative tolerance are specified|/type/Test#Both_absolute_and_relative_tolerance_specified>. @@ -345,7 +346,7 @@ Defined as: multi sub is-deeply(Mu $got, Seq:D $expected, $reason = '') multi sub is-deeply(Mu $got, Mu $expected, $reason = '') -Marks a test as passed if C<$value> and C<$expected> are equivalent, using the +Marks a test as passed if the first and second parameters are equivalent, using the same semantics as the L. This is the best way to check for equality of (deep) data structures. The function accepts an optional description of the test as the last argument. @@ -364,14 +365,13 @@ sub string-info(Str() $_) { )) } -is-deeply string-info('42 Butterflies ♥ Perl'), Map.new(( +is-deeply string-info('42 Butterflies ♥ Raku'), Map.new(( :21length, char-counts => Bag.new-from-pairs: ( :15letters, :2digits, :4other, ) )), 'string-info gives right info'; =end code B for L, - L arguments to C get converted to L by calling L|/routine/cache> on them. If you want to ensure strict C comparisons, use @@ -383,30 +383,30 @@ instead. multi sub cmp-ok(Mu $got is raw, $op, Mu $expected is raw, $desc = '') -Compares C<$value> and C<$expected> with the given C<$comparison> comparator and +Compares C<$got> and C<$expected> with the given C<$op> comparator and passes the test if the comparison yields a C value. The description of the test is optional. -The C<$comparison> comparator can be either a L or +The C<$op> comparator can be either a L or a L containing an infix operator, such as C<'=='>, a C<'~~'>, or a user-defined infix. =for code :preamble - cmp-ok 'my spelling is apperling', '~~', /perl/, "bad speller"; +cmp-ok 'my spelling is apperling', '~~', /perl/, "bad speller"; Metaoperators cannot be given as a string; pass them as a L instead: =for code :preamble - cmp-ok , &[!eqv], , 'not equal'; +cmp-ok , &[!eqv], , 'not equal'; -A L C<$comparison> lets you use custom comparisons: +A L C<$op> lets you use custom comparisons: =for code :preamble - sub my-comp { $^a / $^b < rand }; - cmp-ok 1, &my-comp, 2, 'the dice giveth and the dice taketh away' - cmp-ok 2, -> $a, $b { $a.is-prime and $b.is-prime and $a < $b }, 7, - 'we got primes, one larger than the other!'; +sub my-comp { $^a / $^b < rand }; +cmp-ok 1, &my-comp, 2, 'the dice giveth and the dice taketh away' +cmp-ok 2, -> $a, $b { $a.is-prime and $b.is-prime and $a < $b }, 7, + 'we got primes, one larger than the other!'; =head2 sub isa-ok @@ -414,41 +414,41 @@ Defined as: multi sub isa-ok(Mu $var, Mu $type, $desc = "The object is-a '$type.raku()'") -Marks a test as passed if the given object C<$value> is, or inherits from, the -given C<$expected-type>. For convenience, types may also be specified as a +Marks a test as passed if the given object C<$var> is, or inherits from, the +given C<$type>. For convenience, types may also be specified as a string. The function accepts an optional description of the test, which defaults to a string that describes the object. =begin code :preamble - class Womble {} - class GreatUncleBulgaria is Womble {} - my $womble = GreatUncleBulgaria.new; +class Womble {} +class GreatUncleBulgaria is Womble {} +my $womble = GreatUncleBulgaria.new; - isa-ok $womble, Womble, "Great Uncle Bulgaria is a womble"; - isa-ok $womble, 'Womble'; # equivalent +isa-ok $womble, Womble, "Great Uncle Bulgaria is a womble"; +isa-ok $womble, 'Womble'; # equivalent =end code =head2 sub can-ok Defined as: - multi sub can-ok(Mu $var, Str $meth,$desc = "..." ) + multi sub can-ok(Mu $var, Str $meth, $desc = "..." ) -Marks a test as passed if the given C<$variable> can run the given -C<$method-name>. The function accepts an optional description. For +Marks a test as passed if the given C<$var> can run the method named +C<$meth>. The function accepts an optional description. For instance: =begin code :preamble - class Womble {}; - my $womble = Womble.new; +class Womble {}; +my $womble = Womble.new; - # with automatically generated test description - can-ok $womble, 'collect-rubbish'; - # => An object of type 'Womble' can do the method 'collect-rubbish' +# with automatically generated test description +can-ok $womble, 'collect-rubbish'; +# => An object of type 'Womble' can do the method 'collect-rubbish' - # with human-generated test description - can-ok $womble, 'collect-rubbish', "Wombles can collect rubbish"; - # => Wombles can collect rubbish +# with human-generated test description +can-ok $womble, 'collect-rubbish', "Wombles can collect rubbish"; +# => Wombles can collect rubbish =end code =head2 sub does-ok @@ -457,59 +457,61 @@ Defined as: multi sub does-ok(Mu $var, Mu $type, $desc = "...") -Marks a test as passed if the given C<$variable> can do the given C<$role>. +Marks a test as passed if the given C<$var> can do the given role C<$type>. The function accepts an optional description of the test. =begin code :preamble - # create a Womble who can invent - role Invent { - method brainstorm { say "Aha!" } - } - class Womble {} - class Tobermory is Womble does Invent {} +# create a Womble who can invent +role Invent { + method brainstorm { say "Aha!" } +} +class Womble {} +class Tobermory is Womble does Invent {} - # ... and later in the tests - use Test; +# ... and later in the tests +use Test; - my $tobermory = Tobermory.new; +my $tobermory = Tobermory.new; - # with automatically generated test description - does-ok $tobermory, Invent; - # => The object does role Type +# with automatically generated test description +does-ok $tobermory, Invent; +# => The object does role Type - does-ok $tobermory, Invent, "Tobermory can invent"; - # => Tobermory can invent +does-ok $tobermory, Invent, "Tobermory can invent"; +# => Tobermory can invent =end code =head2 sub like Defined as: - sub like(Str() $got, Regex:D $expected,$desc = "text matches $expected.raku()") + sub like(Str() $got, Regex:D $expected, $desc = "text matches $expected.raku()") Use it this way: =for code :preamble - like 'foo', /fo/, 'foo looks like fo'; +like 'foo', /fo/, 'foo looks like fo'; -Marks a test as passed if the C<$value>, when coerced to a string, matches the -C<$expected-regex>. The function accepts an optional description of the -test with a default value printing the expected match. +Marks a test as passed if the first parameter, when coerced to a string, +matches the regular expression specified as the second parameter. +The function accepts an optional description of the test with a default +value printing the expected match. =head2 sub unlike Defined as: - multi sub unlike(Str() $got, Regex:D $expected,$desc = "text does not match $expected.raku()") + multi sub unlike(Str() $got, Regex:D $expected, $desc = "text does not match $expected.raku()") Used this way: =for code :preamble - unlike 'foo', /bar/, 'foo does not look like bar'; +unlike 'foo', /bar/, 'foo does not look like bar'; -Marks a test as passed if the C<$value>, when coerced to a string, does B -match the C<$expected-regex>. The function accepts an optional description -of the test, which defaults to printing the text that did not match. +Marks a test as passed if the first parameter, when coerced to a string, +does B match the regular expression specified as the second +parameter. The function accepts an optional description of the test, +which defaults to printing the text that did not match. =head2 sub use-ok @@ -624,7 +626,7 @@ The function accepts an optional description of the test as the third positional argument. The routine makes L fatal. If you wish to avoid that, -use L«C pragma|/language/pragmas#index-entry-fatal-fatal» and ensure +use L«C pragma|/language/pragmas#fatal» and ensure the tested code does not sink the possible L. If you wish to test that the code returns a L instead of throwing, use C routine instead. @@ -726,18 +728,17 @@ Mark C<$count> tests as TODO, giving a C<$reason> as to why. By default only one test will be marked TODO. =begin code :preamble - sub my-custom-pi { 3 }; +sub my-custom-pi { 3 }; - todo 'not yet precise enough'; # Mark the test as TODO. - is my-custom-pi(), pi, 'my-custom-pi'; # Run the test, but don't report - # failure in test harness. +todo 'not yet precise enough'; # Mark the test as TODO. +is my-custom-pi(), pi, 'my-custom-pi'; # Run the test, but don't report + # failure in test harness. =end code The result from the test code above will be something like: =begin code :lang -not ok 1 - my-custom-pi# TODO not yet precise enough - +not ok 1 - my-custom-pi # TODO not yet precise enough # Failed test 'my-custom-pi' # at test-todo.t line 7 # expected: '3.14159265358979' @@ -801,9 +802,9 @@ C call will throw an error. Note that C does not exit the test run. Do it manually, or use conditionals to avoid running any further tests. -See also L«C|/language/testing#index-entry-plan-plan($count)» +See also L«C|#sub_plan» to avoid running any tests at all and -L«C|/language/testing#index-entry-bail-out-bail-out($reason?)» to abort +L«C|#sub_bail-out» to abort the test run and mark it as failed. =head2 sub bail-out @@ -824,8 +825,8 @@ Takes an optional reason for bailing out. The subroutine will call C, so if you need to do a clean-up, do it before calling C. If you want to abort the test run, but without marking it as failed, see -L«C|/language/testing#index-entry-skip-rest-skip-rest($reason?)» -or L«C|/language/testing#index-entry-plan-plan($count)» +L«C|#sub_skip-rest» +or L«C|#sub_plan» =head2 sub pass diff --git a/doc/Type/Thread.pod6 b/doc/Type/Thread.pod6 index c26b7b061..9bb0673e9 100644 --- a/doc/Type/Thread.pod6 +++ b/doc/Type/Thread.pod6 @@ -13,8 +13,8 @@ underlying virtual machines (which in turn might or might not be operating system threads). Since threads are fairly low-level, most applications should use other -primitives, like L, which also runs in -parallel and returns a L. +primitives, like L«C|/type/Promise#method_start», which also runs in +parallel and returns a L«C|/type/Promise». =begin code my @threads = (^10).map: { diff --git a/doc/Type/Uni.pod6 b/doc/Type/Uni.pod6 index 8a08d0935..daf577364 100644 --- a/doc/Type/Uni.pod6 +++ b/doc/Type/Uni.pod6 @@ -23,6 +23,14 @@ C and C, which represent strings in one of the L instance from the given codepoint numbers. +=head2 method list + +Defined as: + + method list(Uni:D:) + +Returns a C of integer codepoints. + =head2 method NFC method NFC(Uni:D: --> NFC:D) diff --git a/doc/Type/ValueObjAt.pod6 b/doc/Type/ValueObjAt.pod6 index fdfedb7d4..ec90089f2 100644 --- a/doc/Type/ValueObjAt.pod6 +++ b/doc/Type/ValueObjAt.pod6 @@ -7,7 +7,7 @@ class ValueObjAt is ObjAt { } A subclass of L|/type/ObjAt> that should be used to indicate that a class -produces objects that are value types (in other words: are immutable after +produces objects that are value types - in other words, that are immutable after they have been initialized. my %h = a => 42; # mutable Hash diff --git a/doc/Type/Whatever.pod6 b/doc/Type/Whatever.pod6 index b48e864bb..2e448bcab 100644 --- a/doc/Type/Whatever.pod6 +++ b/doc/Type/Whatever.pod6 @@ -6,11 +6,13 @@ class Whatever { } +X<|* literal> X<|Whatever literal> C is a class whose objects don't have any explicit meaning; it gets its semantics from other routines that accept C-objects as markers to do something special. Using the C<*> literal as an operand creates a C object. +X<|Whatever-currying> Much of C<*>'s charm comes from I. When C<*> is used in term position, that is, as an operand, in combination with most operators, the compiler will transform the expression into a closure of diff --git a/doc/Type/X/Does/TypeObject.pod6 b/doc/Type/X/Does/TypeObject.pod6 index 4c3829f6a..d702068ba 100644 --- a/doc/Type/X/Does/TypeObject.pod6 +++ b/doc/Type/X/Does/TypeObject.pod6 @@ -25,7 +25,7 @@ Roles may only be runtime-mixed into defined object instances: GrassmannNumber.new does AlgebraDebugger; (This restriction may be worked around by using -L, or +L, or with dark Metamodel magics, but this will likely result in a significant performance penalty.) diff --git a/doc/Type/X/Inheritance/NotComposed.pod6 b/doc/Type/X/Inheritance/NotComposed.pod6 index aa22ffd20..564424b7d 100644 --- a/doc/Type/X/Inheritance/NotComposed.pod6 +++ b/doc/Type/X/Inheritance/NotComposed.pod6 @@ -7,7 +7,7 @@ class X::Inheritance::NotComposed is Exception {} When you try to inherit from a class that hasn't been -L, an +L, an exception of type X::Inheritance::NotComposed is thrown. Usually this happens because it's not yet fully parsed, or that is stubbed: diff --git a/doc/Type/X/Proc/Async/BindOrUse.pod6 b/doc/Type/X/Proc/Async/BindOrUse.pod6 index b5c8a001b..912a77eab 100644 --- a/doc/Type/X/Proc/Async/BindOrUse.pod6 +++ b/doc/Type/X/Proc/Async/BindOrUse.pod6 @@ -5,7 +5,7 @@ =SUBTITLE Error due to trying to bind a handle that is also used =for code :preamble - class X::Proc::Async::BindOrUse does X::Proc::Async {} +class X::Proc::Async::BindOrUse does X::Proc::Async {} In general, it occurs when there's some mistake in the direction the stream flows, for instance: diff --git a/doc/Type/X/Syntax/Comment/Embedded.pod6 b/doc/Type/X/Syntax/Comment/Embedded.pod6 index feb5e2208..65b2ba575 100644 --- a/doc/Type/X/Syntax/Comment/Embedded.pod6 +++ b/doc/Type/X/Syntax/Comment/Embedded.pod6 @@ -11,7 +11,7 @@ an opening curly brace. For example -=for code +=for code :skip-test #` dies with diff --git a/doc/Type/independent-routines.pod6 b/doc/Type/independent-routines.pod6 index 13f84f420..3b5c2c5ba 100644 --- a/doc/Type/independent-routines.pod6 +++ b/doc/Type/independent-routines.pod6 @@ -13,17 +13,20 @@ Defined as: =begin code :method proto sub EVAL($code where Blob|Cool|Callable, Str() :$lang = 'Raku', - PseudoStash :$context, *%n) + PseudoStash :$context, Str() :$filename, Bool() :$check, *%_) =end code =begin code :method multi sub EVAL($code, Str :$lang where { ($lang // '') eq 'Perl5' }, - PseudoStash :$context) + PseudoStash :$context, Str() :$filename, :$check) =end code -This routine coerces L C<$code> to L. If +This routine executes at runtime a fragment of code, C<$code>, of a given language, +C<$lang>, which defaults to C. + +It coerces L C<$code> to L. If C<$code> is a L, it'll be processed using the same encoding as the C<$lang> compiler would: for C C<$lang>, uses C; for C, -processes using the same rules as C. +processes using the same rules as Perl. This works as-is with a literal string parameter. More complex input, such as a variable or string with embedded code, is illegal by default. @@ -33,8 +36,13 @@ This can be overridden in any of several ways: use MONKEY; # shortcut that turns on all MONKEY pragmas use Test; + my $init = 0; + my $diff = 10; + my Str $changer = '$init += ' ~ $diff; # contains a Str object with value '$init += 10' # any of the above allows: - EVAL "say { 5 + 5 }"; # OUTPUT: «10␤» + EVAL $changer; + EVAL $changer; + say $init; # OUTPUT: «20␤» In case the C pragma is not activated, the compiler will complain with a C exception. And it is @@ -93,19 +101,39 @@ EVAL "use v5.20; say 'Hello from perl!'", :lang; You need to have L|https://github.com/niner/Inline-Perl5> for this to work correctly. +More languages may be supported with additional +modules which may be found from the +L. + +If the optional C<$filename> parameter is given, the +L«C<$?FILE>|/language/variables#index-entry-$%3FFILE» variable is set to +its value. Otherwise C<$?FILE> is set to a unique and generated file name. + +=for code +use MONKEY-SEE-NO-EVAL; +EVAL 'say $?FILE'; # OUTPUT: «/tmp/EVAL_0␤» +EVAL 'say $?FILE', filename => '/my-eval-code'; # OUTPUT: «/my-eval-code␤» + +If the optional C<$check> parameter is C, C<$code> +is processed by the C<$lang> compiler but is not actually +run. For C, L«C|/language/phasers#BEGIN», and +L«C|/language/phasers#CHECK» blocks are run. The C routine +then returns C if compilation was successful, otherwise an exception +is thrown. + =head2 sub EVALFILE Defined as: - sub EVALFILE($filename where Blob|Cool, :$lang = 'Raku') + sub EVALFILE($filename where Blob|Cool, :$lang = 'Raku', :$check) Slurps the specified file and evaluates it. Behaves the same way as -C with regard to L decoding, scoping, and the C<$lang> -parameter. Evaluates to the value produced by the final statement in the -file. +C with regard to L decoding, scoping, the C<$lang> +parameter and the C<$check> parameter. Evaluates to the value produced +by the final statement in the file when C<$check> is not C. =for code -EVALFILE "foo.p6"; +EVALFILE "foo.raku"; =head2 sub mkdir @@ -218,7 +246,7 @@ C was successfully executed. Defined as: - sub indir(IO() $path, &code, :$d = True, :$r, :$w, :$x --> Mu) + sub indir(IO() $path, &code, :$d = True, :$r, :$w, :$x) Takes L«C|/type/Callable» C<&code> and executes it after locally (to C<&code>) changing C<$*CWD> variable to an L object based on C<$path>, @@ -229,7 +257,7 @@ current directory (see L«C<&*chdir>|/routine/&*chdir»). The C<$*CWD> outside of the C<&code> is not affected, even if C<&code> explicitly assigns a new value to C<$*CWD>. -Returns the return value of C<&code> on success. On failure to +Returns the value returned by the C<&code> call on success. On failure to successfully change C<$*CWD>, returns L«C|/type/Failure». B keep in mind that lazily evaluated things might end up NOT having the C<$*CWD> set by C in their dynamic scope by the time @@ -278,10 +306,11 @@ Defined as: multi sub print(Junction:D --> True) Prints the given text on standard output (the -L«C<$*OUT>|/language/variables#index-entry-%24%2AOUT» filehandle), coercing non-L objects -to L by calling L«C<.Str> method|/routine/Str». L arguments -L and the order of printed strings -is not guaranteed. +L«C<$*OUT>|/language/variables#index-entry-%24%2AOUT» filehandle), coercing +non-L objects to L by calling L«C<.Str> +method|/routine/Str». L arguments +L and the order of +printed strings is not guaranteed. print "Hi there!\n"; # OUTPUT: «Hi there!␤» print "Hi there!"; # OUTPUT: «Hi there!» @@ -407,7 +436,7 @@ do not need to C files or deal with L type di =begin code my $fh = open :w, '/tmp/some-file.txt'; -$fh.say: 'I ♥ writing Perl code'; +$fh.say: 'I ♥ writing Raku code'; $fh.close; $fh = open '/tmp/some-file.txt'; @@ -416,7 +445,7 @@ $fh.seek: 7, SeekFromCurrent; say $fh.readchars: 4; $fh.close; -# OUTPUT: «I ♥ Perl␤» +# OUTPUT: «I ♥ Raku␤» =end code =head2 sub slurp @@ -507,6 +536,7 @@ sub run( Str:D :$nl = "\n", :$cwd = $*CWD, Hash() :$env = %*ENV, + :$arg0, :$win-verbatim-args = False --> Proc:D) @@ -565,7 +595,7 @@ These argument are quite flexible and admit, for instance, handles to redirect them. See L and L for more details. -See also L|/type/Proc#method_new> and L|/type/Proc#method_spawn> +See also L|/type/Proc#routine_new> and L|/type/Proc#method_spawn> for more examples and explanation of all arguments. =head2 sub shell @@ -580,7 +610,7 @@ Runs a command through the system shell, which defaults to C<%*ENV /c> in Windows, C otherwise. All shell metacharacters are interpreted by the shell, including pipes, redirects, environment variable substitutions and so on. Shell escapes are a severe security concern and can cause confusion with -unusual file names. Use L if you want to be safe. +unusual file names. Use L if you want to be safe. The return value is of L. @@ -607,14 +637,13 @@ the case it's being used as a C Defined as: - method printf (*@args) multi sub printf(Cool:D $format, *@args) -As a method, takes the object as a format using -L|/routine/sprintf>; as a sub, its -first argument will be -the format string, and the rest of the arguments will be substituted in the -format following the format conventions. +Produces output according to a format. The format used is the invocant +(if called in method form) or the first argument (if called as a routine). +The rest of the arguments will be substituted in the format following +the format conventions. See L for details on +acceptable format directives. "%s is %s".printf("þor", "mighty"); # OUTPUT: «þor is mighty» printf( "%s is %s", "þor", "mighty"); # OUTPUT: «þor is mighty» @@ -627,18 +656,17 @@ On Cs, it will also autothread, without a guaranteed order. Defined as: - method sprintf(*@args) multi sub sprintf(Cool:D $format, *@args) -Formats and returns a string, following -L|/routine/sprintf>, using as such -format either the object (if called in method form) or the first argument (if -called as a routine) +Returns a string according to a format as described below. The format +used is the invocant (if called in method form) or the first argument +(if called as a routine). sprintf( "%s the %d%s", "þor", 1, "st").put; # OUTPUT: «þor the 1st␤» sprintf( "%s is %s", "þor", "mighty").put; # OUTPUT: «þor is mighty␤» "%s's weight is %.2f %s".sprintf( "Mjölnir", 3.3392, "kg").put; # OUTPUT: «Mjölnir's weight is 3.34 kg␤» + # OUTPUT: «Mjölnir's weight is 3.34 kg␤» This function is mostly identical to the C library's C and C functions. The only difference between the two functions is that C @@ -719,7 +747,7 @@ Compatibility: =end table -=head2 Modifiers +=head3 Modifiers Modifiers change the meaning of format directives, but are largely no-ops (the semantics are still being determined). @@ -1160,10 +1188,106 @@ Defined as: B in 6.d language version and will be removed in 6.e. For L and L, it will become equivalent to -assigning L; for everything else, +assigning L; for everything else, equivalent to assigning L or C in the case of arrays or hashes, whose use is advised. +=head1 Array manipulation + +Routines that manipulate arrays and other mutable collections. + +=head2 sub pop + +Defined as: + + multi sub pop(@a) is raw + +Calls method C on the C argument. That method is supposed to +remove and return the last element, or return a L|/type/Failure> if +the collection is empty. + +See the documentation of the L method|/routine/pop#(Array)_method_pop> +for an example. + +=head2 sub shift + +Defined as: + + multi sub shift(@a) is raw + +Calls method C on the C argument. That method, on +a mutable collection that actually implements it (such as an +L|/routine/shift#(Array)_method_shift> or a +L|/routine/shift#(Buf)_method_shift>), is supposed to remove +and return the first element, or return a L|/type/Failure> if the +collection is empty. + +Example: + + say shift [1,2]; # OUTPUT: «1␤» + +=for code +my @a of Int = [1]; +say shift @a; # OUTPUT: «1␤» +say shift @a; # ERROR: «Cannot shift from an empty Array[Int]␤» + +=head2 sub push + +Defined as: + + multi sub push(\a, **@b is raw) + multi sub push(\a, \b) + +Calls method C on the first argument, passing the remaining arguments. +Method C is supposed to add the provided values to the end of the +collection or parts thereof. See the documentation of the +L method|/routine/push#(Hash)_method_push> for an example where +indirection via this subroutine can be helpful. + +The C method is supposed to flatten all arguments of type C. +Therefore, if you want to implement a conforming method for a new collection +type, it should behave as if its signature was just: + + multi method push(::?CLASS:D: **@values is raw --> ::?CLASS:D) + +Autovivification to an instance of the new type is L if the new type implements the +C role. If the new type is not C, autovivification can +be supported by an adding a multi method with a signature like + + multi method push(::?CLASS:U: **@values is raw --> ::?CLASS:D) + +=head2 sub append + +Defined as: + + multi sub append(\a, **@b is raw) + multi sub append(\a, \b) + +Calls method C on the first argument, passing the remaining arguments. +Method C is supposed to add the provided values to the end of the +collection or parts thereof. Unlike method C, method C should +follow the L. So +if you want to implement a conforming method C for a new collection +type, it should behave as if its signature was just: + + multi method append(::?CLASS:D: +values --> ::?CLASS:D) + +Similar to L|/routine/push#(Independent_routines)_sub_push>, you +may need to add a multi method if you want to support autovivification: + + multi method append(::?CLASS:U: +values --> ::?CLASS:D) + +The subroutine form of C can be helpful when appending to the values of +a C. Whereas L|/routine/append#(Hash)_method_append> will +silently ignore literal pairs that are interpreted as named arguments, the +subroutine will throw: + + my %h = i => 0; + append %h, i => (1, 42); + CATCH { default { put .message } }; + # OUTPUT: «Unexpected named argument 'i' passed␤» + =head1 Control routines Routines that change the flow of the program, maybe returning a value. @@ -1183,7 +1307,7 @@ from zero from a L. C prevents the L phaser to be executed, but it will run the code in the -L|/language/variables#index-entry-%24*EXIT> variable. +L|/language/variables#index-entry-%26*EXIT> variable. C should be used as last resort only to signal the parent process about an exit code different from zero, and not to terminate @@ -1215,6 +1339,49 @@ $supply.tap( -> $v { say "Second : $v" }, done => { say "No more" }); The block passed to the C named argument will be run when C is called within the C block. +=head2 sub lastcall + + sub lastcall(--> True) + +Truncates the current dispatch chain, which means any calls to +C, C, C, and C will not +find any of the next candidates. Note that since C +restarts the dispatch from the start, it's not affected by the +truncation of current chain with C. + +Consider example below. C uses C +when C hasn't been called, and so it reaches the C +candidate. C calls C as well, but since +C was called first, the dispatch chain was truncated and +the C candidate was not reached. The last call, C, +calls C too, however, it then uses C, which +isn't affected by it, and so the dispatch re-starts from scratch, +hits the C candidate with the new argument C<6>, and then +proceeds to the C candidate via C (which +isn't affected by the C that was used before the +C was called): + + multi foo (Int $_) { + say "Int: $_"; + lastcall when *.is-prime; + nextsame when * %% 2; + samewith 6 when * !%% 2; + } + multi foo (Any $x) { say "Any $x" } + + foo 6; say '----'; + foo 2; say '----'; + foo 1; + + # OUTPUT: + # Int: 6 + # Any 6 + # ---- + # Int: 2 + # ---- + # Int: 1 + # Int: 6 + # Any 6 =end pod diff --git a/documentable.json b/documentable.json new file mode 100644 index 000000000..5f7daa25c --- /dev/null +++ b/documentable.json @@ -0,0 +1,94 @@ +{ + "title-page": "Raku official documentation", + "pod-root-path": "https://github.com/Raku/doc/edit/master/doc/", + "irc-link": "https://web.libera.chat/?channel=#raku", + "kinds": [ + { + "kind": "language", + "sort": "1", + "display-text": "Language", + "categories": [ + { + "name": "beginning", + "display-text": "At the beginning" + }, + { + "name": "migration", + "display-text": "Migration guides" + }, + { + "name": "tutorial", + "display-text": "Tutorials" + }, + { + "name": "fundamental", + "display-text": "Fundamental topics" + }, + { + "name": "reference", + "display-text": "General reference" + }, + { + "name": "advanced", + "display-text": "Advanced topics" + } + ] + }, + { + "kind": "type", + "display-text": "Types", + "categories": [ + { + "name": "basic", + "display-text": "Basic" + }, + { + "name": "composite", + "display-text": "Composite" + }, + { + "name": "domain-specific", + "display-text": "Domain-specific" + }, + { + "name": "exception", + "display-text": "Exceptions" + } + ] + }, + { + "kind": "routine", + "display-text": "Routines", + "categories": [ + { + "name": "sub", + "display-text": "Sub" + }, + { + "name": "method", + "display-text": "Method" + }, + { + "name": "term", + "display-text": "Term" + }, + { + "name": "operator", + "display-text": "Operator" + }, + { + "name": "trait", + "display-text": "Trait" + }, + { + "name": "submethod", + "display-text": "Submethod" + } + ] + }, + { + "kind": "programs", + "display-text": "Programs" + } + ] +} diff --git a/highlights/highlight-file.coffee b/highlights/highlight-file.coffee index 327e715db..4ecb3eb50 100755 --- a/highlights/highlight-file.coffee +++ b/highlights/highlight-file.coffee @@ -4,8 +4,15 @@ Highlights = require 'highlights' fs = require 'fs' path = require 'path' highlighter = new Highlights() +modPath = require.resolve('./atom-language-perl6/package.json') highlighter.requireGrammarsSync - modulePath: require.resolve('./atom-language-perl6/package.json') + modulePath: modPath + +rakuGrammarPath = path.join(path.dirname(modPath), 'grammars', 'raku.cson') +if fs.existsSync(rakuGrammarPath) + rakuScopeName = 'source.raku' +else + rakuScopeName = 'source.perl6fe' file_to_hl = path.resolve(process.argv[2]) foo = -> @@ -13,6 +20,6 @@ foo = -> html = highlighter.highlightSync fileContents: foo() - scopeName: 'source.perl6fe' + scopeName: rakuScopeName console.log html diff --git a/highlights/highlight-filename-from-stdin.coffee b/highlights/highlight-filename-from-stdin.coffee index 3d24785a1..5ebfb21db 100755 --- a/highlights/highlight-filename-from-stdin.coffee +++ b/highlights/highlight-filename-from-stdin.coffee @@ -4,8 +4,15 @@ Highlights = require 'highlights' fs = require 'fs' path = require 'path' highlighter = new Highlights() +modPath = require.resolve('./atom-language-perl6/package.json') highlighter.requireGrammarsSync - modulePath: require.resolve('./atom-language-perl6/package.json') + modulePath: modPath + +rakuGrammarPath = path.join(path.dirname(modPath), 'grammars', 'raku.cson') +if fs.existsSync(rakuGrammarPath) + rakuScopeName = 'source.raku' +else + rakuScopeName = 'source.perl6fe' stdin = process.openStdin() stdin.setEncoding 'utf8' @@ -27,7 +34,7 @@ process_file = (given_path) -> if read_err console.error read_err else - highlighter.highlight (fileContents: file_str, scopeName: 'source.perl6fe'), (hl_err, html) -> + highlighter.highlight (fileContents: file_str, scopeName: rakuScopeName), (hl_err, html) -> if hl_err console.error hl_err else diff --git a/highlights/highlight-folder.coffee b/highlights/highlight-folder.coffee index cdc188975..46b119895 100644 --- a/highlights/highlight-folder.coffee +++ b/highlights/highlight-folder.coffee @@ -2,8 +2,15 @@ Highlights = require 'highlights' fs = require 'fs' path = require 'path' highlighter = new Highlights() +modPath = require.resolve('./atom-language-perl6/package.json') highlighter.requireGrammarsSync - modulePath: require.resolve('./atom-language-perl6/package.json') + modulePath: modPath) + +rakuGrammarPath = path.join(path.dirname(modPath), 'grammars', 'raku.cson') +if fs.existsSync(rakuGrammarPath) + rakuScopeName = 'source.raku' +else + rakuScopeName = 'source.perl6fe' TestFolder = path.resolve('TestFolder') files = fs.readdirSync(TestFolder) @@ -13,6 +20,6 @@ for file in files fs.readFileSync path.resolve(TestFolder, file), 'utf8' html = highlighter.highlightSync fileContents: foo() - scopeName: 'source.perl6fe' + scopeName: rakuScopeName console.log html diff --git a/html/.htaccess b/html/.htaccess index 409224a78..63dba7373 100644 --- a/html/.htaccess +++ b/html/.htaccess @@ -33,8 +33,8 @@ Redirect 301 /language/5to6 https://docs.perl6.org/language/5to6-nutshell Redirect 301 /examples http://examples.perl6.org/ Redirect 301 /perl6.xhtml https://docs.perl6.org/perl6.html Redirect 301 /examples.html http://examples.perl6.org/ -Redirect 303 /webchat https://webchat.freenode.net/?channels=#perl6 -Redirect 303 /webchat.html https://webchat.freenode.net/?channels=#perl6 +Redirect 303 /webchat https://kiwiirc.com/client/irc.libera.chat/#raku +Redirect 303 /webchat.html https://kiwiirc.com/client/irc.libera.chat/#raku ErrorDocument 404 /404.html diff --git a/lib/Pod/Cache.pm6 b/lib/Pod/Cache.rakumod similarity index 53% rename from lib/Pod/Cache.pm6 rename to lib/Pod/Cache.rakumod index 732cb6bd4..f45f65a2f 100644 --- a/lib/Pod/Cache.pm6 +++ b/lib/Pod/Cache.rakumod @@ -1,7 +1,11 @@ unit class Pod::Cache; -# Given a filename, generate a cached, rendered version of the POD -# in that file as text. +=begin overview + +Given a filename, generate a cached, rendered text version of the POD +in that file. + +=end overview method cache-file(Str $file --> Str) { my $outfile = '.pod-cache/' ~ $file; @@ -10,7 +14,10 @@ method cache-file(Str $file --> Str) { my $in-time = $file.IO.modified; my $out-time = $output-io.e ?? $output-io.modified !! 0; - if $in-time > $out-time { + # If the input file is newer or the target file is empty, cache. + # The empty check helps in cases where the cache creation died for some reason + + if $in-time > $out-time || $output-io.s == 0 { mkdir $output-io.dirname; my $outfile = $output-io.open(:w); LEAVE $outfile.close; @@ -18,7 +25,10 @@ method cache-file(Str $file --> Str) { my $job = Proc::Async.new($*EXECUTABLE-NAME, '--doc', $file); $job.stdout.tap(-> $buf {$outfile.print: $buf}); - await $job.start; + my $has-error = ! await $job.start; + if $has-error { + note "Error occurred caching $file"; + } } $outfile } diff --git a/lib/Pod/Convenience.pm6 b/lib/Pod/Convenience.pm6 deleted file mode 100644 index c38bc4d5e..000000000 --- a/lib/Pod/Convenience.pm6 +++ /dev/null @@ -1,134 +0,0 @@ -unit module Pod::Convenience; - -sub pod-gist(Pod::Block $pod, $level = 0) is export { - my $leading = ' ' x $level; - my %confs; - my @chunks; - for { - my $thing = $pod.?"$_"(); - if $thing { - %confs{$_} = $thing ~~ Iterable ?? $thing.perl !! $thing.Str; - } - } - @chunks = $leading, $pod.^name, (%confs.perl if %confs), "\n"; - for $pod.contents.list -> $c { - if $c ~~ Pod::Block { - @chunks.append: pod-gist($c, $level + 2); - } - elsif $c ~~ Str { - @chunks.append: $c.indent($level + 2), "\n"; - } elsif $c ~~ Positional { - @chunks.append: $c.map: { - if $_ ~~ Pod::Block { - *.&pod-gist - } elsif $_ ~~ Str { - $_ - } - } - } - } - @chunks.join; -} - -sub first-code-block(@pod) is export { - @pod.first(* ~~ Pod::Block::Code).contents.grep(Str).join; -} - -sub pod-with-title($title, *@blocks) is export { - Pod::Block::Named.new( - name => "pod", - contents => [ - flat pod-title($title), @blocks - ] - ); -} - -sub pod-title($title) is export { - Pod::Block::Named.new( - name => "TITLE", - contents => Array.new( - Pod::Block::Para.new( - contents => [$title], - ) - ) - ); -} - -sub pod-block(*@contents) is export { - Pod::Block::Para.new(:@contents); -} - -sub pod-link($text, $url) is export { - Pod::FormattingCode.new( - type => 'L', - contents => [$text], - meta => [$url], - ); -} - -sub pod-bold($text) is export { - Pod::FormattingCode.new( - type => 'B', - contents => [$text], - ); -} - -sub pod-code($text) is export { - Pod::FormattingCode.new( - type => 'C', - contents => [$text], - ); -} - -sub pod-item(*@contents, :$level = 1) is export { - Pod::Item.new( - :$level, - :@contents, - ); -} - -sub pod-heading($name, :$level = 1) is export { - Pod::Heading.new( - :$level, - :contents[pod-block($name)], - ); -} - -sub pod-table(@contents, :@headers) is export { - Pod::Block::Table.new( - |(:@headers if @headers), - :@contents - ); -} - -sub pod-lower-headings(@content, :$to = 1) is export { - my $by = @content.first(Pod::Heading).level; - return @content unless $by > $to; - my @new-content; - for @content { - @new-content.append: $_ ~~ Pod::Heading - ?? Pod::Heading.new: :level(.level - $by + $to) :contents[.contents] - !! $_; - } - @new-content; -} - -my $precomp-store = CompUnit::PrecompilationStore::File.new(:prefix($?FILE.IO.parent.child("precompiled"))); -my $precomp = CompUnit::PrecompilationRepository::Default.new(store => $precomp-store); - -sub extract-pod(IO() $file) is export { - use nqp; - # The file name is enough for the id because POD files don't have depends - my $id = nqp::sha1(~$file); - my $handle = $precomp.load($id,:since($file.modified))[0]; - - if not $handle { - # precompile it - $precomp.precompile($file, $id, :force); - $handle = $precomp.load($id)[0]; - } - - return nqp::atkey($handle.unit,'$=pod')[0]; -} - -# vim: expandtab shiftwidth=4 ft=perl6 diff --git a/lib/Pod/Convenience.rakumod b/lib/Pod/Convenience.rakumod new file mode 100644 index 000000000..2d10fa629 --- /dev/null +++ b/lib/Pod/Convenience.rakumod @@ -0,0 +1,29 @@ +unit module Pod::Convenience; + +=begin overview + +Provide an C sub which returns an object containing all the pod +elements from a given file. + +=end overview + + +my $precomp-store = CompUnit::PrecompilationStore::File.new(:prefix($?FILE.IO.parent(3).child(".pod-precomp"))); +my $precomp = CompUnit::PrecompilationRepository::Default.new(store => $precomp-store); + +sub extract-pod(IO() $file) is export { + use nqp; + # The file name is enough for the id because POD files don't have depends + my $id = nqp::sha1(~$file); + my $handle = $precomp.load($id,:since($file.modified))[0]; + + if not $handle { + # precompile it + $precomp.precompile($file, $id, :force); + $handle = $precomp.load($id)[0]; + } + + return nqp::atkey($handle.unit,'$=pod')[0]; +} + +# vim: expandtab shiftwidth=4 ft=perl6 diff --git a/lib/Test-Files.pm6 b/lib/Test-Files.pm6 deleted file mode 100644 index 32190967c..000000000 --- a/lib/Test-Files.pm6 +++ /dev/null @@ -1,26 +0,0 @@ -unit class Test-Files; - -method files() { - my @files; - - if @*ARGS { - @files = @*ARGS; - } else { - if %*ENV { - @files = %*ENV.trim.split(/ \s /).grep(*.IO.e); - } else { - @files = qx.lines; - } - } - return @files; -} - -method pods() { - return $.files.grep({$_.ends-with: '.pod6'}) -} - -method documents() { - return $.files.grep({$_.ends-with: '.pod6' or $_.ends-with: '.md'}) -} - -# vim: expandtab shiftwidth=4 ft=perl6 diff --git a/lib/Test-Files.rakumod b/lib/Test-Files.rakumod new file mode 100644 index 000000000..96994f213 --- /dev/null +++ b/lib/Test-Files.rakumod @@ -0,0 +1,44 @@ +unit class Test-Files; + +=begin overview + +Provide methods to generate a list of all C, C documents, +all C (POD and markdown), and C based on the output +of C. + +If the environment variable C is set, it's treated a +space-separated list of files to use instead. Files are trimmed from the list +if they don't exist. + +If files were passed on the command line, use that list (as is) instead. + +=end overview + +method files() { + my @files; + + if @*ARGS { + @files = @*ARGS; + } else { + if %*ENV { + @files = %*ENV.trim.split(/ \s /).grep(*.IO.e); + } else { + @files = qx.lines; + } + } + return @files.sort; +} + +method pods() { + return $.files.grep({$_.ends-with: '.pod6'}) +} + +method documents() { + return $.files.grep({$_.ends-with: '.pod6' or $_.ends-with: '.md'}) +} + +method tests() { + return $.files.grep({$_.ends-with: '.t'}) +} + +# vim: expandtab shiftwidth=4 ft=perl6 diff --git a/resources/i18n/zh/README.zh.md b/resources/i18n/zh/README.zh.md index 7a67fb792..d07d778ad 100644 --- a/resources/i18n/zh/README.zh.md +++ b/resources/i18n/zh/README.zh.md @@ -3,15 +3,13 @@ [![Build Status](https://travis-ci.org/Raku/doc.svg?branch=master)](https://travis-ci.org/Raku/doc) [![artistic](https://img.shields.io/badge/license-Artistic%202.0-blue.svg?style=flat)](https://opensource.org/licenses/Artistic-2.0) [![Run Status](https://api.shippable.com/projects/591e99923f2f790700098a30/badge?branch=master)](https://app.shippable.com/github/Raku/doc) [![CircleCI](https://circleci.com/gh/Raku/doc.svg?style=shield)](https://circleci.com/gh/Raku/doc/tree/master) 本文档的 HTML 版本位于 [https://docs.raku.org/](https://docs.raku.org/) 和 -[`rakudocs.github.io`](https://rakudocs.github.io) (后者实际上更新更频繁)。 +[`rakudocs.github.io`](https://rakudocs.github.io) (后者更新更频繁)。 目前推荐使用这种方式来访问文档。 -本仓库还提供命令行工具 `p6doc` 用于阅读文档(见下)。 - ## Docker 镜像 官方文档的 Docker 镜像地址为 [`jjmerelo/perl6-doc`](https://hub.docker.com/r/jjmerelo/perl6-doc) 。 -这个镜像包含了一份 Web 版本的文档,对应的端口为 3000。你可以这样运行这个镜像: +这个镜像包含了文档的一份副本,对应的端口为 3000。你可以这样运行这个镜像: docker run --rm -it -p 3000:3000 jjmerelo/perl6-doc @@ -32,90 +30,86 @@ * [葡萄牙文版 README](../pt/README.pt.md) * [西班牙文版 README](../es/README.es.md) -## 安装 p6doc - -本模块可通过 Raku 模块生态系统获得。使用命令 - - $ zef install p6doc - -安装可执行文件并添加到执行路径(PATH)中。 - -**注意**: 由于 Pod6 的解析规则改变,在 2018.06 之前的版本将无法通过测试从而无法安装,你可以选择升级到最新的版本或使用 `zef install --force p6doc` 来解决这个问题。无法通过测试并不影响 p6doc 的使用。 - -## 使用 p6doc - -把 `rakudo` 添加到 `PATH` 中后,可以使用命令 - - $ ./bin/p6doc Str - -查看 `Str` 类的文档;或者使用命令 - - $ ./bin/p6doc Str.split - -查看 `Str` 类中的 `split` 方法。如果你已经使用 `zef` 安装了 `p6doc`,那么可以省略 `./bin`。你也可以使用命令 - - $ p6doc -f slurp - -浏览标准函数的文档(在这种情况下实际上会返回多个结果,你可以分别查看)。命令的响应可能会花点时间,这取决于磁盘的速度和 Rakudo 的版本。 +## 安装 rakudoc -------- +请查看 https://github.com/Raku/rakudoc 来了解在命令行查看文档的工具。 ## 构建 HTML 文档 -本文档可以渲染为静态 HTML 页面并/或在本地网站服务。 -此过程涉及创建预编译文档的缓存,以便加快之后的生成速度。 +注意:如果你只是想要一份 HTML 站点的副本,而不想自己处理构建,你可以从这里克隆:[`https://github.com/rakudocs/rakudocs.github.io`](https://github.com/rakudocs/rakudocs.github.io)。 -> 建立文档有许多先决条件,你可能并不想亲自做。 -> 不过,如果你需要 HTML 文档的本地副本,请通过克隆 https://github.com/rakudocs/rakudocs.github.io 进行下载。 +本文档可以渲染为静态 HTML 页面和/或在本地网站服务。此过程涉及创建预编译文档的缓存,以便加快之后的生成速度。 -以下是生成文档需要安装的先决条件: +你需要安装以下这些才能生成文档: * perl 5.20 或更新。 * node 10 或更新。 -* graphviz 。 -* [Documentable](https://github.com/Raku/Documentable) 。 +* graphviz。 +* [Documentable](https://github.com/Raku/Documentable)。 -请按照以下说明(在 Ubuntu 中)进行安装 +在 Ubuntu 中,请按照以下说明进行安装: sudo apt install perl graphviz # 默认情况下,18.04 中未安装 perl curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash - sudo apt-get install -y nodejs cpanm --installdeps . - zef install Documentable + zef install --deps-only . ; # 在这个检出内运行 -> 你可以用任何方式安装 perl 和 node ,包括使用版本管理器,只要它们可以从命令行运行即可。 +> 你可以用任何方式安装 perl 和 node,包括使用版本管理器,只要它们可以从命令行运行即可。 -这应该安装了所有的必备条件,现在你可以 clone 本存储库并开始构建: +这应该安装了所有依赖,现在你可以克隆本存储库并开始构建: - git clone https://github.com/Raku/doc.git # clone 存储库 - cd doc # 移动到本存储库的副本 - make for-documentable # 生成 CSS 和 JS 并安装高亮模块 - documentable start -a -v --highlight # 构建缓存并生成页面 + git clone https://github.com/Raku/doc.git # 克隆存储库 + cd doc # 进入克隆的存储库 + # 生成 CSS 和 JS,安装高亮模块并构建缓存和页面 + make html 只有在第一次构建缓存时才需要这样做。当源代码发生变化(由你自己完成或从本存储库中拉取)后,运行 - documentable update + make update-html 将只会重新生成有变化的页面。 -文档将在 `html` 子目录中生成。你可以使用任何静态Web服务器指向该目录,也可以使用基于 Mojolicious 的开发服务器,运行 +文档将在 `html` 子目录中生成。你可以使用任何静态 Web 服务器指向该目录,也可以使用基于 Mojolicious 的开发服务器,运行 make run 这会在 3000 端口服务文档。 +## 生成 EPUB 和/或“单页 HTML”文档 + +本文档也可以生成 EPUB 格式以及“单页 HTML”格式。请注意,有些功能(如类型部分中继承的方法和类型图,以及代码示例的语法高亮)在这些格式中(暂时)不可用。 + +你需要安装以下这些: + +* Pod::To::BigPage 0.5.2 或更新。 +* Pandoc(仅 EPUB)。 + +在 Ubuntu 或 Debian 上,你可以按照以下说明安装: + + zef install "Pod::To::BigPage:ver<0.5.2+>" + sudo apt install pandoc # 如果你想生成 EPUB + +现在你已经安装了依赖关系,克隆这个仓库,并生成 EPUB 或“单页 HTML”文档。 + + git clone https://github.com/Raku/doc.git # 克隆存储库 + cd doc # 进入克隆的存储库 + make epub # 生成 EPUB 格式, + # 对于“单页 HTML”格式,使用 `make bigpage` + +生成的 EPUB 位于存储库根目录下,名为 `raku.epub`,生成的“单页 HTML”在 `html/raku.html`。 + ## nginx 配置 -生成的文档的最新版本仅包含静态 HTML 页面。所有页面都以 `.html` 结尾;不过大多数内部链接不使用该后缀。大多数Web服务器(例如,服务 GitHub 页面的服务器)都会自动为你添加它。裸服务器不会。你需要向配置中添加这些以使其工作: +生成的文档的最新版本仅包含静态 HTML 页面。所有页面都以 `.html` 结尾;不过大多数内部链接不使用该后缀。大多数 Web 服务器(例如,服务 GitHub 页面的服务器)都会自动为你添加它。裸服务器不会。你需要向配置中添加这些以使其工作: ``` location / { try_files $uri $uri/ $uri.html /404.html; } - ``` -这将为你重定向 URL 。可能需要在其他服务器应用中做出同样的配置。 +这将为你重定向 URL。可能需要在其他服务器应用中做出同样的配置。 --------- @@ -125,32 +119,30 @@ Raku 不是小语言,为它做文档并维护这些文档需要付出很大的 以下是一些帮助我们的方式: - * 添加缺少的 class ,role ,method 或 operator 的文档 - * 为现有文档添加使用示例 - * 校对与更正文档 - * 通过 GitHub 的 issue 系统报告缺少的文档 - * 在本仓库下执行 `git grep TODO`,使用实际文档替换 TODO + * 添加缺少的 class,role,method 或 operator 的文档。 + * 为现有文档添加使用示例。 + * 校对与更正文档。 + * 通过 GitHub 的 issue 系统报告缺少的文档。 + * 在本存储库下执行 `git grep TODO`,并用实际文档替换 TODO。 -[Issues 页面](https://github.com/Raku/doc/issues)列出了当前的 issue 和已知的缺失文档。[CONTRIBUTING 文档](../../../CONTRIBUTING.md)简要地说明了如何开始贡献文档。 +[Issues 页面](https://github.com/Raku/doc/issues)列出了当前的 issue 和已知缺失的文档。[CONTRIBUTING 文档](../../../CONTRIBUTING.md)简要描述了如何开始贡献文档。 -------- ## 注记: -**Q:** 为什么不把文档内嵌到 Rakudo 的核心开发文件中? - -**A:** 起码有以下几点: +**Q:** 为什么不把文档内嵌到 Rakudo 的核心开发文件中?
+**A:** 有以下几点: - 1. 这份文档与 Raku 的一份特定的语言标准相关联, + 1. 这份文档与 Raku 的特定版本的语言标准相关联, 而不是跟某个 Raku 的具体实现相绑定。 2. 处理内嵌的 Pod 的功能还不太稳定,使用单独的文档仓库 - 有利于避免运行时错误。 + 可以避免潜在的运行时错误。 3. 一个 Raku GitHub 账号下的单独的仓库能吸引更多 - 潜在的贡献和编辑。 - -**Q:** 编写文档时我应该包括父类和 role 的方法吗? + 潜在的贡献者。 -**A:** 不用。HTML 版本的文档自动包括了这些方法,`p6doc` 脚本也会自动处理这些。 +**Q:** 编写文档时我应该包括父类和 role 的方法吗?
+**A:** 不用。HTML 版本的文档自动包括了这些方法。 -------- @@ -174,16 +166,16 @@ Raku 不是小语言,为它做文档并维护这些文档需要付出很大的 现在暂时是手动更新。这大概需要改进。 -# 协议 +# 许可证 -本仓库代码使用 Perl 基金会发布的 Artistic License 2.0 协议,可以在 [LICENSE](../../../LICENSE) 文件中查看完整的内容。 +本仓库代码使用 Perl 基金会发布的 Artistic License 2.0 协议,你可以在 [LICENSE](../../../LICENSE) 文件中查看完整的内容。 本仓库可能包括使用其他协议的第三方代码,这些文件在它们的首部注明了版权和协议。目前包括: -* jQuery 与 jQuery UI 库: Copyright 2015 jQuery Foundation and other contributors; [MIT License](http://creativecommons.org/licenses/MIT) -* [jQuery Cookie 插件](https://github.com/js-cookie/js-cookie): - Copyright 2006, 2015 Klaus Hartl & Fagner Brack; +* jQuery 与 jQuery UI 库:Copyright 2015 jQuery Foundation and other contributors;[MIT License](http://creativecommons.org/licenses/MIT) +* [jQuery Cookie 插件](https://github.com/js-cookie/js-cookie): + Copyright 2006, 2015 Klaus Hartl & Fagner Brack; [MIT License](http://creativecommons.org/licenses/MIT) -* 来自 Stack Overflow 的示例 [MIT License](http://creativecommons.org/licenses/MIT); ([ref #1](http://stackoverflow.com/a/43669837/215487) for [1f7cc4e](https://github.com/Raku/doc/commit/1f7cc4efa0da38b5a9bf544c9b13cc335f87f7f6)) +* 来自 Stack Overflow 的示例; [MIT License](http://creativecommons.org/licenses/MIT) ([ref #1](http://stackoverflow.com/a/43669837/215487) for [1f7cc4e](https://github.com/Raku/doc/commit/1f7cc4efa0da38b5a9bf544c9b13cc335f87f7f6)) * 来自 https://github.com/christianbach/tablesorter 的表格排序插件; [MIT License](http://creativecommons.org/licenses/MIT) diff --git a/t/02-pod-valid.t b/t/02-pod-valid.t index 23360f67d..1be3eaf8a 100755 --- a/t/02-pod-valid.t +++ b/t/02-pod-valid.t @@ -22,7 +22,7 @@ my $verbose = %*ENV; @files.race.map: -> $file { react { - my $proc = Proc::Async.new([$*EXECUTABLE-NAME, '--doc', $file]); + my $proc = Proc::Async.new([$*EXECUTABLE-NAME, '-c', '--doc', $file]); whenever $proc.stdout.lines { ; #discard @@ -37,6 +37,7 @@ my $verbose = %*ENV; } whenever $proc.start { + $verbose and diag("processing $file"); $lock.protect: { if %data{$file}:!exists { %data{$file} = !.exitcode; # 0 = True, anything else False diff --git a/t/02-tests-valid.t b/t/03-tests-valid.t similarity index 95% rename from t/02-tests-valid.t rename to t/03-tests-valid.t index 1217f28f4..f41e09d72 100755 --- a/t/02-tests-valid.t +++ b/t/03-tests-valid.t @@ -12,7 +12,7 @@ Ensure any test file, including author tests, have clean syntax and POD =end overview -my @files = Test-Files.files.grep({$_.ends-with: '.t'}); +my @files = Test-Files.tests; if @files { plan +@files; diff --git a/t/03-pod6.t b/t/04-pod6.t similarity index 100% rename from t/03-pod6.t rename to t/04-pod6.t diff --git a/t/05-pod-convenience.t b/t/05-pod-convenience.t deleted file mode 100755 index 217302db5..000000000 --- a/t/05-pod-convenience.t +++ /dev/null @@ -1,184 +0,0 @@ -#!/usr/bin/env raku - -use lib $*PROGRAM.parent(2).child('lib'); -use Test; -BEGIN plan :skip-all unless '.git'.IO.e; - -use Pod::Convenience; -plan 10; - -subtest { - eval-dies-ok('use Pod::Convenience; first-code-block();', "pod argument required"); - eval-dies-ok('use Pod::Convenience; first-code-block("moo");', "array argument required"); - - is(first-code-block(["text"]), '', "non-code POD returns empty string"); - - my @code-blocks; - @code-blocks.push(Pod::Block::Code.new(contents => ['my $first-block'])); - @code-blocks.push(Pod::Block::Code.new(contents => ['my @second-block'])); - - is(first-code-block(@code-blocks), 'my $first-block', "first code block returned"); -}, "first-code-block"; - -subtest { - plan 7; - eval-dies-ok('use Pod::Convenience; pod-with-title();', "title argument required"); - my $pod = pod-with-title("title text"); - isa-ok($pod, Pod::Block::Named); - is($pod.name, "pod", "block name correct"); - # XXX: why do we have to dig so far to get to the title here? - is($pod.contents[0].contents[0].contents[0], "title text", "title matches input"); - nok($pod.contents[1].defined, "empty blocks argument gives undefined content"); - - $pod = pod-with-title("title text", "block text"); - is($pod.contents[1], "block text", "simple block text matches input"); - - my @block_text = [ "a block of text", "another block of text" ]; - $pod = pod-with-title("title text", @block_text); - is($pod.contents[1..*], "a block of text another block of text", - "array block text matches input"); -}, "pod-with-title"; - -subtest { - plan 6; - my $title = "Pod document title"; - my $pod = pod-title($title); - - isa-ok($pod, Pod::Block::Named); - eval-dies-ok('use Pod::Convenience; pod-title()', "title argument required"); - - $pod = pod-title(''); - ok($pod, "empty title is ok"); - - $pod = pod-title($title); - is($pod.name, "TITLE", "is a title element"); - - isa-ok($pod.contents, Array); - is($pod.contents[0].contents, $title, "title contents set correctly"); -}, "pod-title"; - -subtest { - plan 5; - my $pod = pod-block(''); - isa-ok($pod, Pod::Block::Para); - ok(pod-block(), "empty argument ok"); - - $pod = pod-block("hello"); - is($pod.contents, "hello", "simple contents match input"); - - $pod = pod-block("hello", "there"); - is($pod.contents, "hello there", "multi-argument input"); - - $pod = pod-block(qw{hello there world}); - is($pod.contents, 'hello there world', "array argument input"); -}, "pod-block"; - -subtest { - plan 6; - eval-dies-ok('use Pod::Convenience; pod-link()', "text argument required"); - eval-dies-ok('use Pod::Convenience; pod-link("text")', "link argument required"); - - my $pod = pod-link("text", "link"); - isa-ok($pod, Pod::FormattingCode); - - is($pod.type, "L", "is a link type"); - is($pod.contents[0], "text", "text matches input"); - is($pod.meta[0], "link", "link matches input"); -}, "pod-link"; - -subtest { - plan 4; - eval-dies-ok('use Pod::Convenience; pod-bold()', "text argument required"); - - my $pod = pod-bold("text"); - isa-ok($pod, Pod::FormattingCode); - - is($pod.type, "B", "is a bold type"); - is($pod.contents[0], "text", "text matches input"); -}, "pod-bold"; - -subtest { - plan 6; - ok(pod-item(), "empty argument ok"); - ok(pod-item(''), "empty string argument ok"); - - my $pod = pod-item(qw{hello there}); - isa-ok($pod, Pod::Item); - is($pod.level, 1, "default level correct"); - is($pod.contents, "hello there", "contents matches input"); - - $pod = pod-item(qw{hello there}, level => 5); - is($pod.level, 5, "level matches input"); -}, "pod-item"; - -subtest { - plan 6; - eval-dies-ok('use Pod::Convenience; pod-heading()', "name argument required"); - - my $pod = pod-heading("name"); - isa-ok($pod, Pod::Heading); - is($pod.contents[0].contents, "name", "heading name matches input"); - is($pod.level, 1, "level matches default value"); - - $pod = pod-heading("heading name", level => 3); - is($pod.contents[0].contents, "heading name", "heading name matches input"); - is($pod.level, 3, "level matches input"); -}, "pod-heading"; - -subtest { - plan 4; - eval-dies-ok('use Pod::Convenience; pod-table();', "contents argument required"); - eval-dies-ok('use Pod::Convenience; pod-table("");', "fails with empty string argument"); - - my $pod = pod-table(qw{table data}); - isa-ok($pod, Pod::Block::Table); - is($pod.contents, "table data", "table data matches input"); -}, "pod-table"; - -subtest { - eval-dies-ok('use Pod::Convenience; pod-lower-headings();', "content argument required"); - - # should probably die, currently throws an internal error - #eval-dies-ok('use Pod::Convenience; pod-lower-headings(qw{foo bar});', - #"plain content array not acceptable"); - - my $lowered-pod = pod-lower-headings([pod-heading("A head 1 heading")]); - isa-ok($lowered-pod, Array); - is($lowered-pod[0].level, 1, "single POD heading lowered from 1 to 1"); - is($lowered-pod[0].contents[0].contents, "A head 1 heading", "lowered heading contents match input"); - - # if first heading is equal to default level to be lowered to, then don't lower - { - my @pod; - @pod.push(pod-heading("heading head1")); - @pod.push(pod-block(qw{"pod block})); - @pod.push(pod-heading("heading head2", level => 2)); - $lowered-pod = pod-lower-headings(@pod); - is($lowered-pod[0].level, 1, "heading head1 stays at level 1"); - is($lowered-pod[2].level, 2, "heading head2 stays at level 2"); - } - - # if first heading is equal to level to be lowered to, then don't lower - { - my @pod; - @pod.push(pod-heading("heading head2", level => 2)); - @pod.push(pod-block(qw{"pod block})); - @pod.push(pod-heading("heading head3", level => 3)); - $lowered-pod = pod-lower-headings(@pod, to => 2); - is($lowered-pod[0].level, 2, "heading head2 stays at level 2"); - is($lowered-pod[2].level, 3, "heading head3 stays at level 3"); - } - - # if first heading is "higher" than level to be lowered to, then lower to level - { - my @pod; - @pod.push(pod-heading("heading head3", level => 3)); - @pod.push(pod-block(qw{"pod block})); - @pod.push(pod-heading("heading head4", level => 4)); - $lowered-pod = pod-lower-headings(@pod, to => 2); - is($lowered-pod[0].level, 2, "heading head3 lowered to level 2"); - is($lowered-pod[2].level, 3, "heading head4 lowered to level 3"); - } -}, "pod-lower-headings"; - -# vim: expandtab shiftwidth=4 ft=perl6 diff --git a/t/07-tabs.t b/t/05-tabs.t similarity index 100% rename from t/07-tabs.t rename to t/05-tabs.t diff --git a/template/main.mustache b/template/main.mustache index 6b9d094fb..c0e6fb6aa 100644 --- a/template/main.mustache +++ b/template/main.mustache @@ -18,7 +18,7 @@ {{! Site icon }}
-  Raku Documentation +  Raku Documentation {{! Seach barch }} @@ -91,17 +91,17 @@ known to be incomplete.

- + Please report any issues Your contribution is appreciated.

This documentation is provided under the terms of the - + Artistic License 2.0 . The Camelia image is - + copyright © 2009 by Larry Wall. diff --git a/type-graph.txt b/type-graph.txt index 81c1ce9dd..6720d3941 100644 --- a/type-graph.txt +++ b/type-graph.txt @@ -173,6 +173,7 @@ class IO::Path::Unix is IO::Path class IO::Path::Win32 is IO::Path class IO::Path::Cygwin is IO::Path class IO::Path::QNX is IO::Path +class IO::Path::Parts does Positional does Associative does Iterable role IO::Socket class IO::Socket::INET does IO::Socket class IO::Socket::Async @@ -230,6 +231,7 @@ enum Order is Int class Semaphore class Lock class Lock::Async +class Lock::ConditionVariable class Proc::Async class Thread diff --git a/util/Dockerfile b/util/Dockerfile deleted file mode 100644 index 60d9d9a07..000000000 --- a/util/Dockerfile +++ /dev/null @@ -1,32 +0,0 @@ -FROM rakudo-star:latest - -RUN buildDeps=' \ - build-essential \ - cpanminus \ - ' \ - runtimeDeps=' \ - graphviz \ - make \ - ruby-sass \ - ' \ - testDeps=' \ - aspell \ - ' \ - \ - && set -x \ - && apt-get update \ - && apt-get --yes --no-install-recommends install $buildDeps $runtimeDeps $testDeps \ - && rm -rf /var/lib/apt/lists/* \ - \ - && cpanm -vn Mojolicious \ - && zef install zef && zef update && zef install Test::META Perl6::TypeGraph \ - \ - && n=/usr/local/bin/n \ - && curl -fsSL https://raw.githubusercontent.com/tj/n/master/bin/n > "$n" \ - && chmod +x "$n" \ - && n stable - -WORKDIR /perl6/doc -EXPOSE 3000 - -CMD make test && make html && ./app-start diff --git a/util/clean-spell b/util/clean-spell index 7656921af..f57df0ab0 100755 --- a/util/clean-spell +++ b/util/clean-spell @@ -24,6 +24,9 @@ use Pod::Cache; my $regex = %*ENV // "."; +# How many files to check at a time? +my $at-a-time = 4; + # Check the same files as xt/aspell.t does by default... my @files = Test-Files.documents.grep({not $_ ~~ / 'README.' .. '.md' /}); @@ -35,10 +38,10 @@ my @files = Test-Files.documents.grep({not $_ ~~ / 'README.' .. '.md' /}); for -> $dict { for $dict.IO.lines -> $word { next unless $word ~~ /<$regex>/; - next if $word eq "personal_ws-1.1 en 0 utf-8"; + next if $word.starts-with('personal_ws-1.1 en'); note "Testing $dict / $word "; - my $proc = run( 'grep', '-li', $word, |@files, :out); + my $proc = run( 'grep', '-wli', $word, |@files, :out); my $output = $proc.out.slurp; # remove word, keep pointer to backup lexicon @@ -49,12 +52,22 @@ for -> $dict { } else { my @min-files = $output.lines; note "\tfound in {+@min-files} files, testing."; - my $proc = run( 'xt/aspell.t', |@min-files, :out, :err); - if $proc.exitcode == 0 { + my $all-ok = True; + # use rotor, but get the partial chunk first + # so we can fail slightly faster + for @min-files.reverse.rotor($at-a-time, :partial).reverse -> @test-files { + note "\t\t" ~ @test-files.join("\n\t\t"); + my $proc = run( 'xt/aspell.t', |@test-files.reverse, :out, :err); + if $proc.exitcode != 0 { + $all-ok = False; + note "\taspell test failed, keeping word"; + run('mv', $backup, $dict); + last; # no need to test other files + } + } + if $all-ok { note "\taspell test passed, removing word"; - } else { - note "\taspell test failed, keeping word"; - run('mv', $backup, $dict); + # We removed the word to do the test, so just leave as is. } } } diff --git a/util/github-action-test.sh b/util/github-action-test.sh new file mode 100755 index 000000000..71e8140ab --- /dev/null +++ b/util/github-action-test.sh @@ -0,0 +1,28 @@ +#!/bin/bash - + +# This script is run by the step 'Run tests' in the GitHub workflow "test" +# See .github/workflows/test.yml + +set -ex +set -o pipefail + +: ${TEST_IMAGE:=docker.io/jjmerelo/perl6-doccer:latest} +: ${P6_DOC_TEST_VERBOSE:=1} + +# this default value allows one to run a command like +# ./util/github-action-test.sh +: ${GITHUB_WORKSPACE:=${PWD}} + +# if no argument is given run tests from t/ +if [[ $# -eq 0 ]]; then + set -- t +fi + +docker run -t \ + -v "${GITHUB_WORKSPACE}":/test:Z \ + --entrypoint env \ + "${TEST_IMAGE}" \ + P6_DOC_TEST_VERBOSE=${P6_DOC_TEST_VERBOSE} \ + prove6 "$@" + +# vim: ts=2 sts=2 sw=2 expandtab ft=sh: diff --git a/util/ignored-methods.txt b/util/ignored-methods.txt index 761d7b4a4..47c300275 100644 --- a/util/ignored-methods.txt +++ b/util/ignored-methods.txt @@ -1,4 +1,4 @@ -# This file is loaded by `list-missing-methods.p6` (unless a different file is specified +# This file is loaded by `list-missing-methods.raku` (unless a different file is specified # as a CLI option). It list methods that should *not* be listed as 'undocumented'. It is # read as a standard Raku hash, so you can use any valid Raku syntax. Each key should be # either 1) a Type name, or the special key `ALL_TYPES`; each value should be a list of diff --git a/util/issue-with-all-pod6.p6 b/util/issue-with-all-pod6.raku similarity index 98% rename from util/issue-with-all-pod6.p6 rename to util/issue-with-all-pod6.raku index a638be98b..a19637baf 100755 --- a/util/issue-with-all-pod6.p6 +++ b/util/issue-with-all-pod6.raku @@ -1,7 +1,5 @@ #!/usr/bin/env raku -use v6; - my @docs = qx/git ls-files | grep "\.pod6"/.lines; for @docs -> $d { diff --git a/util/list-missing-methods.p6 b/util/list-missing-methods.raku similarity index 99% rename from util/list-missing-methods.p6 rename to util/list-missing-methods.raku index 613e90af4..01b545170 100755 --- a/util/list-missing-methods.p6 +++ b/util/list-missing-methods.raku @@ -1,5 +1,5 @@ #! /usr/bin/env raku -use v6; + use Telemetry; # used so we can check these docs # stubs role Result{...}; role Ok{...}; role Err{...}; role ErrKind{...}; role UncheckableType {...} diff --git a/util/missing-methods.p6 b/util/missing-methods.p6 deleted file mode 100755 index 0cfadf073..000000000 --- a/util/missing-methods.p6 +++ /dev/null @@ -1,51 +0,0 @@ -use v6; - -use lib 'lib'; -use Perl6::TypeGraph; - -=begin pod - -=head1 NAME - - missing-methods - -=head1 SYNOPSIS - - $ raku util/missing-methods.p6 [--type_name=] - -=head1 DESCRIPTION - -A first cut at a program to find methods in a Perl 6 implementation which -have not yet been documented. - -At present this involves a call to C in order to find if the methods -found have documentation. This could be improved by simply calling the -relevant routines within C instead of accessing the functionality -from outside. - -=end pod - -sub MAIN(Str :$type-name) { - my $type-graph = Perl6::TypeGraph.new-from-file('type-graph.txt'); - my @types-to-search = $type-name ?? $type-graph.types{$type-name} - !! $type-graph.sorted; - - for @types-to-search -> $type { - for methods-in-type($type) -> $method { - show-undoc-method($type.name ~ '.' ~ $method.name); - } - } -} - -sub methods-in-type($type) { - my $type-name = ::($type.name); - return $type-name.^methods(:local); -} - -sub show-undoc-method(Str $qualified-method-name) { - my $doc-lookup-command = "PAGER=cat ./bin/p6doc -f \'$qualified-method-name\'"; - my $doc-output = qqx{$doc-lookup-command}; - say "$qualified-method-name" if $doc-output ~~ m:s/No documentation found/; -} - -# vim: expandtab shiftwidth=4 ft=perl6 diff --git a/util/missing-types.p6 b/util/missing-types.raku similarity index 71% rename from util/missing-types.p6 rename to util/missing-types.raku index 2adf9ee56..744e1181d 100755 --- a/util/missing-types.p6 +++ b/util/missing-types.raku @@ -1,9 +1,13 @@ #!/usr/bin/env raku -use v6; + +# This script parses the type-graph.txt file and checks +# the existence of the corresponding pod6 file for most entries +# skips: Metamodel and PROCESS types + use lib 'lib'; -use Perl6::TypeGraph; +use Doc::TypeGraph; -my $t = Perl6::TypeGraph.new-from-file('type-graph.txt'); +my $t = Doc::TypeGraph.new-from-file('type-graph.txt'); for $t.sorted -> $type { next if $type.name.index('Metamodel').defined || $type.name eq 'PROCESS'; diff --git a/util/new-type.p6 b/util/new-type.raku similarity index 69% rename from util/new-type.p6 rename to util/new-type.raku index be9d3bf17..fb5da5853 100755 --- a/util/new-type.p6 +++ b/util/new-type.raku @@ -1,6 +1,8 @@ #!/usr/bin/env raku -use v6; +# If the documentation for a type does not exist, create the skeleton of the doc +# $ raku util/new-type.raku --kind=role Some::Role +# this creates the file doc/Type/Some/Role.pod6 sub MAIN($typename, :$kind='class') { my @path-chunks = $typename.split('::'); @@ -14,8 +16,13 @@ sub MAIN($typename, :$kind='class') { } $path ~= "/$filename"; + if $path.IO ~~ :e { + say "The file $path already exists."; + exit 1; + } + my $fh = open $path, :x; - spurt $path.IO, Q:q:to/HEADER/; + spurt $fh, Q:s:to/HEADER/; =begin pod =TITLE $kind $typename @@ -27,7 +34,7 @@ sub MAIN($typename, :$kind='class') { Synopsis goes here HEADER - spurt $path.IO, Q:c:to/BODY/; + spurt $fh, Q:c:to/BODY/; =head1 Methods @@ -41,7 +48,7 @@ sub MAIN($typename, :$kind='class') { # vim: expandtab shiftwidth=4 ft=perl6 BODY - + $fh.close; say "'$path' written"; say "(remember to 'git add $path')"; } diff --git a/util/perl-nbsp.p6 b/util/perl-nbsp.raku similarity index 99% rename from util/perl-nbsp.p6 rename to util/perl-nbsp.raku index 0090e1b3c..58087b9e7 100755 --- a/util/perl-nbsp.p6 +++ b/util/perl-nbsp.raku @@ -1,5 +1,5 @@ #!/usr/bin/env raku -use v6; + use lib 'lib'; use Test-Files; diff --git a/util/sort-words.raku b/util/sort-words.raku new file mode 100755 index 000000000..06b9bddd1 --- /dev/null +++ b/util/sort-words.raku @@ -0,0 +1,22 @@ +#!/usr/bin/env raku + +=begin overview + +Sort words files as expected by xt/words.t + +=end overview + +my $word-io = $*PROGRAM.parent.parent.child('xt/pws/words.pws').IO; +my $code-io = $*PROGRAM.parent.parent.child('xt/pws/code.pws').IO; + +my @word = $word-io.lines; +my @code = $code-io.lines; + +my $header = @word.shift; + +my $word-out = $word-io.open(:w); +$word-out.say: $header; +$word-out.say: @word.sort.join("\n"); + +my $code-out = $code-io.open(:w); +$code-out.say: @code.sort.join("\n"); diff --git a/util/to-raku.p6 b/util/to-raku.raku similarity index 98% rename from util/to-raku.p6 rename to util/to-raku.raku index 683f657a5..cf4667902 100755 --- a/util/to-raku.p6 +++ b/util/to-raku.raku @@ -1,12 +1,10 @@ #!/usr/bin/env raku -use v6; + use lib 'lib'; use Test-Files; - my $degree = %*ENV // 2; - multi sub replace-perl6(Str $file) { my $content = my $original-content = slurp $file; $content ~~ s:g/ 'Perl' [ \s+ | \x[00A0] ] '6' /Raku/; diff --git a/util/travis-build.sh b/util/travis-build.sh deleted file mode 100755 index decb0a245..000000000 --- a/util/travis-build.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash - -set -e - - -case "${BUILDENV}" in - docker) - docker pull jjmerelo/perl6-doccer - ;; - whateverable) - sudo -E apt-add-repository -y "ppa:ubuntu-toolchain-r/test" - sudo -E apt-get -yq update &>> ~/apt-get-update.log - sudo -E apt-get -yq --no-install-suggests --no-install-recommends --force-yes install graphviz g++-4.8 ruby-sass libc6 - wget https://whateverable.6lang.org/HEAD.tar.gz - tar -xv --absolute-names -f HEAD.tar.gz - HEAD_BUILD=$(echo /tmp/whateverable/rakudo-moar/*) - export PATH="$PATH:$HEAD_BUILD/bin" - ZEF_BUILD="$HEAD_BUILD/share/perl6/site/bin" - git clone https://github.com/ugexe/zef.git && cd zef && perl6 -Ilib bin/zef install . && cd .. - export PATH="$PATH:$ZEF_BUILD" - zef --/tap-harness install IO::Socket::SSL # Needs to be installed in advance - zef --/tap-harness --depsonly install . - mkdir build - ;; -esac diff --git a/util/travis-test.sh b/util/travis-test.sh deleted file mode 100755 index 473403196..000000000 --- a/util/travis-test.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -# Script for the "test" phase of Travis CI. - -set -x -set -e - -case "${BUILDENV}" in - docker) - docker run -t -v $TRAVIS_BUILD_DIR:/test jjmerelo/perl6-doccer - ;; - whateverable) - HEAD_BUILD=$(echo /tmp/whateverable/rakudo-moar/*) - export PATH="$PATH:$HEAD_BUILD/bin" - ZEF_BUILD="$HEAD_BUILD/share/perl6/site/bin" - export PATH="$PATH:$ZEF_BUILD" - P6_DOC_TEST_VERBOSE=1 make test - make clean-build - make gen-pod6-source - perl6 htmlify.p6 --no-highlight --disambiguation=False - ;; -esac diff --git a/util/unskip.p6 b/util/unskip.raku similarity index 99% rename from util/unskip.p6 rename to util/unskip.raku index 29ec604c7..212f8bbfc 100755 --- a/util/unskip.p6 +++ b/util/unskip.raku @@ -1,7 +1,5 @@ #!/usr/bin/env raku -use v6; - use File::Temp; use lib 'lib'; diff --git a/util/update-and-sync b/util/update-and-sync deleted file mode 100755 index fc00e3edd..000000000 --- a/util/update-and-sync +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/bash -# DO NOT USE FOR LOCAL DEVELOPMENT -# this script is used on hack.p6c.org as the 'doc.perl6.org' user to update -# the website. It will remove any local changes you have made in your git checkout - -source ~/perl5/perlbrew/etc/bashrc -source /home/rakudobrew/.rakudobrew-bash -set -e -set -x -cd ~/doc -git fetch -before=$(git rev-parse HEAD) -git checkout origin/master -after=$(git rev-parse HEAD) -if [ ! -f "$HOME/force-update" ] ; then - if [ "$before" = "$after" ] ; then - echo "nothing to do" - exit - fi -fi - -rm "$HOME/force-update" || true; -LOGDIR=$HOME/logs/build-log -mkdir -p "$LOGDIR" -DATE=$(date --iso-8601=minutes) -LOGFILE="$LOGDIR/build-$DATE.log"; -echo "Writing logs to $LOGFILE"; -exec >$LOGFILE 2>&1 - -echo "Building docs for $after with " `perl6 --version` -echo 'Cleaning out old HTML files' -# Clean everything that is not under source control -git clean -xfd -# find html/ -name '*.html' -delete # Old command - -# if the htmlify fails, sync the build log. -# since sync-build-log returns false, not the whole thing is synced -time make html || ./util/sync-build-log -./util/sync -./util/sync-build-log || true - -# vim: expandtab shiftwidth=4 diff --git a/util/update-and-test b/util/update-and-test index b1891ebf8..d5a51a74b 100755 --- a/util/update-and-test +++ b/util/update-and-test @@ -19,11 +19,12 @@ my $old-rev = get-rev; run(); my $new-rev = get-rev; -run(); if $old-rev eq $new-rev { say "No changes to test."; } else { + run(); + my $revs = $old-rev ~ ".." ~ $new-rev; my $files = run('git', 'diff', '--name-only', $revs, :out).out.slurp(:close).chomp.split("\n").sort.join(" "); my $outfile = "./retest"; diff --git a/util/xt-recent.sh b/util/xt-recent.sh index d56a63d92..fd15719bb 100755 --- a/util/xt-recent.sh +++ b/util/xt-recent.sh @@ -1,7 +1,15 @@ #!/bin/sh -# Test only the most recent commits for xtest issues -# (much faster than running the whole suite) +# Anyone working out of the git repo should regularly run 'make xtest' +# on their changes +# +# While util/update-and-test allows a developer to test only those files +# that have changed since the last run, this script picks the last 40 +# POD/Markdown/test file changed, uniques them, and runs 'make test' on them. +# +# Running 'make test' on # all the files is *very* slow, this gives developers +#a shortcut to +# verify recent work. -TEST_FILES="$(git log --name-status | awk '/^M.*\.(pod6|md)$/ {print $2}' | head -40 | sort -u)" make xtest "$@" +TEST_FILES="$(git log --name-status | awk '/^M.*\.(pod6|md|t)$/ {print $2}' | head -40 | sort -u)" make xtest "$@" diff --git a/writing-docs/EXAMPLES.md b/writing-docs/EXAMPLES.md index 265063a84..68056ea7b 100644 --- a/writing-docs/EXAMPLES.md +++ b/writing-docs/EXAMPLES.md @@ -6,9 +6,14 @@ documentation with some example. ## Writing Examples Please use code blocks to highlight example code; any indented blocks -are considered to be code, but you can use the `=for code` directive, or a +are considered to be code, but you can specify the `=for code` directive, or a combination of `=begin code` and `=end code` to better control which -blocks are considered. +blocks are considered. The POD6 directives also allow you to set +attributes for a block of code. + +When using a `=for code` directive or a `=begin code`/`=end code` +combination, the code block does not need to be indented and should not +be for a better aligned result. ## Testing Examples @@ -29,10 +34,11 @@ finesse it. ### Other languages -We're just testing Raku here: to skip another language, use `:lang` +We're just testing Raku here: to mark as another language, use `:lang`, +and this will avoid testing: =begin code :lang - puts "this is not Perl" + puts "this is not Perl" =end code For plain text use `:lang` @@ -43,7 +49,7 @@ One of the checks is to dissuade using `.WHAT` in tests; However, in rare cases that is the explicit point of the test, so you can allow it with ok-test: =begin code :ok-test - say 42.WHAT; + say 42.WHAT; =end ### Allow dd @@ -53,7 +59,7 @@ shouldn't use it unless they are explicitly trying to show how it works. You can allow it with ok-test: =begin code :ok-test

- dd 42; + dd 42; =end ### Allow .perl @@ -63,7 +69,7 @@ method should be used instead. If needed you can allow the use of the `perl` method with ok-test: =begin code :ok-test - say {:42a}.perl; + say {:42a}.perl; =end ### Methods @@ -74,10 +80,10 @@ Multi-line method signatures are much harder to detect, so if you have a method body that spans lines, use the `:method` tag: =begin code :method - method arg ( - Bool $one, - Bool $two - ) + method arg ( + Bool $one, + Bool $two + ) =end code This helps keep the method detection logic in the test code simple. @@ -92,11 +98,11 @@ defined in that snippet; you don't want to have to have a full working example in the code. =begin code :preamble - $x = pi; + $x = pi; =end code =begin code :preamble - $x = frob(); + $x = frob(); =end code Note that when running the code, it's compiled inside an anonymous class. @@ -121,5 +127,27 @@ resort, and many examples might be amenable to using one of the previous annotations. =begin code :skip-test - if 1 "missing a block"; + if 1 "missing a block"; =end code + +### Code Indentation / Formatting + +Documentation can be formatted as code using multiple source +styles. + +## Indented text + +4-space indented text is formatted as a code block. The indent is *not* +part of the displayed code. It's not possible to add any POD6 +directives on this style. + +## =for code + +The following block of text is treated as code. The indentation level +is from the beginning of the line, regardless of how the `=for` +is indented. + +## =begin code / =end code + +The enclosed text is treated as code. The indentation level is +relative to the indentation of the POD6 directives. diff --git a/writing-docs/SQUASHATHONS.md b/writing-docs/SQUASHATHONS.md index 81f11261a..1a93753b3 100644 --- a/writing-docs/SQUASHATHONS.md +++ b/writing-docs/SQUASHATHONS.md @@ -6,7 +6,7 @@ to this repository. It will help the organization of the hackathon if you follow these rules when participating in it. 1. Always work against an [issue](https://github.com/Raku/doc/issues). If you find some typo or any other kind of error for which an issue does not exist, please create one. -2. Always work on assigned issues. Assignments get echoed in the [`raku` IRC channel](https://webchat.freenode.net/?channels=#raku), so everyone knows someone is working on that. +2. Always work on assigned issues. Assignments get echoed in the [`raku` IRC channel](https://web.libera.chat/?channel=#raku), so everyone knows someone is working on that. 3. You can only assign issues to contributors, so if someone who is not a contributor asks to be assigned something, please assign it to yourself (provided you are a contributor) and do an `@` mention with the nick of the actual @@ -18,4 +18,4 @@ you follow these rules when participating in it. other ones till the end of the day (so that others can start with something easy too). If you are already experienced, don't be afraid to tackle other, more difficult, issues, starting with - [the oldest](https://github.com/Raku/doc/issues?page=8&q=is%3Aissue+is%3Aopen). + [the oldest](https://github.com/Raku/doc/issues?q=is%3Aissue+is%3Aopen+sort%3Acreated-asc). diff --git a/writing-docs/STYLEGUIDE.md b/writing-docs/STYLEGUIDE.md index 03e6d0d2c..6c0de9762 100644 --- a/writing-docs/STYLEGUIDE.md +++ b/writing-docs/STYLEGUIDE.md @@ -1,6 +1,6 @@ # Style guide -Please follow these style rules when contributing to the documentation +Please follow these style rules when contributing to the documentation. ## Text @@ -83,7 +83,7 @@ in a given situation, please try to follow these guidelines. When generating output in examples intended to be read by a user, use 'say'. Additionally, add a comment showing the intended output, e.g.: - say 3.^name; #OUTPUT: «Int␤» + say 3.^name; # OUTPUT: «Int␤» For examples where a particular format is required, or exact data is expected (e.g., for something sent over a network connection), prefer 'put'. @@ -119,7 +119,7 @@ term in the documentation and stick to the form that is used the most ### Use present tense when talking about Perl features -Per5 is still an active language, therefore instead of "In Perl +Perl 5 is still an active language, therefore instead of "In Perl this was used for ..., but in Raku ..." use a form like "In Perl this is used for ..., but in Raku ..." ('was' has been made a present 'is'). @@ -188,7 +188,7 @@ roast test suite) * If something is visible to users of Raku and is in roast: document it. * If something is visible to users of Raku and is not in roast: - check with the dev team (#raku-dev on freenode) - This might need + check with the dev team (#raku-dev on libera.chat) - This might need have a test added (and therefore docs), or it might need to be hidden so users cannot see it. In general, documentation of implementation-specific features should be avoided; however, if @@ -197,7 +197,7 @@ roast test suite) the first and latest version the documented feature is available. Future considerations along this line include: documenting things that -are Rakudo specific (like "dd"), and documenting which versions of the +are Rakudo specific (like ```dd```), and documenting which versions of the spec items are available in. ## Use of HTML @@ -205,8 +205,8 @@ spec items are available in. Generally, Pod6 should be more than enough for any documentation. However, if you need to embed HTML into the documentation after thinking about it twice, bear in mind that we support -the current and previous major releases of Chrome, Firefox, Internet -Explorer (Edge), and Safari. Please test layout changes. Lacking +the current and previous major releases of Chrome, Firefox, Edge, +and Safari. Please test layout changes. Lacking actual browsers to test in, you can use [browsershots.org](http://browsershots.org) or [browserstack.com](http://browserstack.com). Ensure the layout looks diff --git a/xt/check-signatures.t b/xt/check-signatures.t index 1048d5e78..5e6fa3d40 100755 --- a/xt/check-signatures.t +++ b/xt/check-signatures.t @@ -30,6 +30,10 @@ variable, this script will attempt to test a specific version by using git check to switch that checkout to a specific version during the test, and run "git checkout -" at the end to reset the state. +NOTE: This test uses introspection from the running copy of rakudo to find +information in the source code. If you are running a different version of raku +then the RAKUDO_SRC directory, it may be unable to find certain method definitions. + To ensure that implementation details don't cause failing tests, we check only for certain discrepancies that are guaranteed to indicate a substantive/non-implementation detail mismatch between Rakudo and the docs. @@ -50,12 +54,19 @@ not (the inverse situation -- where we specify a return constraint that Rakudo does not -- would not necessarily represent an error in the docs so long as the function always does return that type) +You may also wish to review certain skipped results: they may point +to mistakes in the documentation - one example is methods that are +defined on a role instead of a class - it will show up as skips but +points to a need to move the documentation for that method. + =end SYNOPSIS my $error = "To run check-signatures, please specify the path to the Rakudo git checkout with the RAKUDO_SRC environment variable"; my $rakudo-src-dir = %*ENV // plan(:skip-all( $error )); when !$rakudo-src-dir.IO.d { plan(:skip-all( $error )) } when ?(run , :out, :err).exitcode { plan(:skip-all( "check-signatures requires git"))} +my $doc-dir = $*CWD; + given $*RAKU.compiler.verbose-config.split('-') { chdir $rakudo-src-dir; when .elems == 1 { run (|, |("tags/{.[0]}")), :out, :err} @@ -69,8 +80,11 @@ for @doc-files -> $file { when $file !~~ /'doc/Type/'[(\w+)'/'?]+'.pod6'/ { skip "'{$file.basename}' doesn't document a type" } my $type-name = S/'doc/Type/'[(\w+)'/'?]+'.pod6'/$0.join('::')/ with $file; my $type = ::($type-name); - CATCH { default { skip "$type-name lacks required introspection" } } - TypeDocumentation.parse($file.IO.slurp); + CATCH { default { + my $name = $type-name // $file; + skip "$name lacks required introspection"; + }} + TypeDocumentation.parse("$doc-dir/$file".IO.slurp); subtest "check $type-name methods", { plan +$; diff --git a/xt/duplicates.t b/xt/duplicates.t index ffcf17d71..31acfbdd2 100755 --- a/xt/duplicates.t +++ b/xt/duplicates.t @@ -16,7 +16,7 @@ Allow a few well known duplicates, like 'long long' =end overview -my $safe-dupes = Set.new(); # Allow these dupes +my $safe-dupes = Set.new(); # Allow these dupes my @files = Test-Files.documents \ .grep({$_ ne "doc/HomePage.pod6"}) \ # mostly HTML diff --git a/xt/examples-compilation.t b/xt/examples-compilation.t index 2cd84ad24..5eb9213e8 100755 --- a/xt/examples-compilation.t +++ b/xt/examples-compilation.t @@ -29,6 +29,8 @@ do hide $*ERR, but some of these are emitted from parts of the compiler that only know about the low level handle, not the Perl 6 level one. +Error if leading whitespace is present in the code block. + =end SYNOPSIS plan +my @files = Test-Files.pods; @@ -41,6 +43,13 @@ for @files -> $file { } sub test-example ($eg) { + my @lines-all = $eg.lines; + my @lines-ws = @lines-all.grep(/^ \s /); + + if @lines-ws eq @lines-all { + flunk "$eg chunk starting with «" ~ starts-with($eg) ~ '» has extra leading whitespace'; + next; + } # #1355 - don't like .WHAT in examples if ! $eg.contains('WHAT') && $eg.contains('.WHAT') { flunk "$eg chunk starting with «" ~ starts-with($eg) ~ '» uses .WHAT: try .^name instead'; @@ -79,7 +88,7 @@ sub test-example ($eg) { # We wait until none of them is encountered before adding '{}'. # Cases that are not covered by the heuristic and which contain # nothing but a method declaration can use :method instead. - $in-signature ?|= $line.trim.starts-with(any()) + $in-signature ?|= $line.trim ~~ / ^ ('multi'|'method'|'submethod'|'proto'|'only'|'sub') >> / && not $eg; if $in-signature && !$line.trim.ends-with(any(« } , ( »)) { $code ~= " \{}"; diff --git a/xt/final-newline.t b/xt/final-newline.t index 2547387ba..7169cf145 100755 --- a/xt/final-newline.t +++ b/xt/final-newline.t @@ -19,7 +19,11 @@ my @files = Test-Files.files\ .grep({! $_.ends-with: '.svg'})\ .grep({! $_.ends-with: '.ico'}); -plan +@files; +if @files { + plan +@files; +} else { + plan :skip-all; +} for @files -> $file { ok $file.IO.slurp.substr(*-1) eq "\n", "$file must end in a newline"; diff --git a/xt/lib-test-files.raku b/xt/lib-test-files.raku new file mode 100755 index 000000000..35ec3e310 --- /dev/null +++ b/xt/lib-test-files.raku @@ -0,0 +1,22 @@ +#!/usr/bin/env raku + +use Test; +use lib $*PROGRAM.parent(2).child('lib'); +use Test-Files; + +=begin overview + +Exercise Test-Files command line. + +L invokes this script and its results are reported out through that C<.t> file + +=end overview + +say Test-Files.files().join(','); +say '---'; +say Test-Files.pods().join(','); +say '---'; +say Test-Files.documents().join(','); +say '---'; +say Test-Files.tests().join(','); +say '---'; diff --git a/xt/lib-test-files.t b/xt/lib-test-files.t new file mode 100755 index 000000000..a2fca0e3a --- /dev/null +++ b/xt/lib-test-files.t @@ -0,0 +1,70 @@ +#!/usr/bin/env raku + +use Test; +use lib $*PROGRAM.parent(2).child('lib'); + +=begin overview + +Test the Test-Files module + +=end overview + +plan 25; +use-ok 'Test-Files'; + +use Test-Files; + +# We could ourselves be running with TEST_FILES set - ignore it for now... +%*ENV=''; + +my @files = Test-Files.files(); +ok @files.elems > 1, '.files returns something array-like with at least one item'; +ok all(@files.map(*.IO.f)), 'all files returned exist'; + +my @pods = Test-Files.pods(); +ok @pods.elems > 1, '.pods returns something array-like with at least one item'; +ok all(@pods>>.ends-with('.pod6')), 'all files returned are pod files'; +ok all(@pods.map(*.IO.f)), 'all files returned exist'; + +my @docs = Test-Files.documents(); +ok @docs.elems > 1, '.documents returns something array-like with at least one item'; +ok all(@docs>>.ends-with('.pod6'|'.md')), 'all files returned are pod/md files'; +ok all(@docs.map(*.IO.f)), 'all files returned exist'; + +my @tests = Test-Files.tests(); +ok @tests.elems > 1, '.tests returns something array-like with at least one item'; +ok all(@tests>>.ends-with('.t')), 'all files returned are test files'; +ok all(@tests.map(*.IO.f)), 'all files returned exist'; + +my $expected = q:to/END/; +foo,foo.md,foo.pod6,foo.t +--- +foo.pod6 +--- +foo.md,foo.pod6 +--- +foo.t +--- +END + +is run($*EXECUTABLE, 'xt/lib-test-files.raku', 'foo.t', 'foo.pod6', 'foo.md', 'foo', :out).out.slurp(:close), $expected, 'correct (sorted) output from command line usage'; + +# Now test the specific TEST_FILES we want... +%*ENV='this-file-does-not-exist xt/lib-test-files.t'; +is Test-Files.files, 'xt/lib-test-files.t', 'TEST_FILES 1 skip missing files, keep existing'; +is Test-Files.pods, '', 'TEST_FILES 1 skip missing files, bad type'; +is Test-Files.documents, '', 'TEST_FILES 1 skip missing files, bad type'; +is Test-Files.tests, 'xt/lib-test-files.t', 'TEST_FILES 1 skip missing files, keep existing type match'; + +%*ENV='this-file-does-not-exist CONTRIBUTING.md'; +is Test-Files.files, 'CONTRIBUTING.md', 'TEST_FILES 2 skip missing files, keep existing'; +is Test-Files.pods, '', 'TEST_FILES 2 skip missing files, bad type'; +is Test-Files.documents, 'CONTRIBUTING.md', 'TEST_FILES 2 skip missing files, keep existing type match'; +is Test-Files.tests, '', 'TEST_FILES 2 skip missing files, bad type'; + +%*ENV='this-file-does-not-exist doc/Type/Mu.pod6'; +is Test-Files.files, 'doc/Type/Mu.pod6', 'TEST_FILES 3 skip missing files, keep existing'; +is Test-Files.pods, 'doc/Type/Mu.pod6', 'TEST_FILES 3 skip missing files, keep existing type match'; +is Test-Files.documents, 'doc/Type/Mu.pod6', 'TEST_FILES 3 skip missing files, keep existing type match'; +is Test-Files.tests, '', 'TEST_FILES 3 skip missing files, bad type'; + diff --git a/xt/perl-nbsp.t b/xt/perl-nbsp.t index eba44da41..c9bfbd625 100755 --- a/xt/perl-nbsp.t +++ b/xt/perl-nbsp.t @@ -15,22 +15,19 @@ my @files = Test-Files.documents; plan +@files; for @files.sort -> $file { - my $ok = True; - my $row = 0; - my @bad; - my $content = $file.IO.slurp.lines.join("\n"); + my $err-count = 0; + my $content = $file.IO.slurp; for $content ~~ m:g/ 'Perl' $=(\s+) \d / -> $match { my $spaces = ~$match; if $spaces.chars != 1 || $spaces.uniname ne "NO-BREAK SPACE" { - $ok = False; - @bad.push: $row; + $err-count++; } } my $error = $file; - if !$ok { - $error ~= " (line{@bad>1 ?? "s" !! ""} {@bad.join: ', '})"; + if $err-count { + $error ~= " ($err-count instance{$err-count==1 ?? '' !! 's'})"; } - ok $ok, "$error: Perl followed by a version should have a single non-breaking space." ; + ok !$err-count, "$error: Perl followed by a version should have a single non-breaking space." ; } # vim: expandtab shiftwidth=4 ft=perl6 diff --git a/xt/pws/code.pws b/xt/pws/code.pws index f2dd55c85..2f7540b0e 100644 --- a/xt/pws/code.pws +++ b/xt/pws/code.pws @@ -56,6 +56,7 @@ ao apoint apperling aq +asciitilde asdf assixt astringandanint @@ -97,6 +98,8 @@ bloaty bn bol bq +bracketleft +bracketright brakcet bt btf @@ -116,6 +119,7 @@ cba ccc cdef cdgh +centre cha childclass childname @@ -126,11 +130,11 @@ cntrl codelines committable commonancestor -conditionvariable configurationsets configurationsetsactions configvalues consectetur +consologger coverable cp cppstruct @@ -153,6 +157,7 @@ digifier digitmatcher dirstat diskn +dists dm doit dojob @@ -201,6 +206,7 @@ fooz forbiddendirectory forgetit fotbar +fp freeaddrinfo freija frob @@ -210,6 +216,7 @@ fubar fullname funmath fuu +gaa gaatcc gargravarr gct @@ -217,7 +224,9 @@ gecos geth gg gha +ghghfxnnhrgfswe ghi +ghidora gniht gnirts goog @@ -227,6 +236,8 @@ greatunclebulgaria greppable groß gtt +guillemotleft +guillemotright hallo hasour havestaticattr @@ -270,6 +281,7 @@ lastname lenticular libbar libmoar +linkedlist listofstuff listoid lmao @@ -292,6 +304,7 @@ megingjörð messageboxa mfoo mh +mmn modulename moveup msvc @@ -321,6 +334,7 @@ nana nativecallable nbr nbsp +neutronium newclass newfunc nextone @@ -328,6 +342,7 @@ niler noez nosuch notthere +numbersign numerichost numericserv numlist @@ -370,7 +385,10 @@ qrstuvwx qs quant quietlevel +quotedbl qxelwq +raker +rakuy ranklist raquo rawheader @@ -386,9 +404,11 @@ resourceable restnameds restpos rg +räku sar sayit saysomething +sdk seener seqpacket setcallback @@ -420,6 +440,8 @@ synopsebot syslog tac talkin +tcc +tcg tellable tenten tes @@ -428,6 +450,7 @@ testee testgrammar textnode that'sawesome +thorndike tobermory tok toomany @@ -447,12 +470,16 @@ typedef typehouse tête ubits +uff uia +ukar +ultraman undersightable unflat unicodable unitish unspec +usafa vaya versionmajor versionminor @@ -483,6 +510,7 @@ yz za zapatilla zbcd +zipwith zwelp zycd zzbcd diff --git a/xt/pws/words.pws b/xt/pws/words.pws index 3ffd213fc..697952f56 100644 --- a/xt/pws/words.pws +++ b/xt/pws/words.pws @@ -57,6 +57,7 @@ arithmetics arity arrayref arraytype +asciicircum asec asech asin @@ -148,6 +149,7 @@ bitbucket bitmask bitmaskenumeration bitwise +bksl bom bool booleanification @@ -158,7 +160,8 @@ boolifies boolify bools boooh -boundable +braceleft +braceright brack bragi brainer @@ -207,7 +210,6 @@ chr chroot chrs circumfix -cis classhow classname cli @@ -226,6 +228,7 @@ colour combinators commandline comparator +compat compilable compiletime complexstr @@ -239,7 +242,9 @@ concat concreterolehow concretization cond +conditionvariable config +configitem configs conformant connor @@ -306,6 +311,7 @@ decont decontainerization decontainerize decontainerized +decrementing deepmap defaultparent definedness @@ -322,6 +328,8 @@ deparse dependencyspecification deprecations deps +dequeue +dequeues deref dereference dereferenced @@ -387,6 +395,8 @@ endnetent endprotoent endpwent endservent +enqueue +enqueues entrapments ents enum @@ -405,11 +415,14 @@ eqv errno esque euid +eurosign eval evalbot evalbytes evaled evalfile +evdev +exclam exe execl executables @@ -468,13 +481,13 @@ foy fptr fqn freebsd -freenode frobnicate frobnication frontend fsvo ftfy func +gammera gaz gc gcd @@ -588,11 +601,13 @@ imprecisions inb inblock incrementer +incrementing indir indirections inet infixes infixintermposition +inframan ini init initializable @@ -608,6 +623,7 @@ installermaker instanceof instantiation instantiations +interoperate interoperation intmax introspectable @@ -660,6 +676,8 @@ kbar kd kde kernelnames +keycodes +keymap keyof keypress keyvaluepairsactions @@ -672,11 +690,14 @@ kvpair kxxv lakhs langs +languagelist lastable lastcall latebound +layoutlist lcfirst ld +leftsinglequotemark lenz lenz's letterspace @@ -689,6 +710,7 @@ lf lgtm lhf lhs +libera libfoo libidn libmysql @@ -833,6 +855,7 @@ mustbestarted mutator mutators mutex +mutexes myfunnyrole mymodule myname @@ -912,6 +935,7 @@ nswap nswp ntop nul +nullish num numericenumeration numerics @@ -978,6 +1002,7 @@ param parameterization parameterizations parameterized +parameterizes parameterizing parameterless parametricconstant @@ -987,6 +1012,8 @@ parametricrolehow parametricrolehows params paren +parenleft +parenright parsable parsefile parsers @@ -1067,6 +1094,7 @@ procs profiler programfile programmatically +proleptic promisestatus propname propspec @@ -1114,6 +1142,7 @@ raceseqs radix radixoutofrange raja +rak raku raku's rakubrew @@ -1128,6 +1157,7 @@ rakulib rakumod rakutest rakuw +ralt ratstr readchars readdir @@ -1173,6 +1203,7 @@ rethrows reusability rewinddir rhs +rightsinglequotemark rindex rlwrap rmdir @@ -1238,6 +1269,7 @@ setpwent setservent setsockopt setty +setxkbmap sha shellquote shiftjis @@ -1247,6 +1279,7 @@ shmctl shmget shmread shmwrite +shortdescription shortname shoveller sig @@ -1391,6 +1424,7 @@ sysseek syswrite tabstop taketh +takewhile tanh tapbeforespawn tbd @@ -1418,6 +1452,7 @@ titlecase titlemodes tjd tkey +tlde tmi tmp tmpdir @@ -1426,6 +1461,8 @@ to's toc todo tol +tomtom +tomtommaps toolchain toolkits toperl @@ -1479,6 +1516,7 @@ uint ulong ulonglong unallowed +unary unbuffered uncomment uncontainerized @@ -1540,6 +1578,7 @@ vals valueidentifier valueobjat variadic +variantlist varlist vcs vec @@ -1602,6 +1641,8 @@ xfez xff xft xim +xkb +xkbcomp xorg xt xtest @@ -1615,6 +1656,7 @@ yy yyyy zape zef +zef's zipi zl zoffixznet diff --git a/xt/type-graph.t b/xt/type-graph.t index 17164d66c..550dc03cb 100755 --- a/xt/type-graph.t +++ b/xt/type-graph.t @@ -1,10 +1,10 @@ #!/usr/bin/env raku use Test; -use Perl6::TypeGraph; +use Doc::TypeGraph; use Telemetry; -my $t = Perl6::TypeGraph.new-from-file('type-graph.txt'); +my $t = Doc::TypeGraph.new-from-file('type-graph.txt'); for $t.sorted -> $type { next if $type.name.index('Metamodel').defined || $type.name eq 'PROCESS'; diff --git a/xt/word-variants.t b/xt/word-variants.t index ae3cd8ff9..c863e31db 100755 --- a/xt/word-variants.t +++ b/xt/word-variants.t @@ -12,44 +12,57 @@ Make sure certain words are normalized by checking regular expressions. my @files = Test-Files.pods; +# Keys are the preferred variant, values are regex to complain about my %variants = %( - filehandle => 'file [\s+|\-] handle', - filesystem => 'file [\s+|\-] system', - lookahead => 'look \- ahead', - lookbehind => 'look [\s+|\-] behind', - meta => ' meta -[\s+|\-] -<<', - metadata => 'meta [\s+|\+] data', - NYI => 'niy', - precompil => 'pre \- compil', - runtime => 'run [\s+|\-] time', - semicolon => 'semi [\s+|\-] colon', - shorthand => 'short [\s+|\-] hand', - sigiled => 'sigilled', - smartmatch => 'smart [\s+|\-] match', - subdirectory => 'sub \- directory', - zero-width => 'zero \s+ width', + # no lowercase 'boolean', unless it is followed by some selected + # characters as it might be included in a code snippet, + # see for example doc/Language/js-nutshell.pod6 + Boolean => rx/ << boolean \{ \} ]> > /, + "call site" => rx/ <<'call' '-'? 'site'>>/, + filehandle => rx:i/ << file [\s+|\-] handle /, + filesystem => rx:i/ << file [\s+|\-] system /, + lookahead => rx:i/ << look \- ahead /, + lookbehind => rx:i/ << look [\s+|\-] behind /, + meta => rx:i/ << meta [\s+|\-] << > > /, + metadata => rx:i/ << meta [\s+|\+] data /, + NYI => rx:i/ << niy /, + precompil => rx:i/ << pre \- compil /, + runtime => rx:i/ << run [\s+|\-] time /, + semicolon => rx:i/ << semi [\s+|\-] colon /, + shorthand => rx:i/ << short [\s+|\-] hand /, + sigiled => rx:i/ << sigilled /, + smartmatch => rx:i/ << smart [\s+|\-] match /, + subdirectories => rx:i/ << sub \- directories /, + subdirectory => rx:i/ << sub \- directory /, + zero-width => rx:i/ << zero \s+ width /, ); plan +@files; -for @files.sort -> $file { +my %result; + +for @files.race -> $file { my $ok = True; my $row = 0; my @bad; my $content = $file.IO.slurp.lines.join(" "); for %variants.kv -> $word, $rx { - if $content ~~ m/:i << <{$rx}> / { + if $content ~~ $rx { $ok = False; @bad.push: "«$/» found. We prefer 「$word」"; } } + %result{$file} = [$ok, @bad]; +} + +for %result.keys.sort -> $file { my $result = $file; + my $ok = %result{$file}[0]; + my @bad = %result{$file}[1]; if !$ok { - $result ~= " {@bad.join: ', '}): Certain words should be normalized. "; + $result ~= " {@bad.join: ', '}: Certain words should be normalized."; } - ok $ok, "$result" ; + ok $ok, $result; } # vim: expandtab shiftwidth=4 ft=perl6