Showing preview only (3,639K chars total). Download the full file or copy to clipboard to get everything.
Repository: perl6/doc
Branch: main
Commit: 2f8a5bd34949
Files: 523
Total size: 3.3 MB
Directory structure:
gitextract_770pvioc/
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ └── bug-report-or-feature-request.md
│ ├── pull_request_template.md
│ └── workflows/
│ └── test.yml
├── .gitignore
├── Build.rakumod
├── CONTRIBUTING.md
├── CREDITS
├── LICENSE
├── META6.json
├── Makefile
├── README.md
├── doc/
│ ├── Language/
│ │ ├── 101-basics.rakudoc
│ │ ├── REPL.rakudoc
│ │ ├── about.rakudoc
│ │ ├── brackets.rakudoc
│ │ ├── classtut.rakudoc
│ │ ├── community.rakudoc
│ │ ├── compilation.rakudoc
│ │ ├── concurrency.rakudoc
│ │ ├── containers.rakudoc
│ │ ├── contexts.rakudoc
│ │ ├── control.rakudoc
│ │ ├── create-cli.rakudoc
│ │ ├── distributions/
│ │ │ ├── configuration-structure.rakudoc
│ │ │ ├── introduction.rakudoc
│ │ │ ├── testing.rakudoc
│ │ │ ├── tools.rakudoc
│ │ │ └── uploading.rakudoc
│ │ ├── enumeration.rakudoc
│ │ ├── exceptions.rakudoc
│ │ ├── experimental.rakudoc
│ │ ├── faq.rakudoc
│ │ ├── filename-extensions.rakudoc
│ │ ├── functions.rakudoc
│ │ ├── glossary.rakudoc
│ │ ├── grammar_tutorial.rakudoc
│ │ ├── grammars.rakudoc
│ │ ├── hashmap.rakudoc
│ │ ├── haskell-to-p6.rakudoc
│ │ ├── intro.rakudoc
│ │ ├── io-guide.rakudoc
│ │ ├── io.rakudoc
│ │ ├── ipc.rakudoc
│ │ ├── iterating.rakudoc
│ │ ├── js-nutshell.rakudoc
│ │ ├── list.rakudoc
│ │ ├── making-modules/
│ │ │ ├── code.rakudoc
│ │ │ └── introduction.rakudoc
│ │ ├── math.rakudoc
│ │ ├── module-packages.rakudoc
│ │ ├── modules-core.rakudoc
│ │ ├── modules-extra.rakudoc
│ │ ├── modules.rakudoc
│ │ ├── mop.rakudoc
│ │ ├── nativecall.rakudoc
│ │ ├── nativetypes.rakudoc
│ │ ├── newline.rakudoc
│ │ ├── numerics.rakudoc
│ │ ├── objects.rakudoc
│ │ ├── operators.rakudoc
│ │ ├── optut.rakudoc
│ │ ├── packages.rakudoc
│ │ ├── performance.rakudoc
│ │ ├── perl-func.rakudoc
│ │ ├── perl-nutshell.rakudoc
│ │ ├── perl-op.rakudoc
│ │ ├── perl-overview.rakudoc
│ │ ├── perl-syn.rakudoc
│ │ ├── perl-var.rakudoc
│ │ ├── phasers.rakudoc
│ │ ├── pod.rakudoc
│ │ ├── pragmas.rakudoc
│ │ ├── py-nutshell.rakudoc
│ │ ├── quoting.rakudoc
│ │ ├── rb-nutshell.rakudoc
│ │ ├── regexes-best-practices.rakudoc
│ │ ├── regexes.rakudoc
│ │ ├── setbagmix.rakudoc
│ │ ├── signatures.rakudoc
│ │ ├── slangs.rakudoc
│ │ ├── statement-prefixes.rakudoc
│ │ ├── structures.rakudoc
│ │ ├── subscripts.rakudoc
│ │ ├── syntax.rakudoc
│ │ ├── system.rakudoc
│ │ ├── tables.rakudoc
│ │ ├── temporal.rakudoc
│ │ ├── terms.rakudoc
│ │ ├── testing.rakudoc
│ │ ├── traits.rakudoc
│ │ ├── traps.rakudoc
│ │ ├── typesystem.rakudoc
│ │ ├── unicode.rakudoc
│ │ ├── unicode_ascii.rakudoc
│ │ ├── unicode_entry.rakudoc
│ │ ├── using-modules/
│ │ │ ├── code.rakudoc
│ │ │ ├── finding-installing.rakudoc
│ │ │ └── introduction.rakudoc
│ │ └── variables.rakudoc
│ ├── Native/
│ │ └── int.rakudoc
│ ├── Programs/
│ │ ├── 01-debugging.rakudoc
│ │ ├── 02-reading-docs.rakudoc
│ │ ├── 03-environment-variables.rakudoc
│ │ ├── 04-running-raku.rakudoc
│ │ └── README.md
│ ├── Type/
│ │ ├── AST.rakudoc
│ │ ├── Allomorph.rakudoc
│ │ ├── Any.rakudoc
│ │ ├── Array.rakudoc
│ │ ├── Associative.rakudoc
│ │ ├── Attribute.rakudoc
│ │ ├── Backtrace/
│ │ │ └── Frame.rakudoc
│ │ ├── Backtrace.rakudoc
│ │ ├── Bag.rakudoc
│ │ ├── BagHash.rakudoc
│ │ ├── Baggy.rakudoc
│ │ ├── Blob.rakudoc
│ │ ├── Block.rakudoc
│ │ ├── Bool.rakudoc
│ │ ├── Buf.rakudoc
│ │ ├── CX/
│ │ │ ├── Done.rakudoc
│ │ │ ├── Emit.rakudoc
│ │ │ ├── Last.rakudoc
│ │ │ ├── Next.rakudoc
│ │ │ ├── Proceed.rakudoc
│ │ │ ├── Redo.rakudoc
│ │ │ ├── Return.rakudoc
│ │ │ ├── Succeed.rakudoc
│ │ │ ├── Take.rakudoc
│ │ │ └── Warn.rakudoc
│ │ ├── CallFrame.rakudoc
│ │ ├── Callable.rakudoc
│ │ ├── Cancellation.rakudoc
│ │ ├── Capture.rakudoc
│ │ ├── Channel.rakudoc
│ │ ├── Code.rakudoc
│ │ ├── Collation.rakudoc
│ │ ├── CompUnit/
│ │ │ ├── PrecompilationRepository.rakudoc
│ │ │ ├── Repository/
│ │ │ │ ├── FileSystem.rakudoc
│ │ │ │ ├── Installation.rakudoc
│ │ │ │ └── Unknown.rakudoc
│ │ │ └── Repository.rakudoc
│ │ ├── CompUnit.rakudoc
│ │ ├── Compiler.rakudoc
│ │ ├── Complex.rakudoc
│ │ ├── ComplexStr.rakudoc
│ │ ├── Cool.rakudoc
│ │ ├── CurrentThreadScheduler.rakudoc
│ │ ├── Date.rakudoc
│ │ ├── DateTime.rakudoc
│ │ ├── Dateish.rakudoc
│ │ ├── Distribution/
│ │ │ ├── Hash.rakudoc
│ │ │ ├── Locally.rakudoc
│ │ │ ├── Path.rakudoc
│ │ │ └── Resource.rakudoc
│ │ ├── Distribution.rakudoc
│ │ ├── Distro.rakudoc
│ │ ├── Duration.rakudoc
│ │ ├── Encoding/
│ │ │ └── Registry.rakudoc
│ │ ├── Encoding.rakudoc
│ │ ├── Endian.rakudoc
│ │ ├── Enumeration.rakudoc
│ │ ├── Exception.rakudoc
│ │ ├── Failure.rakudoc
│ │ ├── FatRat.rakudoc
│ │ ├── ForeignCode.rakudoc
│ │ ├── Format.rakudoc
│ │ ├── Formatter.rakudoc
│ │ ├── Grammar.rakudoc
│ │ ├── Hash.rakudoc
│ │ ├── HyperSeq.rakudoc
│ │ ├── HyperWhatever.rakudoc
│ │ ├── IO/
│ │ │ ├── ArgFiles.rakudoc
│ │ │ ├── CatHandle.rakudoc
│ │ │ ├── Handle.rakudoc
│ │ │ ├── Notification/
│ │ │ │ └── Change.rakudoc
│ │ │ ├── Notification.rakudoc
│ │ │ ├── Path/
│ │ │ │ ├── Cygwin.rakudoc
│ │ │ │ ├── Parts.rakudoc
│ │ │ │ ├── QNX.rakudoc
│ │ │ │ ├── Unix.rakudoc
│ │ │ │ └── Win32.rakudoc
│ │ │ ├── Path.rakudoc
│ │ │ ├── Pipe.rakudoc
│ │ │ ├── Socket/
│ │ │ │ ├── Async/
│ │ │ │ │ └── ListenSocket.rakudoc
│ │ │ │ ├── Async.rakudoc
│ │ │ │ └── INET.rakudoc
│ │ │ ├── Socket.rakudoc
│ │ │ ├── Spec/
│ │ │ │ ├── Cygwin.rakudoc
│ │ │ │ ├── QNX.rakudoc
│ │ │ │ ├── Unix.rakudoc
│ │ │ │ └── Win32.rakudoc
│ │ │ ├── Spec.rakudoc
│ │ │ └── Special.rakudoc
│ │ ├── IO.rakudoc
│ │ ├── Instant.rakudoc
│ │ ├── Int.rakudoc
│ │ ├── IntStr.rakudoc
│ │ ├── Iterable.rakudoc
│ │ ├── IterationBuffer.rakudoc
│ │ ├── Iterator.rakudoc
│ │ ├── Junction.rakudoc
│ │ ├── Kernel.rakudoc
│ │ ├── Label.rakudoc
│ │ ├── List.rakudoc
│ │ ├── Lock/
│ │ │ ├── Async.rakudoc
│ │ │ └── ConditionVariable.rakudoc
│ │ ├── Lock.rakudoc
│ │ ├── Macro.rakudoc
│ │ ├── Map.rakudoc
│ │ ├── Match.rakudoc
│ │ ├── Metamodel/
│ │ │ ├── AttributeContainer.rakudoc
│ │ │ ├── C3MRO.rakudoc
│ │ │ ├── ClassHOW.rakudoc
│ │ │ ├── ConcreteRoleHOW.rakudoc
│ │ │ ├── CurriedRoleHOW.rakudoc
│ │ │ ├── DefiniteHOW.rakudoc
│ │ │ ├── Documenting.rakudoc
│ │ │ ├── EnumHOW.rakudoc
│ │ │ ├── Finalization.rakudoc
│ │ │ ├── MROBasedMethodDispatch.rakudoc
│ │ │ ├── MethodContainer.rakudoc
│ │ │ ├── MethodDelegation.rakudoc
│ │ │ ├── Mixins.rakudoc
│ │ │ ├── MultipleInheritance.rakudoc
│ │ │ ├── Naming.rakudoc
│ │ │ ├── PackageHOW.rakudoc
│ │ │ ├── ParametricRoleGroupHOW.rakudoc
│ │ │ ├── ParametricRoleHOW.rakudoc
│ │ │ ├── Primitives.rakudoc
│ │ │ ├── PrivateMethodContainer.rakudoc
│ │ │ ├── RoleContainer.rakudoc
│ │ │ ├── RolePunning.rakudoc
│ │ │ ├── Stashing.rakudoc
│ │ │ ├── Trusting.rakudoc
│ │ │ ├── TypePretense.rakudoc
│ │ │ └── Versioning.rakudoc
│ │ ├── Method.rakudoc
│ │ ├── Mix.rakudoc
│ │ ├── MixHash.rakudoc
│ │ ├── Mixy.rakudoc
│ │ ├── Mu.rakudoc
│ │ ├── NFC.rakudoc
│ │ ├── NFD.rakudoc
│ │ ├── NFKC.rakudoc
│ │ ├── NFKD.rakudoc
│ │ ├── Nil.rakudoc
│ │ ├── Num.rakudoc
│ │ ├── NumStr.rakudoc
│ │ ├── Numeric.rakudoc
│ │ ├── ObjAt.rakudoc
│ │ ├── Order.rakudoc
│ │ ├── Pair.rakudoc
│ │ ├── Parameter.rakudoc
│ │ ├── Perl.rakudoc
│ │ ├── Pod/
│ │ │ ├── Block/
│ │ │ │ ├── Code.rakudoc
│ │ │ │ ├── Comment.rakudoc
│ │ │ │ ├── Declarator.rakudoc
│ │ │ │ ├── Named.rakudoc
│ │ │ │ ├── Para.rakudoc
│ │ │ │ └── Table.rakudoc
│ │ │ ├── Block.rakudoc
│ │ │ ├── Defn.rakudoc
│ │ │ ├── FormattingCode.rakudoc
│ │ │ ├── Heading.rakudoc
│ │ │ └── Item.rakudoc
│ │ ├── Positional.rakudoc
│ │ ├── PositionalBindFailover.rakudoc
│ │ ├── PredictiveIterator.rakudoc
│ │ ├── Proc/
│ │ │ └── Async.rakudoc
│ │ ├── Proc.rakudoc
│ │ ├── Promise.rakudoc
│ │ ├── PromiseStatus.rakudoc
│ │ ├── Proxy.rakudoc
│ │ ├── PseudoStash.rakudoc
│ │ ├── QuantHash.rakudoc
│ │ ├── RaceSeq.rakudoc
│ │ ├── Raku.rakudoc
│ │ ├── RakuAST/
│ │ │ ├── Doc/
│ │ │ │ ├── Block.rakudoc
│ │ │ │ ├── Declarator.rakudoc
│ │ │ │ ├── DeclaratorTarget.rakudoc
│ │ │ │ ├── Markup.rakudoc
│ │ │ │ └── Paragraph.rakudoc
│ │ │ └── Doc.rakudoc
│ │ ├── RakuAST.rakudoc
│ │ ├── Range.rakudoc
│ │ ├── Rat.rakudoc
│ │ ├── RatStr.rakudoc
│ │ ├── Rational.rakudoc
│ │ ├── Real.rakudoc
│ │ ├── Regex.rakudoc
│ │ ├── Routine/
│ │ │ └── WrapHandle.rakudoc
│ │ ├── Routine.rakudoc
│ │ ├── Scalar.rakudoc
│ │ ├── Scheduler.rakudoc
│ │ ├── Semaphore.rakudoc
│ │ ├── Seq.rakudoc
│ │ ├── Sequence.rakudoc
│ │ ├── Set.rakudoc
│ │ ├── SetHash.rakudoc
│ │ ├── Setty.rakudoc
│ │ ├── Signal.rakudoc
│ │ ├── Signature.rakudoc
│ │ ├── Slip.rakudoc
│ │ ├── Stash.rakudoc
│ │ ├── Str.rakudoc
│ │ ├── StrDistance.rakudoc
│ │ ├── Stringy.rakudoc
│ │ ├── Sub.rakudoc
│ │ ├── Submethod.rakudoc
│ │ ├── Supplier/
│ │ │ └── Preserving.rakudoc
│ │ ├── Supplier.rakudoc
│ │ ├── Supply.rakudoc
│ │ ├── Systemic.rakudoc
│ │ ├── Tap.rakudoc
│ │ ├── Telemetry/
│ │ │ ├── Instrument/
│ │ │ │ ├── Thread.rakudoc
│ │ │ │ ├── ThreadPool.rakudoc
│ │ │ │ └── Usage.rakudoc
│ │ │ ├── Period.rakudoc
│ │ │ └── Sampler.rakudoc
│ │ ├── Telemetry.rakudoc
│ │ ├── Test.rakudoc
│ │ ├── Thread.rakudoc
│ │ ├── ThreadPoolScheduler.rakudoc
│ │ ├── UInt.rakudoc
│ │ ├── Uni.rakudoc
│ │ ├── Unicode.rakudoc
│ │ ├── VM.rakudoc
│ │ ├── ValueObjAt.rakudoc
│ │ ├── Variable.rakudoc
│ │ ├── Version.rakudoc
│ │ ├── Whatever.rakudoc
│ │ ├── WhateverCode.rakudoc
│ │ ├── X/
│ │ │ ├── AdHoc.rakudoc
│ │ │ ├── Anon/
│ │ │ │ ├── Augment.rakudoc
│ │ │ │ └── Multi.rakudoc
│ │ │ ├── Assignment/
│ │ │ │ └── RO.rakudoc
│ │ │ ├── Attribute/
│ │ │ │ ├── NoPackage.rakudoc
│ │ │ │ ├── Package.rakudoc
│ │ │ │ ├── Required.rakudoc
│ │ │ │ └── Undeclared.rakudoc
│ │ │ ├── Augment/
│ │ │ │ └── NoSuchType.rakudoc
│ │ │ ├── Bind/
│ │ │ │ ├── NativeType.rakudoc
│ │ │ │ └── Slice.rakudoc
│ │ │ ├── Bind.rakudoc
│ │ │ ├── Caller/
│ │ │ │ └── NotDynamic.rakudoc
│ │ │ ├── Cannot/
│ │ │ │ ├── Empty.rakudoc
│ │ │ │ └── Lazy.rakudoc
│ │ │ ├── Channel/
│ │ │ │ ├── ReceiveOnClosed.rakudoc
│ │ │ │ └── SendOnClosed.rakudoc
│ │ │ ├── Comp.rakudoc
│ │ │ ├── Composition/
│ │ │ │ └── NotComposable.rakudoc
│ │ │ ├── Constructor/
│ │ │ │ └── Positional.rakudoc
│ │ │ ├── Control.rakudoc
│ │ │ ├── ControlFlow/
│ │ │ │ └── Return.rakudoc
│ │ │ ├── ControlFlow.rakudoc
│ │ │ ├── DateTime/
│ │ │ │ └── TimezoneClash.rakudoc
│ │ │ ├── Declaration/
│ │ │ │ ├── Scope/
│ │ │ │ │ └── Multi.rakudoc
│ │ │ │ └── Scope.rakudoc
│ │ │ ├── Does/
│ │ │ │ └── TypeObject.rakudoc
│ │ │ ├── Dynamic/
│ │ │ │ └── NotFound.rakudoc
│ │ │ ├── Eval/
│ │ │ │ └── NoSuchLang.rakudoc
│ │ │ ├── Export/
│ │ │ │ └── NameClash.rakudoc
│ │ │ ├── IO/
│ │ │ │ ├── BinaryMode.rakudoc
│ │ │ │ ├── Chdir.rakudoc
│ │ │ │ ├── Chmod.rakudoc
│ │ │ │ ├── Chown.rakudoc
│ │ │ │ ├── Copy.rakudoc
│ │ │ │ ├── Cwd.rakudoc
│ │ │ │ ├── Dir.rakudoc
│ │ │ │ ├── DoesNotExist.rakudoc
│ │ │ │ ├── Flush.rakudoc
│ │ │ │ ├── Link.rakudoc
│ │ │ │ ├── Lock.rakudoc
│ │ │ │ ├── Mkdir.rakudoc
│ │ │ │ ├── Move.rakudoc
│ │ │ │ ├── Rename.rakudoc
│ │ │ │ ├── Rmdir.rakudoc
│ │ │ │ ├── Symlink.rakudoc
│ │ │ │ └── Unlink.rakudoc
│ │ │ ├── IO.rakudoc
│ │ │ ├── Inheritance/
│ │ │ │ ├── NotComposed.rakudoc
│ │ │ │ └── Unsupported.rakudoc
│ │ │ ├── Method/
│ │ │ │ ├── InvalidQualifier.rakudoc
│ │ │ │ ├── NotFound.rakudoc
│ │ │ │ └── Private/
│ │ │ │ ├── Permission.rakudoc
│ │ │ │ └── Unqualified.rakudoc
│ │ │ ├── Mixin/
│ │ │ │ └── NotComposable.rakudoc
│ │ │ ├── NYI.rakudoc
│ │ │ ├── NoDispatcher.rakudoc
│ │ │ ├── Numeric/
│ │ │ │ ├── CannotConvert.rakudoc
│ │ │ │ ├── DivideByZero.rakudoc
│ │ │ │ └── Real.rakudoc
│ │ │ ├── OS.rakudoc
│ │ │ ├── Obsolete.rakudoc
│ │ │ ├── OutOfRange.rakudoc
│ │ │ ├── Package/
│ │ │ │ └── Stubbed.rakudoc
│ │ │ ├── Parameter/
│ │ │ │ ├── Default.rakudoc
│ │ │ │ ├── MultipleTypeConstraints.rakudoc
│ │ │ │ ├── Placeholder.rakudoc
│ │ │ │ ├── Twigil.rakudoc
│ │ │ │ └── WrongOrder.rakudoc
│ │ │ ├── Phaser/
│ │ │ │ ├── Multiple.rakudoc
│ │ │ │ └── PrePost.rakudoc
│ │ │ ├── Placeholder/
│ │ │ │ ├── Block.rakudoc
│ │ │ │ └── Mainline.rakudoc
│ │ │ ├── Pod.rakudoc
│ │ │ ├── Proc/
│ │ │ │ ├── Async/
│ │ │ │ │ ├── AlreadyStarted.rakudoc
│ │ │ │ │ ├── BindOrUse.rakudoc
│ │ │ │ │ ├── CharsOrBytes.rakudoc
│ │ │ │ │ ├── MustBeStarted.rakudoc
│ │ │ │ │ ├── OpenForWriting.rakudoc
│ │ │ │ │ └── TapBeforeSpawn.rakudoc
│ │ │ │ ├── Async.rakudoc
│ │ │ │ └── Unsuccessful.rakudoc
│ │ │ ├── Promise/
│ │ │ │ ├── CauseOnlyValidOnBroken.rakudoc
│ │ │ │ └── Vowed.rakudoc
│ │ │ ├── Redeclaration.rakudoc
│ │ │ ├── Role/
│ │ │ │ └── Initialization.rakudoc
│ │ │ ├── Scheduler/
│ │ │ │ └── CueInNaNSeconds.rakudoc
│ │ │ ├── Seq/
│ │ │ │ └── Consumed.rakudoc
│ │ │ ├── Sequence/
│ │ │ │ └── Deduction.rakudoc
│ │ │ ├── Signature/
│ │ │ │ ├── NameClash.rakudoc
│ │ │ │ └── Placeholder.rakudoc
│ │ │ ├── Str/
│ │ │ │ ├── Match/
│ │ │ │ │ └── x.rakudoc
│ │ │ │ └── Numeric.rakudoc
│ │ │ ├── StubCode.rakudoc
│ │ │ ├── Syntax/
│ │ │ │ ├── Augment/
│ │ │ │ │ └── WithoutMonkeyTyping.rakudoc
│ │ │ │ ├── Comment/
│ │ │ │ │ └── Embedded.rakudoc
│ │ │ │ ├── Confused.rakudoc
│ │ │ │ ├── InfixInTermPosition.rakudoc
│ │ │ │ ├── Malformed.rakudoc
│ │ │ │ ├── Missing.rakudoc
│ │ │ │ ├── NegatedPair.rakudoc
│ │ │ │ ├── NoSelf.rakudoc
│ │ │ │ ├── Number/
│ │ │ │ │ └── RadixOutOfRange.rakudoc
│ │ │ │ ├── P5.rakudoc
│ │ │ │ ├── Perl5Var.rakudoc
│ │ │ │ ├── Regex/
│ │ │ │ │ ├── Adverb.rakudoc
│ │ │ │ │ └── SolitaryQuantifier.rakudoc
│ │ │ │ ├── Reserved.rakudoc
│ │ │ │ ├── Self/
│ │ │ │ │ └── WithoutObject.rakudoc
│ │ │ │ ├── Signature/
│ │ │ │ │ └── InvocantMarker.rakudoc
│ │ │ │ ├── Term/
│ │ │ │ │ └── MissingInitializer.rakudoc
│ │ │ │ ├── UnlessElse.rakudoc
│ │ │ │ └── Variable/
│ │ │ │ ├── Match.rakudoc
│ │ │ │ ├── Numeric.rakudoc
│ │ │ │ └── Twigil.rakudoc
│ │ │ ├── Syntax.rakudoc
│ │ │ ├── Temporal/
│ │ │ │ └── InvalidFormat.rakudoc
│ │ │ ├── Temporal.rakudoc
│ │ │ ├── TypeCheck/
│ │ │ │ ├── Assignment.rakudoc
│ │ │ │ ├── Binding.rakudoc
│ │ │ │ ├── Return.rakudoc
│ │ │ │ └── Splice.rakudoc
│ │ │ ├── TypeCheck.rakudoc
│ │ │ └── Undeclared.rakudoc
│ │ ├── atomicint.rakudoc
│ │ ├── independent-routines.rakudoc
│ │ └── utf8.rakudoc
│ └── announcements.rakudoc
├── lib/
│ └── Pod/
│ ├── Cache.rakumod
│ └── Convenience.rakumod
├── resources/
│ └── i18n/
│ ├── de/
│ │ └── README.de.md
│ ├── es/
│ │ └── README.es.md
│ ├── fr/
│ │ └── README.fr.md
│ ├── it/
│ │ └── README.it.md
│ ├── jp/
│ │ └── README.jp.md
│ ├── nl/
│ │ └── README.nl.md
│ ├── pt/
│ │ └── README.pt.md
│ └── zh/
│ └── README.zh.md
├── t/
│ ├── 00-meta.rakutest
│ ├── 02-pod-valid.rakutest
│ ├── 03-tests-valid.rakutest
│ ├── 04-trailing-whitespace.rakutest
│ ├── 05-tabs.rakutest
│ ├── 06-double-dots.rakutest
│ ├── 07-duplicates.rakutest
│ ├── 08-headings.rakutest
│ ├── 09-final-newline.rakutest
│ ├── 10-vim-mode.rakutest
│ ├── 11-return-type.rakutest
│ ├── 12-perl-nbsp.rakutest
│ ├── 13-braces.rakutest
│ ├── 14-routine-definitions.rakutest
│ ├── 15-word-variants.rakutest
│ ├── 16-an-grammar.rakutest
│ ├── 17-space-after-comma.rakutest
│ ├── 18-rakuast-validate.rakutest
│ ├── 19-examples-compilation.rakutest
│ ├── 20-camelia-invocations.rakutest
│ ├── 21-version-release.rakutest
│ ├── 22-glossary-sorted.rakutest
│ ├── 23-aspell.rakutest
│ ├── 24-words.rakutest
│ └── pws/
│ ├── code.pws
│ └── words.pws
├── type-graph.txt
├── util/
│ ├── clean-spell
│ ├── create-brackets-table.raku
│ ├── dumpast.raku
│ ├── github-action-test.sh
│ ├── missing-types.raku
│ ├── new-type.raku
│ ├── perl-nbsp.raku
│ ├── sort-words.raku
│ ├── test-modified.sh
│ ├── test-website.raku
│ ├── unskip.raku
│ └── update-and-test
├── writing-docs/
│ ├── CREATING-NEW-DOCS.md
│ ├── EXAMPLES.md
│ ├── INDEXING.md
│ ├── README.md
│ ├── STYLEGUIDE.md
│ └── TESTING.md
└── xt/
├── 01-raku-version.rakutest
├── check-signatures.rakutest
├── rakuast-compare.rakutest
├── rakudoc-l.rakutest
├── rakudoc-types.rakutest
├── search-categories.rakutest
└── type-graph.rakutest
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/ISSUE_TEMPLATE/bug-report-or-feature-request.md
================================================
---
name: Bug report or feature request
about: Create a report to help us improve
title: ''
labels: docs
assignees: ''
---
## Problem or new feature
A clear and concise description of what the bug is, including links to the page where you have found it.
## Suggestions
If applicable, suggest something towards the solution.
================================================
FILE: .github/pull_request_template.md
================================================
## The problem
## Solution provided
<!--
The template below contains optional suggestions. Simply omit it
if you think it does not apply to this PR.
Please state clearly in "The problem" what you are addressing with this
pull request, referencing the issue(s) where it is described.
In "Solution provided", tell us what you have done to address the
problem.
-->
================================================
FILE: .github/workflows/test.yml
================================================
name: test
on:
push:
branches: [ main ]
paths:
- '**'
pull_request:
branches: [ main ]
paths:
- '**'
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: ${{ github.event_name == 'pull_request' && 2 || 0 }}
- name: Get changed files
id: changed-files
run: |
if ${{ github.event_name == 'pull_request' }}; then
echo "changed_files=$(git diff --name-only -r HEAD^1 HEAD | xargs)" >> $GITHUB_OUTPUT
else
echo "changed_files=$(git diff --name-only ${{ github.event.before }} ${{ github.event.after }} | xargs)" >> $GITHUB_OUTPUT
fi
- name: Run tests
run: ./util/github-action-test.sh t
env:
TEST_IMAGE: docker.io/coke/rakudo-docs-test
TEST_FILES: ${{ steps.changed-files.outputs.changed_files }}
================================================
FILE: .gitignore
================================================
# Precompilation folders
.precomp/
.pod-precomp
.pod-cache
# Generated files for testing
t/pws/aspell.pws
retest
# Cached file for building pages
util/Grammar.nqp
# IDE
*.iml
# website clone for testing
doc-website
================================================
FILE: Build.rakumod
================================================
class Build {
BEGIN {
note q:to/END/;
This repository is not intended to be installed!
View the latest HTML version at https://docs.raku.org/
Command line viewer at https://github.com/raku/rakudoc
END
die;
}
}
================================================
FILE: CONTRIBUTING.md
================================================
# Contributing
Your patches to `Raku/doc` are very welcome, and if you want to
help,
[please read this guide](https://github.com/Raku/doc/wiki) as
well as the detailed instructions below.
This document describes how to get started and helps to provide documentation
that adheres to the common style and formatting guidelines.
Your contributions here will be credited in the next Rakudo release
announcement. Your name from the commit log will be used. If you'd like to be
credited under a different name, please add it to the local [CREDITS](CREDITS)
file (or ask someone to do it for you until you have commit privileges).
If you have any questions regarding contributing to this project, please ask
in the [#raku IRC channel](https://raku.org/community/irc).
# TABLE OF CONTENTS
- [General principles](#general-principles)
- [Writing code examples](#writing-code-examples)
- [Indexing content](#indexing-content)
- [Adding a new Language document](#adding-a-new-language-document)
- [Documenting types](#documenting-types)
- [Writing and Testing Examples](#writing-and-testing-examples)
- [Debug mode](#debug-mode)
- [Invisible index anchors](#invisible-index-anchors)
- [Viewport size](#viewport-size)
- [Broken links](#broken-links)
- [Heading numbering](#heading-numbering)
- [Reporting bugs](#reporting-bugs)
- [Contributing pull requests](#contributing-pull-requests)
- [Dependency installation](#dependency-installation)
- [Rakudo](#rakudo)
- [Zef](#zef)
## General principles
* Please use the present tense unless writing about history or upcoming events or planned features
* Prefer [active voice](https://en.wikipedia.org/wiki/Active_voice) to the [passive voice](https://en.wikipedia.org/Passive_voice#In_English) with "by": "this is used by crafty programmers" → "crafty programmers use this"
* Link to external resources (like Wikipedia) for topics that are not
directly related to Raku (like the math that our routines implement).
* Duplicate small pieces of information rather than rely on linking.
* Be explicit about routine signatures. If a method accepts an `*%args`,
but treats some of them specially, list them separately.
* Check out [the styleguide](writing-docs/STYLEGUIDE.md) for further guidance.
## Documenting versions
* If you are adding a recently introduced feature, please indicate in a note
which version it was introduced in.
* If you change an example to use the new feature, leave the old
example if it's still working, at least while it's not obsolete, for people
who have not upgraded yet, clarifying in the text around it the versions it
will run with.
## Writing Code Examples
See [EXAMPLES.md](writing-docs/EXAMPLES.md) for detailed information on the options
available when writing code examples in the documentation.
## Indexing content
See [INDEXING.md](writing-docs/INDEXING.md) for detailed information on how
indexing of terms and locations in the documentation works.
## Adding a new Language document
We suggest you discuss proposing a new Language document on the #raku
channel and/or the [issues for this repository](https://github.com/Raku/doc/issues)
before you proceed further. After you get consensus on a title, subtitle,
section, and filename, you can add the document by following these steps:
+ create a **filename.rakudoc** file in the **doc/Language** directory and
ensure it adheres to the conventions in
[CREATING-NEW-DOCS.md](writing-docs/CREATING-NEW-DOCS.md).
## Documenting types
The Pod6 documentation of types is located in the `doc/Type` directory and
subdirectories of this repository. For example the Pod6 file of `X::Bind::Slice`
lives in `doc/Type/X/Bind/Slice.pod6`.
To start contributing, fork and checkout the repository, find the document
you want to improve, commit your changes, and create a pull request. Should
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.raku`. Say you want to create `MyFunnyRole`:
$ raku util/new-type.raku --kind=role MyFunnyRole
Fill the documentation file `doc/Type/MyFunnyRole.rakudoc` like this:
```raku
=TITLE role MyFunnyRole
=SUBTITLE Sentence or half-sentence about what it does
role MyFunnyRole does OtherRole is SuperClass { ... }
Longer description here about what this type is, and
how you can use it.
# usage example goes here
=head1 Methods
=head2 method do-it
method do-it(Int $how-often --> Nil:D)
Method description here
MyFunnyRole.do-it(2); # OUTPUT: «example output»
```
When documenting a pair of a sub and a method with the same functionality, the
heading should be `=head2 routine do-it`, and the next thing should be two or
more lines with the signatures. Other allowed words instead of `method` are
`sub`, `trait`, `infix`, `prefix`, `postfix`, `circumfix`, `postcircumfix`,
`term`. If you wish to hide a heading from any index, prefix it with the empty
comment `Z<>`.
When providing a code example result or output, use this style:
```raku
# For the result of an expression.
1 + 2; # RESULT: «3»
# For the output.
say 1 + 3; # OUTPUT: «3»
# For the explanatory comment
do-work; # We call do-work sub
```
## Running tests
Any contributions should pass the `make test` target. This insures basic
integrity of the documentation, and is run automatically by a corresponding
travis build. Even edits made via the GitHub editor should pass this test.
The repo should also pass `make xtest` most of the time - this includes
tests about whitespace and spelling that might be difficult to get right
on an initial commit, and shouldn't be considered to break the build. However,
if you're contributing a patch or pull request, this must pass.
If you have local modifications and want to insure they pass xtest before
committing, you can use this command to test only modified files:
TEST_FILES=`git status --porcelain --untracked-files=no | awk '{print $2}'` make xtest
## Writing and Testing Examples
See [Writing and Testing Examples](writing-docs/EXAMPLES.md)
## Debug mode
On the right side of the footer you can find [Debug: off]. Click it and reload
the page to activate debug mode. The state of debug mode will be remembered by
`window.sessionStorage` and will not survive a browser restart or opening the
docs in a new tab.
### Broken links
To check for broken links use debug mode. Any spotted broken link will be
listed under the search input. Please note that some external links may not get
checked depending on your browser settings.
### Heading numbering
Please check if the headings you add are well structured. You can use [debug mode](#debug-mode)
to display heading numbers.
## Reporting bugs
Report issues with the content on [github](https://github.com/Raku/doc/issues).
This includes missing or incorrect documentation, as well as information about
versioning (e.g., "method foo" only available in raku v6.d).
For issues with the website functionality (as opposed to the content), for
examples issues with search,
please report on [doc-website](https://github.com/Raku/doc-website/issues).
## Contributing pull requests
If you would like to contribute documentation or other bug fixes, please use
[GitHub's pull requests (PRs)](https://github.com/Raku/doc/pulls). For a complete
recipe for a new PR contributor, check [this PR guide](https://github.com/tbrowder/tidbits/blob/master/Contributing-PRs.md).
### Dependency installation
#### Raku
See [rakudo.org](https://rakudo.org/downloads) for Raku installation information.
#### Zef
To install any prerequisites for this module, use:
$ zef install --deps-only .
See [zef](https://github.com/ugexe/zef) for any questions on zef.
### Test the documentation
The [Makefile] has a lot of targets to help with testing the documentation
Use this command to see them:
$ make help
================================================
FILE: CREDITS
================================================
=pod
Following in the steps of other open source projects that
eventually take over the world, here is the partial list
of people who have contributed to this documentation.
It is sorted by name and formatted to allow easy
grepping and beautification by scripts.
The fields are: name (N), email (E), web-address (W),
description (D), GitHub username (U) and snail-mail
address (S).
Thanks,
The Raku/doc Team
PS: Yes, this looks remarkably like the Linux CREDITS format
PPS: This file is encoded in UTF-8
----------
N: ab5tract
E: john.haltiwanger@gmail.com
N: abcxyzp
E: abcxyz@cpan.org
N: Adrian Kreher
E: avuserow@gmail.com
N: Ahmad M. Zawawi
E: ahmad.zawawi@gmail.com
N: Akim Demaille
E: akim@lrde.epita.fr
N: Alex Chen
U: TisonKun
U: W4anD0eR96
E: wander4096@gmail.com
N: Alexander Moquin
E: alexmoquin@gmail.com
N: andreoss
E: andreoss@sdf.org
N: Andrew Egeler
E: andrew@egeler.us
N: Ben Noordhuis
E: info@bnoordhuis.nl
N: Ben Tyler
E: benjamin.tyler@gmail.com
N: Brent Laabs
E: bslaabs@gmail.com
N: Brian Duggan
U: bduggan
E: bduggan@matatu.org
N: Brock Wilcox
E: awwaiid@thelackthereof.org
N: Bruce Gray
E: bruce.gray@acm.org
N: Calvin Schwenzfeier
E: cschwenz@users.noreply.github.com
N: Carl Hayter
E: hayter@usc.edu
N: Carl Mäsak
E: cmasak@gmail.com
N: Carlin
E: carbin@users.noreply.github.com
N: Chloé Kekoa
E: rightfold+ck@gmail.com
W: foldr.nl
U: chloekek
N: Christopher Bottoms
E: molecules@users.noreply.github.com
N: Cole Keirsey
E: ckeirsey2@gmail.com
N: cygx
E: cygx@users.noreply.github.com
N: Cédric Vincent
E: cedric@reproducible.io
N: Daniel Green
U: MasterDuke17
E: ddgreen@gmail.com
N: David Farrell
E: davidnmfarrell@gmail.com
N: David H. Adler
E: dha@pobox.com
N: David M. Cawthon
E: dmc00@fastmail.com
N: David Simon Schultz
U: schultzdavid
E: dss@noreply.codeberg.org
N: Dmitriy Olshevskiy
E: olshevskiy87@bk.ru
N: Edwin Steiner
E: edwin.steiner@gmx.net
N: Elizabeth Mattijsen
U: lizmat
E: liz@wenzperl.nl
N: Eric Forste
U: arkiuat
E: arkiuat@mm.st
N: ennio
E: scriplit@yahoo.com
N: Felix Herrmann
E: felix@herrmann-koenigsberg.de
N: Florian Helmberger
E: fh@25th-floor.com
N: Gabor Szabo
E: gabor@szabgab.com
N: Geoffrey Broadwell
E: geoff@broadwell.org
N: GlitchMr
E: glitchmr@myopera.com
N: Graham Todd
E: info@opendevelopment.net
N: Heiko Jansen
E: heiko_jansen@web.de
N: Ilmari Vacklin
E: ilmari.vacklin@reaktor.fi
N: isBEKaml
E: nastavs@gmail.com
N: Jeremy Studer
E: studerj1.mail@gmail.com
N: Jimmy Zhuo
E: zhuomingliang@yahoo.com.cn
N: JJ Merelo
N: Juan Julián Merelo Guervós
E: jjmerelo@gmail.com
U: JJ
N: Joelle Maslak
E: jmaslak@antelope.net
U: jmaslak
N: John Gabriele
E: jgabriele@fastmail.fm
N: Joji Antony
E: simula67@gmail.com
N: Jonathan Scott Duff
E: duff@pobox.com
N: Jonathan Stowe
E: jns+git@gellyfish.co.uk
N: Jonathan Worthington
E: jnthn@jnthn.net
N: Justin DeVuyst
E: justin@devuyst.com
N: Kamil Kułaga
E: teodozjan@gmail.com
N: Karl Yerkes
E: karl.yerkes@gmail.com
N: Klaus Brüssel
E: trixium@web.de
N: Konrad Borowski
E: glitchmr@myopera.com
N: LLFourn
E: LLFourn@users.noreply.github.com
N: Lloyd Fournier
E: LLFourn@users.noreply.github.com
N: Luca Ferrari
E: fluca1978@gmail.com
W: https://fluca1978.github.io
U: fluca1978
N: lue
E: rnddim@gmail.com
N: lumimies
E: lumimies@gmail.com
N: Marcel Timmerman
E: mt1957@gmail.com
N: Matthew
E: rnddim@gmail.com
N: Matthias Krull
E: m.krull@uninets.eu
N: mdinger
E: mdinger.bugzilla@gmail.com
N: Mike Francis
E: ungrim97@gmail.com
N: Moray Jones
E: github@mrjones.co.uk
N: Moritz Lenz
E: moritz@faui2k3.org
U: moritz
U: moritz_
D: Initial p6doc development, documentation
N: Mouq
E: alexmoquin@gmail.com
N: muraiki
E: muraiki@users.noreply.github.com
N: Nami-Doc
E: vendethiel@hotmail.fr
N: Nathan Brown
E: nbrown04@gmail.com
N: Nick Logan
E: nlogan@gmail.com
N: niner
E: nine@detonation.org
N: Noel Maddy
E: zhtwnpanta@gmail.com
N: Nova Patch
E: patch@cpan.org
N: Patrick R. Michaud
U: pmichaud
D: Perl 6 (Rakudo Perl) lead developer
E: pmichaud@pobox.com
N: Paul Cochrane
E: paul@liekut.de
N: Pawel Pabian
E: bbkr@post.pl
N: Philippe Bruhat (BooK)
E: book@cpan.org
N: Prog Rammer
E: prammer1@gmail.com
N: raiph
E: ralphdjmellor@gmail.com
N: raydiak
E: raydiak@cyberuniverses.com
N: Ricardo Signes
E: rjbs@users.noreply.github.com
N: Rob Hoelz
E: rob@hoelz.ro
N: Ronald Schmidt
E: ronaldxs@software-path.com
N: ronaldxs
E: ronaldxs@software-path.com
N: Salve J. Nilsen
E: sjn@cpan.org
N: Sam S
E: smls75@gmail.com
N: sergot
E: filip@sergot.pl
N: Sgeo
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
N: smls
E: smls75@gmail.com
N: Stefan Seifert
E: nine@detonation.org
N: Sterling Hanenkamp
E: sterling@hanenkamp.com
N: Steve Mynott
E: steve.mynott@gmail.com
N: Stéphane Payrard
E: cognominal@gmail.com
N: Tadeusz Sośnierz
E: tadzikes@gmail.com
N: Tim Nelson
E: wayland@wayland.id.au
N: Tim Smith
E: tim.dolores@gmail.com
N: timo
E: timonator@perpetuum-immobile.de
N: Timo Paulssen
E: timonator@perpetuum-immobile.de
N: TimToady
E: larry@wall.org
N: Tobias Leich
E: email@froggs.de
N: Tokuhiro Matsuno
E: tokuhirom@gmail.com
N: Tom Browder
E: tom.browder@gmail.com
U: tbrowder
N: Trey Harris
E: treyharris@gmail.com
N: Claudio Ramirez
E: pub.claudio@gmail.com
N: ugexe
E: nlogan@gmail.com
N: usev6
E: use_v6@aglaz.de
N: ven
E: vendethiel@hotmail.fr
N: VZ
E: vz-github@zeitlins.org
N: Wenzel P. P. Peppmeyer
U: gfldex
E: wenzel.peppmeyer@gmx.de
N: Will Coleda
N: Coke
E: will@coleda.com
N: Xtreak
E: tirkarthi@users.noreply.github.com
N: Zoffix Znet
E: cpan@zoffix.com
=cut
================================================
FILE: LICENSE
================================================
The Artistic License 2.0
Copyright (c) 2000-2006, The Perl Foundation.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
This license establishes the terms under which a given free software
Package may be copied, modified, distributed, and/or redistributed.
The intent is that the Copyright Holder maintains some artistic
control over the development of that Package while still keeping the
Package available as open source and free software.
You are always permitted to make arrangements wholly outside of this
license directly with the Copyright Holder of a given Package. If the
terms of this license do not permit the full use that you propose to
make of the Package, you should contact the Copyright Holder and seek
a different licensing arrangement.
Definitions
"Copyright Holder" means the individual(s) or organization(s)
named in the copyright notice for the entire Package.
"Contributor" means any party that has contributed code or other
material to the Package, in accordance with the Copyright Holder's
procedures.
"You" and "your" means any person who would like to copy,
distribute, or modify the Package.
"Package" means the collection of files distributed by the
Copyright Holder, and derivatives of that collection and/or of
those files. A given Package may consist of either the Standard
Version, or a Modified Version.
"Distribute" means providing a copy of the Package or making it
accessible to anyone else, or in the case of a company or
organization, to others outside of your company or organization.
"Distributor Fee" means any fee that you charge for Distributing
this Package or providing support for this Package to another
party. It does not mean licensing fees.
"Standard Version" refers to the Package if it has not been
modified, or has been modified only in ways explicitly requested
by the Copyright Holder.
"Modified Version" means the Package, if it has been changed, and
such changes were not explicitly requested by the Copyright
Holder.
"Original License" means this Artistic License as Distributed with
the Standard Version of the Package, in its current version or as
it may be modified by The Perl Foundation in the future.
"Source" form means the source code, documentation source, and
configuration files for the Package.
"Compiled" form means the compiled bytecode, object code, binary,
or any other form resulting from mechanical transformation or
translation of the Source form.
Permission for Use and Modification Without Distribution
(1) You are permitted to use the Standard Version and create and use
Modified Versions for any purpose without restriction, provided that
you do not Distribute the Modified Version.
Permissions for Redistribution of the Standard Version
(2) You may Distribute verbatim copies of the Source form of the
Standard Version of this Package in any medium without restriction,
either gratis or for a Distributor Fee, provided that you duplicate
all of the original copyright notices and associated disclaimers. At
your discretion, such verbatim copies may or may not include a
Compiled form of the Package.
(3) You may apply any bug fixes, portability changes, and other
modifications made available from the Copyright Holder. The resulting
Package will still be considered the Standard Version, and as such
will be subject to the Original License.
Distribution of Modified Versions of the Package as Source
(4) You may Distribute your Modified Version as Source (either gratis
or for a Distributor Fee, and with or without a Compiled form of the
Modified Version) provided that you clearly document how it differs
from the Standard Version, including, but not limited to, documenting
any non-standard features, executables, or modules, and provided that
you do at least ONE of the following:
(a) make the Modified Version available to the Copyright Holder
of the Standard Version, under the Original License, so that the
Copyright Holder may include your modifications in the Standard
Version.
(b) ensure that installation of your Modified Version does not
prevent the user installing or running the Standard Version. In
addition, the Modified Version must bear a name that is different
from the name of the Standard Version.
(c) allow anyone who receives a copy of the Modified Version to
make the Source form of the Modified Version available to others
under
(i) the Original License or
(ii) a license that permits the licensee to freely copy,
modify and redistribute the Modified Version using the same
licensing terms that apply to the copy that the licensee
received, and requires that the Source form of the Modified
Version, and of any works derived from it, be made freely
available in that license fees are prohibited but Distributor
Fees are allowed.
Distribution of Compiled Forms of the Standard Version
or Modified Versions without the Source
(5) You may Distribute Compiled forms of the Standard Version without
the Source, provided that you include complete instructions on how to
get the Source of the Standard Version. Such instructions must be
valid at the time of your distribution. If these instructions, at any
time while you are carrying out such distribution, become invalid, you
must provide new instructions on demand or cease further distribution.
If you provide valid instructions or cease distribution within thirty
days after you become aware that the instructions are invalid, then
you do not forfeit any of your rights under this license.
(6) You may Distribute a Modified Version in Compiled form without
the Source, provided that you comply with Section 4 with respect to
the Source of the Modified Version.
Aggregating or Linking the Package
(7) You may aggregate the Package (either the Standard Version or
Modified Version) with other packages and Distribute the resulting
aggregation provided that you do not charge a licensing fee for the
Package. Distributor Fees are permitted, and licensing fees for other
components in the aggregation are permitted. The terms of this license
apply to the use and Distribution of the Standard or Modified Versions
as included in the aggregation.
(8) You are permitted to link Modified and Standard Versions with
other works, to embed the Package in a larger work of your own, or to
build stand-alone binary or bytecode versions of applications that
include the Package, and Distribute the result without restriction,
provided the result does not expose a direct interface to the Package.
Items That are Not Considered Part of a Modified Version
(9) Works (including, but not limited to, modules and scripts) that
merely extend or make use of the Package, do not, by themselves, cause
the Package to be a Modified Version. In addition, such works are not
considered parts of the Package itself, and are not subject to the
terms of this license.
General Provisions
(10) Any use, modification, and distribution of the Standard or
Modified Versions is governed by this Artistic License. By using,
modifying or distributing the Package, you accept this license. Do not
use, modify, or distribute the Package, if you do not accept this
license.
(11) If your Modified Version has been derived from a Modified
Version made by someone other than you, you are nevertheless required
to ensure that your Modified Version complies with the requirements of
this license.
(12) This license does not grant you the right to use any trademark,
service mark, tradename, or logo of the Copyright Holder.
(13) This license includes the non-exclusive, worldwide,
free-of-charge patent license to make, have made, use, offer to sell,
sell, import and otherwise transfer the Package with respect to any
patent claims licensable by the Copyright Holder that are necessarily
infringed by the Package. If you institute patent litigation
(including a cross-claim or counterclaim) against any party alleging
that the Package constitutes direct or contributory patent
infringement, then this Artistic License to you shall terminate on the
date that such litigation is filed.
(14) Disclaimer of Warranty:
THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS
IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL
LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================
FILE: META6.json
================================================
{
"name": "Raku doc",
"description": "Raku™ documentation",
"version": "2.0",
"raku": "6.*",
"authors": [
"raku"
],
"auth": "raku",
"test-depends": [
"Cro::HTTP::Client",
"File::Temp",
"Test::META",
"Doc::TypeGraph",
"RakuDoc::Test::Files:ver<0.3+>"
],
"build-depends": [],
"provides": {
"Pod::Cache": "lib/Pod/Cache.rakumod",
"Pod::Convenience": "lib/Pod/Convenience.rakumod"
},
"support": {
"source": "git://github.com/Raku/doc.git"
},
"license": "Artistic-2.0",
"tags": [
"raku",
"pod6",
"rakudoc",
"documentation",
"reference",
"perl6"
],
"source-url": "git://github.com/Raku/doc.git",
"meta6": "0"
}
================================================
FILE: Makefile
================================================
.PHONY: test xtest push help
help:
@echo "Usage: make [test|xtest|push]"
@echo ""
@echo "Options:"
@echo " test: run the basic test suite"
@echo " xtest: run all tests"
@echo " push: run the basic test suite and git push"
# Common tests - also run by CI
test:
if [ "${TEST_JOBS}" != "" ]; then prove --ext=rakutest -j ${TEST_JOBS} -e raku t; else prove --ext=rakutest -e raku t; fi
# Extended tests - should be run by authors before committing
xtest:
if [ "${TEST_JOBS}" != "" ]; then prove --ext=rakutest -j ${TEST_JOBS} -e raku t xt; else prove --ext=rakutest -e raku t xt; fi
push: test
git pull --rebase && git push
================================================
FILE: README.md
================================================
# Official Documentation of Raku™
[](https://opensource.org/licenses/Artistic-2.0)
[](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/).
That site is updated from the main branch here
frequently (but not continuously).
This is currently the recommended way to consume the documentation. The tooling
to build and run this site is [available on github](https://github.com/Raku/doc-website).
This repository is not intended to be installed as a module. When running tests or
scripts locally, you may need to set ``RAKULIB=.``
## README in other languages
[日本語](resources/i18n/jp/README.jp.md)
| [普通话](resources/i18n/zh/README.zh.md)
| [Deutsch](resources/i18n/de/README.de.md)
| [español](resources/i18n/es/README.es.md)
| [français](resources/i18n/fr/README.fr.md)
| [italiano](resources/i18n/it/README.it.md)
| [nederlands](resources/i18n/nl/README.nl.md)
| [Português](resources/i18n/pt/README.pt.md)
## Help Wanted!
[Interested in contributing?](writing-docs/README.md)
## Why aren't the docs embedded in the compiler source?
1. This documentation is intended to be universal with
respect to the specification, and not tied to any specific
implementation.
2. Implementations' handling of embedded Pod is still
a bit uneven; this avoids potential runtime impacts.
3. This separate repo in the Raku Github account invites
more potential contributors and editors.
## rakudoc
There is a [CLI](https://github.com/Raku/rakudoc) for viewing Raku documentation.
## Vision
> I want p6doc and docs.raku.org to become the No. 1 resource to consult
> when you want to know something about a Raku feature, be it from the
> language, or built-in types and routines. I want it to be useful to every
> Raku programmer.
>
> -- moritz
# LICENSE
The documentation and code in this repository is available under the Artistic License 2.0
as published by [The Perl & Raku Foundation (TPRF)](https://rakufoundation.org).
See the [LICENSE](LICENSE) file for the full text.
This repository may also contain examples authored by third parties that may be licensed under a different license. Such
files indicate the copyright and license terms at the top of the file. Currently these include:
* 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))
================================================
FILE: doc/Language/101-basics.rakudoc
================================================
=begin pod :kind("Language") :subkind("Language") :category("beginning")
=TITLE Raku by example 101
=SUBTITLE A basic introductory example of a Raku program
Suppose that you host a table tennis tournament. The referees tell you
the results of each game in the format C<Player1 Player2 | 3:2>, which
means that C<Player1> won against C<Player2> by 3 to 2 sets. You need a
script that sums up how many matches and sets each player has won to
determine the overall winner.
The input data (stored in a file called C<scores.txt>) looks like this:
=for code :lang<data>
Beth Ana Charlie Dave
Ana Dave | 3:0
Charlie Beth | 3:1
Ana Beth | 2:3
Dave Charlie | 3:0
Ana Charlie | 3:1
Beth Dave | 0:3
The first line is the list of players. Every subsequent line records a result
of a match.
Here's one way to solve that problem in Raku:
=begin code :solo
use v6;
# start by printing out the header.
say "Tournament Results:\n";
my $file = open 'scores.txt'; # get filehandle and...
my @names = $file.get.words; # ... get players.
my %matches;
my %sets;
for $file.lines -> $line {
next unless $line; # ignore any empty lines
my ($pairing, $result) = $line.split(' | ');
my ($p1, $p2) = $pairing.words;
my ($r1, $r2) = $result.split(':');
%sets{$p1} += $r1;
%sets{$p2} += $r2;
if $r1 > $r2 {
%matches{$p1}++;
} else {
%matches{$p2}++;
}
}
my @sorted = @names.sort({ %sets{$_} }).sort({ %matches{$_} }).reverse;
for @sorted -> $n {
my $match-noun = %matches{$n} == 1 ?? 'match' !! 'matches';
my $set-noun = %sets{$n} == 1 ?? 'set' !! 'sets';
say "$n has won %matches{$n} $match-noun and %sets{$n} $set-noun";
}
=end code
This produces the output:
=begin code :lang<text>
Tournament Results:
Ana has won 2 matches and 8 sets
Dave has won 2 matches and 6 sets
Charlie has won 1 match and 4 sets
Beth has won 1 match and 4 sets
=end code
=head1 Pragma X<C<v6>|Tutorial,v6 (Basics)>
=begin code :solo
use v6;
=end code
Every Raku program should begin with a line similar to C<use v6;>. This line
tells the compiler which version of Raku the program expects. For instance,
6.c is an example of a Raku version. Should you accidentally run the file
with Perl, you'll get a helpful error message.
=head1 X<Statements|Tutorial,statement (Basics)>
=begin code
# start by printing out the header.
say "Tournament Results:\n";
=end code
A Raku program consists of zero or more statements. A I<statement> ends with
a semicolon or a curly brace at the end of a line.
In Raku, single line comments start with a single hash character C<#> and
extend until the end of the line. Raku also supports
L<multi-line/embedded comments|/language/syntax#Multi-line_/_embedded_comments>.
The compiler doesn't evaluate comments as program text and they're only intended
for human readers.
=head1 X<Lexical scope|Tutorial,my (Basics)> and X<block|Tutorial,block (Basics)>
=begin code
my $file = open 'scores.txt';
=end code
C<my> declares a lexical variable, which are visible only in the current block
from the point of declaration to the end of the block. If there's no enclosing
block, it's visible throughout the remainder of the file (which would
effectively be the enclosing block). A block is any part of the code enclosed
between curly braces C<{ }>.
=head2 X<Sigils|Tutorial,sigils (Basics)> and X<identifiers|Tutorial,identifiers (Basics)>
A variable name begins with a I<sigil>, which is a non-alpha-numeric
symbol such as C<$>, C<@>, C<%>, or C<&> E<mdash> or occasionally the double
colon C<::>. Sigils indicate the structural interface for the variable,
such as whether it should be treated as a single value, a compound value,
a subroutine, etc. After the sigil comes an I<identifier>, which may
consist of letters, digits and the underscore. Between letters you can
also use a dash C<-> or an apostrophe C<'>, so C<isn't> and
C<double-click> are valid identifiers.
=head2 X<Scalar|Tutorial,scalar (Basics)>
Sigils indicate the default access method for a variable. Variables
with the C<@> sigil are accessed positionally; variables with the C<%>
sigil are accessed by string key. The C<$> sigil, however, indicates a
general scalar container that can hold any single value and be accessed
in any manner. A scalar can even contain a compound object like an
L<C<Array>|/type/Array> or a L<C<Hash>|/type/Hash>; the C<$> sigil signifies that it should be
treated as a single value, even in a context that expects multiple
values (as with an L<C<Array>|/type/Array> or L<C<Hash>|/type/Hash>).
=head2 X<Filehandle|Tutorial,filehandle (Basics)> and X<assignment|Tutorial,assignment (Basics)>
The built-in function C<open> opens a file, here named C<scores.txt>,
and returns a I<filehandle> E<mdash> an object representing that file. The
assignment operator C<=> I<assigns> that filehandle to the variable on the left,
which means that C<$file> now stores the filehandle.
=head2 X<String literals|Tutorial,string literal (Basics)>
C<'scores.txt'> is a I<string literal>. A string is a piece of text, and a
string literal is a string which appears directly in the program. In this line,
it's the argument provided to C<open>.
=head1 X<Arrays|Tutorial,array (Basics)>, X<methods|Tutorial,method (Basics)> and X<invocants|Tutorial,invocant (Basics)>
=begin code :preamble<my $file>
my @names = $file.get.words;
=end code
The right-hand side calls a I<method> E<mdash> a named group of
behavior E<mdash> named C<get> on the filehandle stored in C<$file>. The C<get>
method reads and returns one line from the file, removing the line ending. If
you print the contents of C<$file> after calling C<get>, you will see that the
first line is no longer in there. C<words> is also a method, called on the
string returned from C<get>. C<words> decomposes its I<invocant> E<mdash>
the string on which it operates E<mdash> into a list of words, which here means
strings separated by whitespace. It turns the single string C<'Beth Ana Charlie
Dave'> into the list of strings C<'Beth', 'Ana', 'Charlie', 'Dave'>.
Finally, this list gets stored in the L<C<Array>|/type/Array> C<@names>.
The C<@> sigil marks the declared variable as an L<C<Array>|/type/Array>.
Arrays store ordered lists.
=head1 X<Hashes|Tutorial,hash (Basics)>
=begin code
my %matches;
my %sets;
=end code
These two lines of code declare two hashes. The C<%> sigil marks each variable
as a L<C<Hash>|/type/Hash>. A L<C<Hash>|/type/Hash> is an unordered collection of key-value pairs. Other
programming languages call that a I<hash table>, I<dictionary>, or I<map>.
You can query a hash table for the value that corresponds to a certain
C<$key> with C<%hash{$key}>.
In the score counting program, C<%matches> stores the number of matches each
player has won. C<%sets> stores the number of sets each player has won. Both
of these hashes are indexed by the player's name.
=head1 X<C<for>|Tutorial,for (Basics)> and blocks
=begin code :preamble<my $file>
for $file.lines -> $line {
...
}
=end code
C<for> produces a loop that runs the I<block> delimited by curly braces
once for each item of the list, setting the variable C<$line>
to the current value of each iteration. C<$file.lines> produces a list of
the lines read from the file C<scores.txt>, starting with the second line
of the file since we already called C<$file.get> once, and going all the way
to the end of the file.
During the first iteration, C<$line> will contain the string C<Ana Dave |
3:0>; during the second, C<Charlie Beth | 3:1>, and so on.
=begin code :preamble<my $line>
my ($pairing, $result) = $line.split(' | ');
=end code
C<my> can declare multiple variables simultaneously. The right-hand side of the
assignment is a call to a method named C<split>, passing along the string
C<' | '> as an argument.
C<split> decomposes its invocant into a list of strings, so that joining the
list items with the separator C<' | '> produces the original string.
C<$pairing> gets the first item of the returned list, and C<$result> the second.
After processing the first line, C<$pairing> will hold the string C<Ana Dave>
and C<$result> will hold C<3:0>.
The next two lines follow the same pattern:
=begin code :preamble<my $pairing;my $result>
my ($p1, $p2) = $pairing.words;
my ($r1, $r2) = $result.split(':');
=end code
The first extracts and stores the names of the two players in the variables
C<$p1> and C<$p2>. The second extracts the results for each player and stores
them in C<$r1> and C<$r2>.
After processing the first line of the file, the variables contain the values:
=begin table
Variable Contents
$line 'Ana Dave \| 3:0'
$pairing 'Ana Dave'
$result '3:0'
$p1 'Ana'
$p2 'Dave'
$r1 '3'
$r2 '0'
=end table
The program then counts the number of sets each player has won:
=begin code :preamble<my %sets;my $p1;my $p2;my $r1;my $r2>
%sets{$p1} += $r1;
%sets{$p2} += $r2;
=end code
The above two statements involve the C<+=> compound assignment operator. They
are a variant of the following two statements that use the simple assignment
operator C<=> and that may be easier to understand at first sight:
=begin code :preamble<my %sets;my $p1;my $p2;my $r1;my $r2>
%sets{$p1} = %sets{$p1} + $r1;
%sets{$p2} = %sets{$p2} + $r2;
=end code
For your program, the shorthand version using the C<+=> compound assignment
operator is preferred over the longhand version using the simple assignment
operator C<=>. This is not only because the shorter version requires less
typing, but also because the C<+=> operator silently initializes undefined
values of the hash's key-value pairs to zero. In other words: by using C<+=>,
there is no need to include a separate statement like C<%sets{$p1} = 0> before
you can meaningfully add C<$r1> to it. We'll look at this behavior in a bit
more detail below.
=head2 X<C<Any>|Tutorial,Any (Basics)> and X<C<+=>|Tutorial,+= (Basics)>
=begin code :preamble<my %sets;my $p1;my $p2;my $r1;my $r2>
%sets{$p1} += $r1;
%sets{$p2} += $r2;
=end code
C<%sets{$p1} += $r1> means I<increase the value in the variable on the left by $r1>.
In the first iteration C<%sets{$p1}> is not yet defined, so it defaults to a special
value called L<C<Any>|/type/Any>. The C<+=> operator conveniently treats the undefined value
L<C<Any>|/type/Any> as a number with the value C<0>, allowing it to sensibly add some other
value to it. To perform the addition, the strings C<$r1>, C<$r2>, etc. are
automatically converted to numbers, as addition is a numeric operation.
=head2 X<Fat arrow|Tutorial,fat arrow (Basics)>, X<pairs|Tutorial,pair (Basics)> and X<autovivification|Tutorial,autovivification (Basics)>
Before these two lines execute, C<%sets> is empty. Adding to an entry that is
not in the hash yet will cause that entry to spring into existence
just-in-time, with a value starting at zero. This behavior is known as
I<autovivification>. After these two lines have run for the first time, C<%sets>
contains C«'Ana' => 3, 'Dave' => 0». (The fat arrow C«=>» separates the
key and the value in a L<C<Pair>|/type/Pair>.)
=head2 X<Postincrement|Tutorial,postincrement (Basics)> and X<preincrement|Tutorial,preincrement (Basics)>
=begin code :preamble<my $r1;my $r2;my $p1;my $p2;my %matches;>
if $r1 > $r2 {
%matches{$p1}++;
} else {
%matches{$p2}++;
}
=end code
If C<$r1> is numerically larger than C<$r2>, C<%matches{$p1}> increments by one.
If C<$r1> is not larger than C<$r2>, C<%matches{$p2}> increments. Just as in
the case of C<+=>, if either hash value did not exist previously, it is
autovivified by the increment operation.
C<$thing++> is a variant of C<$thing += 1>; it differs from the latter in that
the return value of the expression is C<$thing> I<before> the increment, and not
the incremented value. As in many other programming languages, you can use C<++>
as a prefix. Then it returns the incremented value: C<my $x = 1; say ++$x>
prints C<2>.
=head1 X<Topic variable|Tutorial,topic variable (Basics)>
=begin code :preamble<my @names;my %sets;my %matches>
my @sorted = @names.sort({ %sets{$_} }).sort({ %matches{$_} }).reverse;
=end code
This line consists of three individually simple steps. An array's C<sort>
method returns a sorted version of the array's contents. However, the default
sort on an array sorts by its contents. To print player names in winner-first
order, the code must sort the array by the I<scores> of the players, not their
names. The C<sort> method's argument is a I<block> used to transform the array
elements (the names of players) to the data by which to sort. The array items
are passed in through the I<topic variable> C<$_>.
=head2 Blocks
You have seen blocks before: both the C<for> loop C<<-> $line { ... }>> and
the C<if> statement worked on blocks. A block is a self-contained piece of
Raku code with an optional signature (the C<<-> $line>> part).
The simplest way to sort the players by score would be C<@names.sort({
%matches{$_} })>, which sorts by number of matches won. However Ana and Dave
have both won two matches. That simple sort doesn't account for the number of
sets won, which is the secondary criterion to decide who has won the
tournament.
=head2 Stable sort
When two array items have the same value, C<sort> leaves them in the same order
as it found them. Computer scientists call this a I<stable sort>. The program
takes advantage of this property of Raku's C<sort> to achieve the goal by
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<Beth Charlie Dave
Ana>. After the second sorting step, it's still the same, because no one has
won fewer matches but more sets than someone else. Such a situation is entirely
possible, especially at larger tournaments.
C<sort> sorts in ascending order, from smallest to largest. This is the
opposite of the desired order. Therefore, the code calls the C<.reverse> method
on the result of the second sort, and stores the final list in C<@sorted>.
=head1 Standard output
=begin code :preamble<my @sorted;my %matches;my %sets>
for @sorted -> $n {
my $match-noun = %matches{$n} == 1 ?? 'match' !! 'matches';
my $set-noun = %sets{$n} == 1 ?? 'set' !! 'sets';
say "$n has won %matches{$n} $match-noun and %sets{$n} $set-noun";
}
=end code
To print out the players and their scores, the code loops over C<@sorted>,
setting C<$n> to the name of each player in turn. Read this code as "For each
element of sorted, set C<$n> to the element, then execute the contents of the
following block." The variable C<$match-noun> will store either the string
I<match> if the player has won a single match or I<matches> if the player
has won zero or more matches. In order to do this, the I<ternary>
operator (C<?? !!>) is used. If C<%matches{$n} == 1> evaluates to C<True>,
then I<match> is returned. Otherwise, I<matches> is returned. Either way,
the returned value is stored in C<$match-noun>. The same approach applies
to C<$set-noun>.
The statement C<say> prints its arguments to the standard output
(the screen, normally), followed by a newline. (Use C<print> if you don't
want the newline at the end.)
Note that C<say> will truncate certain data structures by calling the C<.gist>
method so C<put> is safer if you want exact output.
=head2 X<Variable interpolation|Tutorial,variable interpolation (Basics)>
When you run the program, you'll see that C<say> doesn't print the contents of
that string verbatim. In place of C<$n> it prints the contents of the variable
C<$n> E<mdash> a player's name stored in C<$n>. This automatic substitution
of code with its contents is called I<interpolation>. This interpolation happens
only in strings delimited by double quotes C<"...">. Single quoted strings
C<'...'> do not interpolate:
=head2 X<Double-quoted strings|Tutorial,double-quoted strings> and X<single-quoted strings|Tutorial,single-quoted strings>
=begin code
my $names = 'things';
say 'Do not call me $names'; # OUTPUT: «Do not call me $names»
say "Do not call me $names"; # OUTPUT: «Do not call me things»
=end code
Double quoted strings in Raku can interpolate variables with the C<$>
sigil as well as blocks of code in curly braces. Since any arbitrary
Raku code can appear within curly braces, L<C<Array>|/type/Array>s and L<C<Hash>|/type/Hash>es may be
interpolated by placing them within curly braces.
Arrays within curly braces are interpolated with a single space character
between each item. Hashes within curly braces are interpolated as a series of
lines. Each line will contain a key, followed by a tab character, then the
value associated with that key, and finally a newline.
Let's see an example of this now.
In this example, you will see some special syntax that makes it easier
to make a list of strings. This is the
C«<...>» L<quote-words|/language/operators#index-entry-qw-quote-words-quote-words>
construct. When you put words in between the C«<» and C«>» they are all assumed
to be strings, so you do not need to wrap them each in double quotes
C«"..."».
=begin code :preamble<my %sets>
say "Math: { 1 + 2 }";
# OUTPUT: «Math: 3»
my @people = <Luke Matthew Mark>;
say "The synoptics are: {@people}";
# OUTPUT: «The synoptics are: Luke Matthew Mark»
say "{%sets}";
# OUTPUT (From the table tennis tournament):
# Charlie 4
# Dave 6
# Ana 8
# Beth 4
=end code
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 operator E<mdash> a bracketing pair that follows a
statement. It's also ok to have a method call between the variable name and
the postcircumfix.
=head1 Zen slices
=begin code
my @flavors = <vanilla peach>;
say "we have @flavors"; # OUTPUT: «we have @flavors»
say "we have @flavors[0]"; # OUTPUT: «we have vanilla»
# so-called "Zen slice"
say "we have @flavors[]"; # OUTPUT: «we have vanilla peach»
# method calls ending in postcircumfix
say "we have @flavors.sort()"; # OUTPUT: «we have peach vanilla»
# chained method calls:
say "we have @flavors.sort.join(', ')";
# OUTPUT: «we have peach, vanilla»
=end code
=head1 Calling a raku method from another file
To call a raku subroutine from another file, the convention is to have a minimal
raku module or class file.
=begin code
# MyClass.rakumod
class C {
has $.x;
}
=end code
Then your script can C<use> this file.
=begin code :skip-test
# myscript.raku
use MyClass;
my $instance = C.new(x=>42);
say $instance.x;
=end code
The C<-I.> directive tells the raku interpreter to look for modules in directory C<.>.
=begin code :lang<shell>
> raku -I. myscript.raku
=end code
=head1 Exercises
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, 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<Answer:> After removing the first line in C<scores.txt>, remove the line C<my
@names = $file.get.words;> (which would read it), and change:
=begin code :preamble<my @names;my %sets;my %matches>
my @sorted = @names.sort({ %sets{$_} }).sort({ %matches{$_} }).reverse;
=end code
... into:
=begin code :preamble<my %sets;my %matches>
my @sorted = %sets.keys.sort({ %sets{$_} }).sort({ %matches{$_} }).reverse;
=end code
B<2.> Instead of deleting the redundant C<@names> variable, you can also use it
to warn if a player appears that wasn't mentioned in the first line, for
example due to a typo. How would you modify your program to achieve that?
Hint: Try using L<membership operators|/language/operators#infix_(elem),_infix_∈>.
B<Answer:> Change C<@names> to C<@valid-players>. When looping through the
lines of the file, check to see that C<$p1> and C<$p2> are in
C<@valid-players>. Note that for membership operators you can also use C<(elem)>
and C<!(elem)>.
=begin code :preamble<my $file>
...;
my @valid-players = $file.get.words;
...;
for $file.lines -> $line {
my ($pairing, $result) = $line.split(' | ');
my ($p1, $p2) = $pairing.split(' ');
if $p1 ∉ @valid-players {
say "Warning: '$p1' is not on our list!";
}
if $p2 ∉ @valid-players {
say "Warning: '$p2' is not on our list!";
}
...
}
=end code
=end pod
================================================
FILE: doc/Language/REPL.rakudoc
================================================
=begin pod :kind("Language") :subkind("Language") :category("tutorial")
=TITLE REPL
=SUBTITLE Interactive Raku, read-eval-print loop
=head1 Overview
The C<REPL> is an interactive Raku prompt. Each line of code you enter in the C<REPL>
is executed, and if no output was generated, the value returned
by the expression is output.
=head1 Trap
B<Note>: Running code in the C<REPL> is not equivalent to saving the code in a file and
running that. Each line introduces a new scope which can confuse code that has multiple
lines. See C<sub repl()> below for a way to target a REPL inside a larger script.
=head1 Previous Values
As you enter commands into the REPL, each line has a numeric ID associated with it, starting
with C<0>. On subsequent lines, you can use the result with a special variable only available
in the REPL. C<$*0>, C<$*1>, etc. In this example, we calculate two values and then use them
both on the third line.
=begin code :lang<REPL>
✗ raku
Welcome to Rakudo™ v2025.08.
Implementing the Raku® Programming Language v6.d.
Built on MoarVM version 2025.08.
To exit type 'exit' or '^D'
[0] > 3+2
5
[1] > 7+1
8
[2] > $*0 * $*1
40
[3] >
=end code
=head1 non-interactive mode
If invoked from the command line with C<raku --repl-mode=non-interactive>, no history or prompts
are printed, and the code is not executed until you close input (on Linux, for example, you can pipe
the code to it or press C<Control-d>.
=for code :lang<shell>
$ echo "say 3" | raku --repl-mode=non-interactive
3
=head1 sub repl()
This routine allows you to embed a REPL inside a larger script and have access to all
the variables in context.
See L<sub repl()|/type/independent-routines#sub_repl> in Independent Routines for more
information.
=head1 ENVIRONMENT Variables
See L<ENVIRONMENT Variables|/programs/03-environment-variables#Environment_variables_used_by_the_raku_command_line>.
=head2 Get command line history
In a fresh install, there is no command history. Running the C<REPL> in this mode will
prompt you to install one of the various modules that provide this support. If enabled,
you can use the arrow keys to scroll through previous commands and use standard terminal
shortcuts for editing. There are currently four options:
=item 1
=for code :lang<shell>
zef install Terminal::LineEditor
=item 2
=for code :lang<shell>
zef install Linenoise
This requires a working C<C> toolchain.
=item 3
=for code :lang<shell>
zef install Readline
This requires an installation of the C<Readline> development library.
=item 4
An alternative for UNIX-like systems is to install C<rlwrap>. This can
be done on Debian-ish systems by running:
=for code :lang<shell>
sudo apt-get install rlwrap
And then use it to invoke the C<REPL>:
=for code :lang<shell>
rlwrap raku
=end pod
================================================
FILE: doc/Language/about.rakudoc
================================================
=begin pod :kind("Language") :subkind("Language") :category("beginning")
=TITLE About the docs
=SUBTITLE How to locally generate the Raku documentation; and how to contribute to it.
This document collection represents the on-going effort to document the
Raku programming language with the goals of being comprehensive,
easy to use, easy to navigate, and useful to both newcomers and experienced
Raku programmers.
An L<HTML version of the documentation|https://docs.raku.org> is available.
The official source for this documentation is located at
L<Raku/doc on GitHub|https://github.com/Raku/doc>.
=head1 Structure
All of the documentation is written in Raku Pod and kept in the C<doc/>
directory. These files are processed are rendered to HTML, and also
processed into some generated pages, using the C<.rakudoc> files as
sources.
=head1 Generating HTML from Pod
The build process is managed through a separate repository,
L<Raku/doc-website on GitHub|https://github.com/Raku/doc-website>.
=head1 Contributing
For a quick introduction to Raku Pod, see L<Raku Pod|/language/pod>.
For historic details about the Raku Pod specification, see L<Synopsis 26, Documentation|https://github.com/Raku/old-design-docs/blob/master/S26-documentation.pod>.
For information on how to contribute to the documentation, please
read L<CONTRIBUTING.md|https://github.com/Raku/doc/blob/main/CONTRIBUTING.md>.
=end pod
================================================
FILE: doc/Language/brackets.rakudoc
================================================
=begin pod :kind("Language") :subkind("Language") :category("reference")
=TITLE Brackets
=SUBTITLE Valid opening/closing paired delimiters
The following table shows all of the valid graphemes usable as opening
and closing paired delimiters in such constructs as I<Pod6 declarator
blocks>. Note they are shown between pipe symbols so the extra bounding
space for any wide characters can be seen.
The data source for the table is the I<$brackets> string defined in the
I<HLL::Grammar> module in the I<github.com/Raku/nqp> repository.
The data are arranged in the order found in the source string.
Each opening bracket is shown in its printed form followed by its
paired closing bracket. Each pair is then followed by its codepoints.
There are two sets of bracket pairs shown per table row.
=begin table :caption<Bracket pairs>
LChar | RChar | LHex | RHex | LChar | RChar | LHex | RHex
======+======+======+======+======+======+======+======
\|(\| | \|)\| | 0x0028 | 0x0029 | \|<\| | \|>\| | 0x003C | 0x003E
--------+---------+---------+---------+--------+---------+---------+---------
\|[\| | \|]\| | 0x005B | 0x005D | \|{\| | \|}\| | 0x007B | 0x007D
--------+---------+---------+---------+--------+---------+---------+---------
\|«\| | \|»\| | 0x00AB | 0x00BB | \|༺\| | \|༻\| | 0x0F3A | 0x0F3B
--------+---------+---------+---------+--------+---------+---------+---------
\|༼\| | \|༽\| | 0x0F3C | 0x0F3D | \|᚛\| | \|᚜\| | 0x169B | 0x169C
--------+---------+---------+---------+--------+---------+---------+---------
\|‘\| | \|’\| | 0x2018 | 0x2019 | \|‚\| | \|’\| | 0x201A | 0x2019
--------+---------+---------+---------+--------+---------+---------+---------
\|‛\| | \|’\| | 0x201B | 0x2019 | \|“\| | \|”\| | 0x201C | 0x201D
--------+---------+---------+---------+--------+---------+---------+---------
\|„\| | \|”\| | 0x201E | 0x201D | \|‟\| | \|”\| | 0x201F | 0x201D
--------+---------+---------+---------+--------+---------+---------+---------
\|‹\| | \|›\| | 0x2039 | 0x203A | \|⁅\| | \|⁆\| | 0x2045 | 0x2046
--------+---------+---------+---------+--------+---------+---------+---------
\|⁽\| | \|⁾\| | 0x207D | 0x207E | \|₍\| | \|₎\| | 0x208D | 0x208E
--------+---------+---------+---------+--------+---------+---------+---------
\|∈\| | \|∋\| | 0x2208 | 0x220B | \|∉\| | \|∌\| | 0x2209 | 0x220C
--------+---------+---------+---------+--------+---------+---------+---------
\|∊\| | \|∍\| | 0x220A | 0x220D | \|∕\| | \|⧵\| | 0x2215 | 0x29F5
--------+---------+---------+---------+--------+---------+---------+---------
\|∼\| | \|∽\| | 0x223C | 0x223D | \|≃\| | \|⋍\| | 0x2243 | 0x22CD
--------+---------+---------+---------+--------+---------+---------+---------
\|≒\| | \|≓\| | 0x2252 | 0x2253 | \|≔\| | \|≕\| | 0x2254 | 0x2255
--------+---------+---------+---------+--------+---------+---------+---------
\|≤\| | \|≥\| | 0x2264 | 0x2265 | \|≦\| | \|≧\| | 0x2266 | 0x2267
--------+---------+---------+---------+--------+---------+---------+---------
\|≨\| | \|≩\| | 0x2268 | 0x2269 | \|≪\| | \|≫\| | 0x226A | 0x226B
--------+---------+---------+---------+--------+---------+---------+---------
\|≮\| | \|≯\| | 0x226E | 0x226F | \|≰\| | \|≱\| | 0x2270 | 0x2271
--------+---------+---------+---------+--------+---------+---------+---------
\|≲\| | \|≳\| | 0x2272 | 0x2273 | \|≴\| | \|≵\| | 0x2274 | 0x2275
--------+---------+---------+---------+--------+---------+---------+---------
\|≶\| | \|≷\| | 0x2276 | 0x2277 | \|≸\| | \|≹\| | 0x2278 | 0x2279
--------+---------+---------+---------+--------+---------+---------+---------
\|≺\| | \|≻\| | 0x227A | 0x227B | \|≼\| | \|≽\| | 0x227C | 0x227D
--------+---------+---------+---------+--------+---------+---------+---------
\|≾\| | \|≿\| | 0x227E | 0x227F | \|⊀\| | \|⊁\| | 0x2280 | 0x2281
--------+---------+---------+---------+--------+---------+---------+---------
\|⊂\| | \|⊃\| | 0x2282 | 0x2283 | \|⊄\| | \|⊅\| | 0x2284 | 0x2285
--------+---------+---------+---------+--------+---------+---------+---------
\|⊆\| | \|⊇\| | 0x2286 | 0x2287 | \|⊈\| | \|⊉\| | 0x2288 | 0x2289
--------+---------+---------+---------+--------+---------+---------+---------
\|⊊\| | \|⊋\| | 0x228A | 0x228B | \|⊏\| | \|⊐\| | 0x228F | 0x2290
--------+---------+---------+---------+--------+---------+---------+---------
\|⊑\| | \|⊒\| | 0x2291 | 0x2292 | \|⊘\| | \|⦸\| | 0x2298 | 0x29B8
--------+---------+---------+---------+--------+---------+---------+---------
\|⊢\| | \|⊣\| | 0x22A2 | 0x22A3 | \|⊦\| | \|⫞\| | 0x22A6 | 0x2ADE
--------+---------+---------+---------+--------+---------+---------+---------
\|⊨\| | \|⫤\| | 0x22A8 | 0x2AE4 | \|⊩\| | \|⫣\| | 0x22A9 | 0x2AE3
--------+---------+---------+---------+--------+---------+---------+---------
\|⊫\| | \|⫥\| | 0x22AB | 0x2AE5 | \|⊰\| | \|⊱\| | 0x22B0 | 0x22B1
--------+---------+---------+---------+--------+---------+---------+---------
\|⊲\| | \|⊳\| | 0x22B2 | 0x22B3 | \|⊴\| | \|⊵\| | 0x22B4 | 0x22B5
--------+---------+---------+---------+--------+---------+---------+---------
\|⊶\| | \|⊷\| | 0x22B6 | 0x22B7 | \|⋉\| | \|⋊\| | 0x22C9 | 0x22CA
--------+---------+---------+---------+--------+---------+---------+---------
\|⋋\| | \|⋌\| | 0x22CB | 0x22CC | \|⋐\| | \|⋑\| | 0x22D0 | 0x22D1
--------+---------+---------+---------+--------+---------+---------+---------
\|⋖\| | \|⋗\| | 0x22D6 | 0x22D7 | \|⋘\| | \|⋙\| | 0x22D8 | 0x22D9
--------+---------+---------+---------+--------+---------+---------+---------
\|⋚\| | \|⋛\| | 0x22DA | 0x22DB | \|⋜\| | \|⋝\| | 0x22DC | 0x22DD
--------+---------+---------+---------+--------+---------+---------+---------
\|⋞\| | \|⋟\| | 0x22DE | 0x22DF | \|⋠\| | \|⋡\| | 0x22E0 | 0x22E1
--------+---------+---------+---------+--------+---------+---------+---------
\|⋢\| | \|⋣\| | 0x22E2 | 0x22E3 | \|⋤\| | \|⋥\| | 0x22E4 | 0x22E5
--------+---------+---------+---------+--------+---------+---------+---------
\|⋦\| | \|⋧\| | 0x22E6 | 0x22E7 | \|⋨\| | \|⋩\| | 0x22E8 | 0x22E9
--------+---------+---------+---------+--------+---------+---------+---------
\|⋪\| | \|⋫\| | 0x22EA | 0x22EB | \|⋬\| | \|⋭\| | 0x22EC | 0x22ED
--------+---------+---------+---------+--------+---------+---------+---------
\|⋰\| | \|⋱\| | 0x22F0 | 0x22F1 | \|⋲\| | \|⋺\| | 0x22F2 | 0x22FA
--------+---------+---------+---------+--------+---------+---------+---------
\|⋳\| | \|⋻\| | 0x22F3 | 0x22FB | \|⋴\| | \|⋼\| | 0x22F4 | 0x22FC
--------+---------+---------+---------+--------+---------+---------+---------
\|⋶\| | \|⋽\| | 0x22F6 | 0x22FD | \|⋷\| | \|⋾\| | 0x22F7 | 0x22FE
--------+---------+---------+---------+--------+---------+---------+---------
\|⌈\| | \|⌉\| | 0x2308 | 0x2309 | \|⌊\| | \|⌋\| | 0x230A | 0x230B
--------+---------+---------+---------+--------+---------+---------+---------
\|〈\| | \|〉\| | 0x2329 | 0x232A | \|⎴\| | \|⎵\| | 0x23B4 | 0x23B5
--------+---------+---------+---------+--------+---------+---------+---------
\|❨\| | \|❩\| | 0x2768 | 0x2769 | \|❪\| | \|❫\| | 0x276A | 0x276B
--------+---------+---------+---------+--------+---------+---------+---------
\|❬\| | \|❭\| | 0x276C | 0x276D | \|❮\| | \|❯\| | 0x276E | 0x276F
--------+---------+---------+---------+--------+---------+---------+---------
\|❰\| | \|❱\| | 0x2770 | 0x2771 | \|❲\| | \|❳\| | 0x2772 | 0x2773
--------+---------+---------+---------+--------+---------+---------+---------
\|❴\| | \|❵\| | 0x2774 | 0x2775 | \|⟃\| | \|⟄\| | 0x27C3 | 0x27C4
--------+---------+---------+---------+--------+---------+---------+---------
\|⟅\| | \|⟆\| | 0x27C5 | 0x27C6 | \|⟕\| | \|⟖\| | 0x27D5 | 0x27D6
--------+---------+---------+---------+--------+---------+---------+---------
\|⟝\| | \|⟞\| | 0x27DD | 0x27DE | \|⟢\| | \|⟣\| | 0x27E2 | 0x27E3
--------+---------+---------+---------+--------+---------+---------+---------
\|⟤\| | \|⟥\| | 0x27E4 | 0x27E5 | \|⟦\| | \|⟧\| | 0x27E6 | 0x27E7
--------+---------+---------+---------+--------+---------+---------+---------
\|⟨\| | \|⟩\| | 0x27E8 | 0x27E9 | \|⟪\| | \|⟫\| | 0x27EA | 0x27EB
--------+---------+---------+---------+--------+---------+---------+---------
\|⦃\| | \|⦄\| | 0x2983 | 0x2984 | \|⦅\| | \|⦆\| | 0x2985 | 0x2986
--------+---------+---------+---------+--------+---------+---------+---------
\|⦇\| | \|⦈\| | 0x2987 | 0x2988 | \|⦉\| | \|⦊\| | 0x2989 | 0x298A
--------+---------+---------+---------+--------+---------+---------+---------
\|⦋\| | \|⦌\| | 0x298B | 0x298C | \|⦍\| | \|⦐\| | 0x298D | 0x2990
--------+---------+---------+---------+--------+---------+---------+---------
\|⦏\| | \|⦎\| | 0x298F | 0x298E | \|⦑\| | \|⦒\| | 0x2991 | 0x2992
--------+---------+---------+---------+--------+---------+---------+---------
\|⦓\| | \|⦔\| | 0x2993 | 0x2994 | \|⦕\| | \|⦖\| | 0x2995 | 0x2996
--------+---------+---------+---------+--------+---------+---------+---------
\|⦗\| | \|⦘\| | 0x2997 | 0x2998 | \|⧀\| | \|⧁\| | 0x29C0 | 0x29C1
--------+---------+---------+---------+--------+---------+---------+---------
\|⧄\| | \|⧅\| | 0x29C4 | 0x29C5 | \|⧏\| | \|⧐\| | 0x29CF | 0x29D0
--------+---------+---------+---------+--------+---------+---------+---------
\|⧑\| | \|⧒\| | 0x29D1 | 0x29D2 | \|⧔\| | \|⧕\| | 0x29D4 | 0x29D5
--------+---------+---------+---------+--------+---------+---------+---------
\|⧘\| | \|⧙\| | 0x29D8 | 0x29D9 | \|⧚\| | \|⧛\| | 0x29DA | 0x29DB
--------+---------+---------+---------+--------+---------+---------+---------
\|⧸\| | \|⧹\| | 0x29F8 | 0x29F9 | \|⧼\| | \|⧽\| | 0x29FC | 0x29FD
--------+---------+---------+---------+--------+---------+---------+---------
\|⨫\| | \|⨬\| | 0x2A2B | 0x2A2C | \|⨭\| | \|⨮\| | 0x2A2D | 0x2A2E
--------+---------+---------+---------+--------+---------+---------+---------
\|⨴\| | \|⨵\| | 0x2A34 | 0x2A35 | \|⨼\| | \|⨽\| | 0x2A3C | 0x2A3D
--------+---------+---------+---------+--------+---------+---------+---------
\|⩤\| | \|⩥\| | 0x2A64 | 0x2A65 | \|⩹\| | \|⩺\| | 0x2A79 | 0x2A7A
--------+---------+---------+---------+--------+---------+---------+---------
\|⩽\| | \|⩾\| | 0x2A7D | 0x2A7E | \|⩿\| | \|⪀\| | 0x2A7F | 0x2A80
--------+---------+---------+---------+--------+---------+---------+---------
\|⪁\| | \|⪂\| | 0x2A81 | 0x2A82 | \|⪃\| | \|⪄\| | 0x2A83 | 0x2A84
--------+---------+---------+---------+--------+---------+---------+---------
\|⪋\| | \|⪌\| | 0x2A8B | 0x2A8C | \|⪑\| | \|⪒\| | 0x2A91 | 0x2A92
--------+---------+---------+---------+--------+---------+---------+---------
\|⪓\| | \|⪔\| | 0x2A93 | 0x2A94 | \|⪕\| | \|⪖\| | 0x2A95 | 0x2A96
--------+---------+---------+---------+--------+---------+---------+---------
\|⪗\| | \|⪘\| | 0x2A97 | 0x2A98 | \|⪙\| | \|⪚\| | 0x2A99 | 0x2A9A
--------+---------+---------+---------+--------+---------+---------+---------
\|⪛\| | \|⪜\| | 0x2A9B | 0x2A9C | \|⪡\| | \|⪢\| | 0x2AA1 | 0x2AA2
--------+---------+---------+---------+--------+---------+---------+---------
\|⪦\| | \|⪧\| | 0x2AA6 | 0x2AA7 | \|⪨\| | \|⪩\| | 0x2AA8 | 0x2AA9
--------+---------+---------+---------+--------+---------+---------+---------
\|⪪\| | \|⪫\| | 0x2AAA | 0x2AAB | \|⪬\| | \|⪭\| | 0x2AAC | 0x2AAD
--------+---------+---------+---------+--------+---------+---------+---------
\|⪯\| | \|⪰\| | 0x2AAF | 0x2AB0 | \|⪳\| | \|⪴\| | 0x2AB3 | 0x2AB4
--------+---------+---------+---------+--------+---------+---------+---------
\|⪻\| | \|⪼\| | 0x2ABB | 0x2ABC | \|⪽\| | \|⪾\| | 0x2ABD | 0x2ABE
--------+---------+---------+---------+--------+---------+---------+---------
\|⪿\| | \|⫀\| | 0x2ABF | 0x2AC0 | \|⫁\| | \|⫂\| | 0x2AC1 | 0x2AC2
--------+---------+---------+---------+--------+---------+---------+---------
\|⫃\| | \|⫄\| | 0x2AC3 | 0x2AC4 | \|⫅\| | \|⫆\| | 0x2AC5 | 0x2AC6
--------+---------+---------+---------+--------+---------+---------+---------
\|⫍\| | \|⫎\| | 0x2ACD | 0x2ACE | \|⫏\| | \|⫐\| | 0x2ACF | 0x2AD0
--------+---------+---------+---------+--------+---------+---------+---------
\|⫑\| | \|⫒\| | 0x2AD1 | 0x2AD2 | \|⫓\| | \|⫔\| | 0x2AD3 | 0x2AD4
--------+---------+---------+---------+--------+---------+---------+---------
\|⫕\| | \|⫖\| | 0x2AD5 | 0x2AD6 | \|⫬\| | \|⫭\| | 0x2AEC | 0x2AED
--------+---------+---------+---------+--------+---------+---------+---------
\|⫷\| | \|⫸\| | 0x2AF7 | 0x2AF8 | \|⫹\| | \|⫺\| | 0x2AF9 | 0x2AFA
--------+---------+---------+---------+--------+---------+---------+---------
\|⸂\| | \|⸃\| | 0x2E02 | 0x2E03 | \|⸄\| | \|⸅\| | 0x2E04 | 0x2E05
--------+---------+---------+---------+--------+---------+---------+---------
\|⸉\| | \|⸊\| | 0x2E09 | 0x2E0A | \|⸌\| | \|⸍\| | 0x2E0C | 0x2E0D
--------+---------+---------+---------+--------+---------+---------+---------
\|⸜\| | \|⸝\| | 0x2E1C | 0x2E1D | \|⸠\| | \|⸡\| | 0x2E20 | 0x2E21
--------+---------+---------+---------+--------+---------+---------+---------
\|⸨\| | \|⸩\| | 0x2E28 | 0x2E29 | \|〈\| | \|〉\| | 0x3008 | 0x3009
--------+---------+---------+---------+--------+---------+---------+---------
\|《\| | \|》\| | 0x300A | 0x300B | \|「\| | \|」\| | 0x300C | 0x300D
--------+---------+---------+---------+--------+---------+---------+---------
\|『\| | \|』\| | 0x300E | 0x300F | \|【\| | \|】\| | 0x3010 | 0x3011
--------+---------+---------+---------+--------+---------+---------+---------
\|〔\| | \|〕\| | 0x3014 | 0x3015 | \|〖\| | \|〗\| | 0x3016 | 0x3017
--------+---------+---------+---------+--------+---------+---------+---------
\|〘\| | \|〙\| | 0x3018 | 0x3019 | \|〚\| | \|〛\| | 0x301A | 0x301B
--------+---------+---------+---------+--------+---------+---------+---------
\|〝\| | \|〞\| | 0x301D | 0x301E | \|︗\| | \|︘\| | 0xFE17 | 0xFE18
--------+---------+---------+---------+--------+---------+---------+---------
\|︵\| | \|︶\| | 0xFE35 | 0xFE36 | \|︷\| | \|︸\| | 0xFE37 | 0xFE38
--------+---------+---------+---------+--------+---------+---------+---------
\|︹\| | \|︺\| | 0xFE39 | 0xFE3A | \|︻\| | \|︼\| | 0xFE3B | 0xFE3C
--------+---------+---------+---------+--------+---------+---------+---------
\|︽\| | \|︾\| | 0xFE3D | 0xFE3E | \|︿\| | \|﹀\| | 0xFE3F | 0xFE40
--------+---------+---------+---------+--------+---------+---------+---------
\|﹁\| | \|﹂\| | 0xFE41 | 0xFE42 | \|﹃\| | \|﹄\| | 0xFE43 | 0xFE44
--------+---------+---------+---------+--------+---------+---------+---------
\|﹇\| | \|﹈\| | 0xFE47 | 0xFE48 | \|﹙\| | \|﹚\| | 0xFE59 | 0xFE5A
--------+---------+---------+---------+--------+---------+---------+---------
\|﹛\| | \|﹜\| | 0xFE5B | 0xFE5C | \|﹝\| | \|﹞\| | 0xFE5D | 0xFE5E
--------+---------+---------+---------+--------+---------+---------+---------
\|(\| | \|)\| | 0xFF08 | 0xFF09 | \|<\| | \|>\| | 0xFF1C | 0xFF1E
--------+---------+---------+---------+--------+---------+---------+---------
\|[\| | \|]\| | 0xFF3B | 0xFF3D | \|{\| | \|}\| | 0xFF5B | 0xFF5D
--------+---------+---------+---------+--------+---------+---------+---------
\|⦅\| | \|⦆\| | 0xFF5F | 0xFF60 | \|「\| | \|」\| | 0xFF62 | 0xFF63
--------+---------+---------+---------+--------+---------+---------+---------
\|⟮\| | \|⟯\| | 0x27EE | 0x27EF | \|⸤\| | \|⸥\| | 0x2E24 | 0x2E25
--------+---------+---------+---------+--------+---------+---------+---------
\|⟬\| | \|⟭\| | 0x27EC | 0x27ED | \|⸢\| | \|⸣\| | 0x2E22 | 0x2E23
--------+---------+---------+---------+--------+---------+---------+---------
\|⸦\| | \|⸧\| | 0x2E26 | 0x2E27 | | | |
--------+---------+---------+---------+--------+---------+---------+---------
=end table
Z<This file was created by program '/util/create-brackets-table.raku'>
=end pod
================================================
FILE: doc/Language/classtut.rakudoc
================================================
=begin pod :kind("Language") :subkind("Language") :category("tutorial")
=TITLE Classes and objects
=SUBTITLE A tutorial about creating and using classes in Raku
X<|Tutorial,OOP>
Raku provides a rich built-in syntax for defining and using classes. It makes writing classes
expressive and short for most cases, but also provides mechanisms to cover
the rare corner cases.
=head1 A quick overview
Let's start with an example to give an overview:
=begin code
class Rectangle {
has Int $.length = 1;
has Int $.width = 1;
method area(--> Int) {
return $!length * $!width;
}
}
my $r1 = Rectangle.new(length => 2, width => 3);
say $r1.area(); # OUTPUT: «6»
=end code
We define a new I<Rectangle> class using the L<class|/language/objects#Classes> keyword. It has two L<attributes|#Attributes>, C<$!length> and C<$!width> introduced
with the L<has|/syntax/has> keyword. Both default to C<1>. Read only accessor methods are automatically generated. (Note the C<.> instead of C<!> in the declaration, which triggers the generation. Mnemonic: C<!> resembles a closed door, C<.> an open one.)
The L<method|/language/objects#Methods> named C<area> will return the area of the rectangle.
It is rarely necessary to explicitly write a constructor. An automatically inherited default constructor called L<new|/language/objects#Object_construction> will automatically initialize attributes from named parameters passed to the constructor.
=head1 The Task example
As a more elaborate example the following piece of code implements a dependency
handler. It showcases custom constructors, private and public attributes,
methods, and various aspects of signatures. It's not a lot of code, and yet the
result is interesting and useful. It will be used as an example throughout the
following sections.
=begin code
class Task {
has &!callback is built;
has Task @!dependencies is built;
has Bool $.done;
method new(&callback, *@dependencies) {
return self.bless(:&callback, :@dependencies);
}
method add-dependency(Task $dependency) {
push @!dependencies, $dependency;
}
method perform() {
unless $!done {
.perform() for @!dependencies;
&!callback();
$!done = True;
}
}
}
my $eat =
Task.new({ say 'eating dinner. NOM!' },
Task.new({ say 'making dinner' },
Task.new({ say 'buying food' },
Task.new({ say 'making some money' }),
Task.new({ say 'going to the store' })
),
Task.new({ say 'cleaning kitchen' })
)
);
$eat.perform();
=end code
=head1 X<Class|Tutorial,class>
X<|Tutorial,state>
Raku, like many other languages, uses the C<class> keyword to define a
class. The block that follows may contain arbitrary code, just as with
any other block, but classes commonly contain state and behavior
declarations. The example code includes attributes (state), introduced
through the C<has> keyword, and behaviors, introduced through the C<method>
keyword.
=head1 X<Attributes|Tutorial,attributes>
X<|Tutorial,encapsulation>
X<|Tutorial,has>
In the C<Task> class, the first three lines inside the block all
declare attributes (called I<fields> or I<instance storage> in other
languages) using the C<has> declarator. Just as a C<my> variable cannot be
accessed from outside its declared scope, attributes are never directly
accessible from outside of the class (this is in contrast to many other
languages). This I<encapsulation> is one of the key principles of object
oriented design.
=head2 X<Twigil C<$!>|Tutorial,twigils>
X<|Tutorial,!>
X<|Tutorial,&>
The first declaration specifies instance storage for a callback (i.e.
a bit of code to invoke in order to perform the task that an object
represents):
=for code
has &!callback is built;
The C<&> sigil indicates that this attribute represents something invocable.
The C<!> character is a I<twigil>, or secondary sigil. A twigil forms part
of the name of the variable. In this case, the C<!> twigil emphasizes that
this attribute is private to the class. The attribute is I<encapsulated>.
Private attributes will not be set by the default constructor by default, which is
why we add the C<is built> trait to allow just that. Mnemonic: C<!> looks like a closed door.
The second declaration also uses the private twigil:
=for code :preamble<class Task {}>
has Task @!dependencies is built;
However, this attribute represents an array of items, so it requires the
C<@> sigil. These items each specify a task that must be completed before
the present one is completed. Furthermore, the type declaration on this
attribute indicates that the array may only hold instances of the C<Task>
class (or some subclass of it).
X<|Tutorial,.>
X<|Tutorial,accessors>
X<|Tutorial,accessor methods>
=head2 Twigil C<$.>
The third attribute represents the state of completion of a task:
=for code
has Bool $.done;
This scalar attribute (with the C<$> sigil) has a type of L<C<Bool>|/type/Bool>. Instead
of the C<!> twigil, the C<.> twigil is used. While Raku does enforce
encapsulation on attributes, it also saves you from writing accessor
methods. Replacing the C<!> with a C<.> both declares a private attribute
and an accessor method named after the attribute. In this case,
both the attribute C<$!done> and the accessor method C<done> are declared.
It's as if you had written:
=begin code
has Bool $!done;
method done() { return $!done }
=end code
Note that this is not like declaring a public attribute, as some languages
allow; you really get I<both> a private attribute and a method,
without having to write the method by hand. You are free instead to write
your own accessor method, if at some future point you need to do something
more complex than returning the value.
=head2 X<C<is rw> trait|Tutorial,is rw>
Note that using the C<.> twigil has created a method that will provide
read-only access to the attribute. If instead the users of this object
should be able to reset a task's completion state (perhaps to perform it
again), you can change the attribute declaration:
=for code
has Bool $.done is rw;
The L<C<is rw>|/type/Attribute#trait_is_rw> trait causes the generated accessor method to return a container
so external code can modify the value of the attribute.
=head2 C<is built> trait
=for code
has &!callback is built;
X<|Types,traits>
X<|Types,is built>
By default private attributes are not automatically set by the default constructor. (They are private after
all.) In the above example we want to allow the user to provide the initial value but keep the attribute
otherwise private. The L<C<is built>|/type/Attribute#trait_is_built> trait allows to do just that.
One can use the same trait C<is built> to do the opposite for public attributes, i.e. prevent them from being
automatically initialized with a user-provided value, but still generate the accessor method. This is done by giving
the argument C<False> to the trait:
=for code
has $.done is built(False);
Above declaration makes sure one can't construct finished tasks, but still allow users to look if a task is done.
The C<is built> trait was introduced in Rakudo release 2020.01.
=head2 C<is required> trait
X<|Types,traits>
X<|Types,is required>
Providing a value for an attribute during initialization is optional by default. Which in the task example
makes sense for all three, the C<&!callback>, the C<@!dependencies> and the C<$.done> attribute. But lets say
we want to add another attribute, C<$.name>, that holds a tasks name and we want to force the user to
provide a value on initialization. We can do that as follows:
=for code
has $.name is required;
=head2 Default values
You can also supply default values to attributes (which works equally for
those with and without accessors):
=for code
has Bool $.done = False;
The assignment is carried out at object build time. The right-hand side is
evaluated at that time, and can even reference earlier attributes:
=begin code :preamble<class Task {}>
has Task @!dependencies;
has $.ready = not @!dependencies;
=end code
Writable attributes are accessible through writable containers:
=begin code
class a-class {
has $.an-attribute is rw;
}
say (a-class.new.an-attribute = "hey"); # OUTPUT: «hey»
=end code
This attribute can also be accessed using the C<.an-attribute> or
C<.an-attribute()> syntax. See also
L<the C<is rw> trait on classes|/language/typesystem#trait_is_rw> for examples
on how this works on the whole class.
X<|Tutorial,class variables>
=head1 Class variables
A class declaration can also include I<class variables>, declared with C<my> or C<our>, which are variables
whose value is shared by all instances, and can be used for things like
counting the number of instantiations or any other shared state. So I<class variables> act similarly to
I<static> variables known from other programming languages.
They look the same as normal (non class) lexical variables (and in fact they are the same):
=begin code
class Str-with-ID is Str {
my $counter = 0;
our $our-counter = 0;
has Str $.string;
has Int $.ID is built(False);
submethod TWEAK() {
$counter++;
$our-counter++;
$!ID = $counter;
}
}
class Str-with-ID-and-tag is Str-with-ID {
has Str $.tag;
}
say Str-with-ID.new(string => 'First').ID; # OUTPUT: «1»
say Str-with-ID.new(string => 'Second').ID; # OUTPUT: «2»
say Str-with-ID-and-tag.new( string => 'Third', tag => 'Ordinal' ).ID; # OUTPUT: «3»
say $Str-with-ID::our-counter; # OUTPUT: «3»
=end code
I<Class variables> are shared by all subclasses, in this case
C<Str-with-ID-and-tag>. Additionally, when the package scope C<our> declarator
is used, the variable is visible via their fully qualified name (FQN), while
lexically scoped C<my> variables are "private". This is the exact behavior that
C<my> and C<our> also show in non class context.
X<|Types,static>
I<Class variables> act similarly to I<static> variables in many other programming
languages.
=begin code
class Singleton {
my Singleton $instance;
method new {!!!}
submethod instance {
$instance = Singleton.bless unless $instance;
$instance;
}
}
=end code
In this implementation of the I<Singleton> pattern a I<class variable> is used
to save the instance.
=begin code
class HaveStaticAttr {
my Int $.foo = 5;
}
=end code
Class attributes may also be declared with a secondary sigil – in a similar
manner to instance attributes – that will generate read-only accessors if the
attribute is to be public.
Default values behave as expected and are assigned only once.
=head1 Methods
X<|Tutorial,methods>
While attributes give objects state, methods give objects behaviors. Back to our C<Task> example. Let's
ignore the C<new> method temporarily; it's a special type of method.
Consider the second method, C<add-dependency>, which adds a new task to a
task's dependency list:
=begin code :skip-test<incomplete code>
method add-dependency(Task $dependency) {
push @!dependencies, $dependency;
}
=end code
X<|Tutorial,invocant>
In many ways, this looks a lot like a C<sub> declaration. However, there are
two important differences. First, declaring this routine as a method adds it
to the list of methods for the current class, thus any instance of the
C<Task> class can call it with the C<.> method call operator.
Second, a method places its invocant into the special variable C<self>.
The method itself takes the passed parameter – which must be an instance of
the C<Task> class – and C<push>es it onto the invocant's C<@!dependencies>
attribute.
The C<perform> method contains the main logic of the dependency handler:
=begin code :skip-test<incomplete code>
method perform() {
unless $!done {
.perform() for @!dependencies;
&!callback();
$!done = True;
}
}
=end code
It takes no parameters, working instead with the object's attributes. First,
it checks if the task has already completed by checking the C<$!done>
attribute. If so, there's nothing to do.
Otherwise, the method performs all of the task's dependencies, using the
C<for> construct to iterate over all of the items in the C<@!dependencies>
attribute. This iteration places each item – each a C<Task> object – into
the topic variable, C<$_>. Using the C<.> method call operator without
specifying an explicit invocant uses the current topic as the invocant.
Thus the iteration construct calls the C<.perform()> method on every C<Task>
object in the C<@!dependencies> attribute of the current invocant.
After all of the dependencies have completed, it's time to perform the
current C<Task>'s task by invoking the C<&!callback> attribute directly;
this is the purpose of the parentheses. Finally, the method sets the
C<$!done> attribute to C<True>, so that subsequent invocations of C<perform>
on this object (if this C<Task> is a dependency of another C<Task>, for
example) will not repeat the task.
=head2 X<Private methods|Tutorial,FQN>
X<|Tutorial,Private methods>
Just like attributes, methods can also be private. Private methods are declared
with a prefixed exclamation mark. They are called with C<self!> followed by the
method's name. In the following implementation of a C<MP3TagData> class to
extract L<ID3v1|https://en.wikipedia.org/wiki/ID3> metadata from an mp3 file,
methods C<parse-data>, C<can-read-format>, and C<trim-nulls> 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<C<trusts>|/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 {...}
class C {
trusts B;
has $!hidden = 'invisible';
method !not-yours () { say 'hidden' }
method yours-to-use () {
say $!hidden;
self!not-yours();
}
}
class B {
method i-am-trusted () {
my C $c.=new;
$c!C::not-yours();
}
}
C.new.yours-to-use(); # the context of this call is GLOBAL, and not trusted by C
B.new.i-am-trusted();
=end code
Trust relationships are not subject to inheritance. To trust the global
namespace, the pseudo package C<GLOBAL> can be used.
=head1 X<Construction|Tutorial,Constructor>
The object construction mechanisms described up to now suffice for most use cases. But if one actually needs
to tweak object construction more than said mechanisms allow, it's good to understand how object construction
works in more detail.
Raku is rather more liberal than many languages in the area of
constructors. A constructor is anything that returns an instance of the
class. Furthermore, constructors are ordinary methods. You inherit a
default constructor named C<new> from the base class L<C<Mu>|/type/Mu>, but you are
free to override C<new>, as the Task example does:
=begin code
method new(&callback, *@dependencies) {
return self.bless(:&callback, :@dependencies);
}
=end code
X<|Tutorial,bless>
=head2 bless
The biggest difference between constructors in Raku and constructors in
languages such as C# and Java is that rather than setting up state on a
somehow already magically created object, Raku constructors create the
object themselves. They do this by calling the
L<bless|/routine/bless> method, also inherited from L<C<Mu>|/type/Mu>.
The C<bless> method expects a set of named parameters to provide the initial
values for each attribute.
The example's constructor turns positional arguments into named arguments,
so that the class can provide a nicer constructor for its users. The first
parameter is the callback (the thing which will execute the task). The rest
of the parameters are dependent C<Task> instances. The constructor captures
these into the C<@dependencies> slurpy array and passes them as named
parameters to C<bless> (note that C<:&callback> uses the name of the
variable – minus the sigil – as the name of the parameter).
One should refrain from putting logic other than reformulating the parameters in the constructor, because
constructor methods are not recursively called for parent classes. This is different from e.g. Java.
Declaring C<new> as a C<method> and not as a C<multi method> prevents access to the default constructor.
+So if you intend to keep the default constructor available, use C<multi method new>.
=head2 X<C<TWEAK>|Tutorial,TWEAK>
After C<bless> has initialized the classes attributes from the passed values, it will in turn call C<TWEAK>
for each class in the inheritance hierarchy.
C<TWEAK> gets passed all the arguments passed to bless.
This is where custom initialization logic should go.
Remember to always make C<TWEAK> a L<submethod|/type/Submethod> and not a normal C<method>. If in a class hierarchy a class contains a C<TWEAK> method (declared as a C<method> instead of a C<submethod>) that method is inherited to its subclass and will thus be called twice during construction of the subclass!
=head2 X<C<BUILD>|Tutorial,BUILD>
It is possible to disable the automatic attribute initialization and perform the initialization of
attributes oneself. To do so one needs to write a custom C<BUILD> submethod. There are several edge cases one
needs to be aware of and take into account though. This is detailed in the
L<Object Construction Reference|/language/objects#Object_construction>. Because of the difficulty of using
C<BUILD>, it is recommended to only make use of it when none of the other approaches described above suffices.
X<|Tutorial,submethod DESTROY>
=head1 X<Destruction|Tutorial,DESTROY>
Raku is a garbage collecting language. This means that one usually doesn't need to care about cleaning up objects,
because Raku does so automatically. Raku does not give any guarantees as to when it will
clean up a given object though. It usually does a cleanup run only if the runtime needs the memory, so we
can't rely on when it's going to happen.
To run custom code when an object is cleaned up one can use the C<DESTROY> submethod. It can for example be used to close handles or supplies or delete temporary files that are no longer
going to be used. As garbage collection can happen at arbitrary points during the runtime of our program, even in the middle of some totally unrelated piece of code in a different thread, we
must make sure to not assume any context in our C<DESTROY> submethod.
=begin code
my $in_destructor = 0;
class Foo {
submethod DESTROY { $in_destructor++ }
}
my $foo;
for 1 .. 6000 {
$foo = Foo.new();
}
say "DESTROY called $in_destructor times";
=end code
This might print something like C<DESTROY called 5701 times> and possibly only kicks
in after we have stomped over former instances of C<Foo> a few thousand times. We also can't
rely, on the order of destruction.
Same as C<TWEAK>: Make sure to always declare C<DESTROY> as a C<submethod>.
=head1 Consuming our class
After creating a class, you can create instances of the class. Declaring a
custom constructor provides a simple way of declaring tasks along with their
dependencies. To create a single task with no dependencies, write:
=for code :preamble<class Task {}>
my $eat = Task.new({ say 'eating dinner. NOM!' });
An earlier section explained that declaring the class C<Task> installed a
type object in the namespace. This type object is a kind of "empty
instance" of the class, specifically an instance without any state. You can
call methods on that instance, as long as they do not try to access any
state; C<new> is an example, as it creates a new object rather than
modifying or accessing an existing object.
Unfortunately, dinner never magically happens. It has dependent tasks:
=begin code :preamble<class Task {}>
my $eat =
Task.new({ say 'eating dinner. NOM!' },
Task.new({ say 'making dinner' },
Task.new({ say 'buying food' },
Task.new({ say 'making some money' }),
Task.new({ say 'going to the store' })
),
Task.new({ say 'cleaning kitchen' })
)
);
=end code
Notice how the custom constructor and the sensible use of whitespace makes
task dependencies clear.
Finally, the C<perform> method call recursively calls the C<perform> method
on the various other dependencies in order, giving the output:
=begin code :lang<output>
making some money
going to the store
buying food
cleaning kitchen
making dinner
eating dinner. NOM!
=end code
=head2 X<A word on types|Tutorial,type object>
X<|Tutorial,DEFINITE>
Declaring a class creates a new I<type object> which, by default, is installed
into the current package (just like a variable declared with C<our> scope).
This type object is an "empty instance" of the class. For example, types such as
L<C<Int>|/type/Int> and L<C<Str>|/type/Str> refer to the type object of one of the Raku built-in
classes. One can call methods on these type objects. So there is nothing special
with calling the C<new> method on a type object.
You can use the C<.DEFINITE> method to find out if what you have is an instance
or a type object:
=begin code
say Int.DEFINITE; # OUTPUT: «False» (type object)
say 426.DEFINITE; # OUTPUT: «True» (instance)
class Foo {};
say Foo.DEFINITE; # OUTPUT: «False» (type object)
say Foo.new.DEFINITE; # OUTPUT: «True» (instance)
=end code
In function signatures one can use so called type "smileys" to only accept instances
or type objects:
=begin code
multi foo (Int:U) { "It's a type object!" }
multi foo (Int:D) { "It's an instance!" }
say foo Int; # OUTPUT: «It's a type object!»
say foo 42; # OUTPUT: «It's an instance!»
=end code
=head1 X<Inheritance|Tutorial,inheritance>
Object Oriented Programming provides the concept of inheritance as one of
the mechanisms for code reuse. Raku supports the ability for one
class to inherit from one or more classes. When a class inherits from
another class it informs the method dispatcher to follow the inheritance
chain to look for a method to dispatch. This happens both for standard
methods defined via the C<method> keyword and for methods generated through
other means, such as attribute accessors.
=begin code
class Employee {
has $.salary;
}
class Programmer is Employee {
has @.known_languages is rw;
has $.favorite_editor;
method code_to_solve( $problem ) {
return "Solving $problem using $.favorite_editor in "
~ $.known_languages[0];
}
}
=end code
Now, any object of type Programmer can make use of the methods and accessors
defined in the Employee class as though they were from the Programmer class.
=begin code :preamble<class Programmer {}>
my $programmer = Programmer.new(
salary => 100_000,
known_languages => <Raku Perl Erlang C++>,
favorite_editor => 'vim'
);
say $programmer.code_to_solve('halting problem'),
" will get \$ {$programmer.salary()}";
# OUTPUT: «Solving halting problem using vim in Raku will get $100000»
=end code
=head2 Overriding inherited methods
Classes can override methods and attributes defined by parent
classes by defining their own. The example below demonstrates the C<Baker>
class overriding the C<Cook>'s C<cook> method.
=begin code :preamble<class Employee {}>
class Cook is Employee {
has @.utensils is rw;
has @.cookbooks is rw;
method cook( $food ) {
say "Cooking $food";
}
method clean_utensils {
say "Cleaning $_" for @.utensils;
}
}
class Baker is Cook {
method cook( $confection ) {
say "Baking a tasty $confection";
}
}
my $cook = Cook.new(
utensils => <spoon ladle knife pan>,
cookbooks => 'The Joy of Cooking',
salary => 40000
);
$cook.cook( 'pizza' ); # OUTPUT: «Cooking pizza»
say $cook.utensils.raku; # OUTPUT: «["spoon", "ladle", "knife", "pan"]»
say $cook.cookbooks.raku; # OUTPUT: «["The Joy of Cooking"]»
say $cook.salary; # OUTPUT: «40000»
my $baker = Baker.new(
utensils => 'self cleaning oven',
cookbooks => "The Baker's Apprentice",
salary => 50000
);
$baker.cook('brioche'); # OUTPUT: «Baking a tasty brioche»
say $baker.utensils.raku; # OUTPUT: «["self cleaning oven"]»
say $baker.cookbooks.raku; # OUTPUT: «["The Baker's Apprentice"]»
say $baker.salary; # OUTPUT: «50000»
=end code
Because the dispatcher will see the C<cook> method on C<Baker> before it
moves up to the parent class the C<Baker>'s C<cook> method will be called.
To access methods in the inheritance chain, use
L<re-dispatch|/language/functions#Re-dispatching> or the
L<MOP|/type/Metamodel::ClassHOW#method_can>.
=head2 Multiple inheritance
As mentioned before, a class can inherit from multiple classes. When a
class inherits from multiple classes the dispatcher knows to look at both
classes when looking up a method to search for. Raku uses the
L<C3 algorithm|https://en.wikipedia.org/wiki/Multiple_inheritance> to linearize
multiple inheritance hierarchies, which is better than depth-first search
for handling multiple inheritance.
=begin code :preamble<class Programmer {}; class Cook {}>
class GeekCook is Programmer is Cook {
method new( *%params ) {
push( %params<cookbooks>, "Cooking for Geeks" );
return self.bless(|%params);
}
}
my $geek = GeekCook.new(
books => 'Learning Raku',
utensils => ('stainless steel pot', 'knife', 'calibrated oven'),
favorite_editor => 'MacVim',
known_languages => <Raku>
);
$geek.cook('pizza');
$geek.code_to_solve('P =? NP');
=end code
Now all the methods made available to the Programmer and the Cook classes
are available from the GeekCook class.
While multiple inheritance is a useful concept to know and occasionally use,
it is important to understand that there are more useful OOP concepts. When
reaching for multiple inheritance it is good practice to consider whether
the design wouldn't be better realized by using roles, which are generally
safer because they force the class author to explicitly resolve conflicting
method names. For more information on roles, see
L<Roles|/language/objects#Roles>.
=head2 The X<C<also>|Tutorial,also declarator> declarator
Classes to be inherited from can be listed in the class declaration body by
prefixing the C<is> trait with C<also>. This also works for the role
composition trait C<does>.
=begin code :preamble<class Programmer {}; class Cook {}>
class GeekCook {
also is Programmer;
also is Cook;
# ...
}
role A {};
role B {};
class C {
also does A;
also does B;
# ...
}
=end code
=head1 Introspection
Introspection is the process of gathering information about some objects in
your program, not by reading the source code, but by querying the object (or
a controlling object) for some properties, such as its type.
Given an object C<$o> and the class definitions from the previous sections,
we can ask it a few questions:
=begin code :preamble<class Programmer {}; class Employee {}; class GeekCook {}>
my Programmer $o .= new;
if $o ~~ Employee { say "It's an employee" };
say $o ~~ GeekCook ?? "It's a geeky cook" !! "Not a geeky cook";
say $o.^name;
say $o.raku;
say $o.^methods(:local)».name.join(', ');
=end code
The output might look like this:
=begin code :lang<output>
It's an employee
Not a geeky cook
Programmer
Programmer.new(known_languages => ["Perl", "Python", "Pascal"],
favorite_editor => "gvim", salary => "too small")
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 C<True>. So the object in
question is of class C<Employee> or one that inherits from it, but not
C<GeekCook>.
The call C<$o.^name> tells us the type of C<$o>; in this case C<Programmer>.
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
all cases, it is very useful for debugging simple objects.
N<For example, closures cannot easily be reproduced this way; if you
don't know what a closure is don't worry. Also current implementations have
problems with dumping cyclic data structures this way, but they are expected
to be handled correctly by C<.raku> at some point.>
The syntax of calling a method with C<.^> instead of a single dot means that
it is actually a method call on its I<metaclass>, which is a class managing
the properties of the C<Programmer> class – or any other class you are
interested in. This metaclass enables other ways of introspection too:
=for code :preamble<my $o>
say $o.^attributes.join(', ');
say $o.^parents.map({ $_.^name }).join(', ');
Finally C<$o.^name> calls the C<name> method on the metaobject, which
unsurprisingly returns the class name.
Given an object C<$mp3> and the C<MP3TagData> class definition from the section
L<Private methods|/language/classtut#Private_methods>, we can inquire about its
public methods with C<.^methods>:
=begin code :skip-test<compile time error>
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<|Syntax,^methods>
C<$mp3.^methods(:local)> produces a list of L<C<Method>|/type/Method>s that can be
called on C<$mp3>. The C<:local> named argument limits the returned methods to
those defined in the C<MP3TagData> class and excludes the inherited methods;
C<MP3TagData> inherits from no class, so providing C<:local> makes no difference.
X<|Language,find_method>
To check if a type object (or an instance object) implements a certain public
method, use the L<C<.^find-method>|/routine/find_method> metamethod, which
returns the method object if it exists. Otherwise, it returns L<C<Mu>|/type/Mu>.
=begin code :skip-test<compile time error>
say $mp3.^find_method('name'); # OUTPUT: «(Mu)»
say $mp3.^find_method('artist'); # OUTPUT: «artist»
=end code
X<|Language,private_methods>
X<|Language,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<C<.^private_methods>|/routine/private_methods> and
L<C<.^find_private_method>|/routine/find_private_method>.
=begin code :skip-test<compile time error>
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
for it with C<.raku>, and so on, you'll get a good idea of what its return
value is. With C<.^methods>, you can learn what you can do with the class.
But there are other applications too. For instance, a routine that serializes
objects to a bunch of bytes needs to know the attributes of that object,
which it can find out via introspection.
=head2 X<Overriding default gist method|Reference,Overriding default gist method>
Some classes might need their own version of C<gist>, which overrides the terse
way they are printed when called to provide a default representation of the class.
For instance, L<exceptions|/language/exceptions#Uncaught_exceptions> might want
to write just the C<payload> and not the full object so that it is clearer what
to see what's happened. However, this isn't limited to exceptions; you can
do that with every class:
=begin code
class Cook {
has @.utensils is rw;
has @.cookbooks is rw;
method cook( $food ) {
return "Cooking $food";
}
method clean_utensils {
return "Cleaning $_" for @.utensils;
}
multi method gist(Cook:U:) { '⚗' ~ self.^name ~ '⚗' }
multi method gist(Cook:D:) {
'⚗ Cooks with ' ~ @.utensils.join( " ‣ ") ~ ' using '
~ @.cookbooks.map( "«" ~ * ~ "»").join( " and ") }
}
my $cook = Cook.new(
utensils => <spoon ladle knife pan>,
cookbooks => ['Cooking for geeks','The French Chef Cookbook']);
say Cook.gist; # OUTPUT: «⚗Cook⚗»
say $cook.gist; # OUTPUT: «⚗ Cooks with spoon ‣ ladle ‣ knife ‣ pan using «Cooking for geeks» and «The French Chef Cookbook»»
=end code
Usually you will want to define two methods, one for the class and another for
class instances; in this case, the class method uses the alembic symbol, and the
instance method, defined below it, aggregates the data we have on the cook to show
it in a narrative way.
=head2 A practical introspection example
When one creates a new class, it is sometimes useful to have
informative (and safe) introspection accessible more easily as a
public method. For example, the following class is used to hold
attributes for a record row in a CSV spreadsheet with a header row
defining its field (attribute) names.
=begin code :solo
unit class CSV-Record;
#| Field names and values for a CSV row
has $last;
has $first;
#...more fields (attributes)...
method fields(--> List) {
#| Return a list of the the attribute names (fields)
#| of the class instance
my @attributes = self.^attributes;
my @names;
for @attributes -> $a {
my $name = $a.name;
# The name is prefixed by its sigil and twigil
# which we don't want
$name ~~ s/\S\S//;
@names.push: $name;
}
@names
}
method values(--> List) {
#| Return a list of the values for the attributes
#| of the class instance
my @attributes = self.^attributes;
my @values;
for @attributes -> $a {
# Syntax is not obvious
my $value = $a.get_value: self;
@values.push: $value;
}
@values
}
=end code
We use it with a simple CSV file with contents:
=begin code :lang<csv>
last, first #...more fields...
Wall, Larry
Conway, Damian
=end code
Load the first record and show its contents:
=begin code :preamble<my $last; my $first; class CSV-Record {}>
my $record = CSV-Record.new: :$last, :$first;
say $record.fields.raku; # OUTPUT: «["last", "first"]»
say $record.values.raku; # OUTPUT: «["Wall", "Larry"]»
=end code
Note that practically we would have designed the class so that it has
the C<fields> list as a constant since its values are the same for all
class objects:
=begin code
constant @fields = <last first>;
method fields(--> List) {
@fields
}
=end code
Downsides of using the introspective method for attribute names
include slightly more processing time and power and the probable need
to remove the sigil and twigil for public presentation.
=end pod
================================================
FILE: doc/Language/community.rakudoc
================================================
=begin pod :kind("Language") :subkind("Language") :category("reference")
=TITLE Community
=SUBTITLE Information about the people working on and using Raku
=head1 Overview
"Perl 5 was my rewrite of Perl. I want Perl 6 to be the community's rewrite
of Perl and of the community." - Larry Wall (circa 2000)
"I am in favor of this change [a community driven renaming from Perl 6 to Raku], because it reflects an ancient wisdom:
'No one sews a patch of unshrunk cloth on an old garment, for the patch will pull away from
the garment, making the tear worse. Neither do people pour new wine into old wineskins.
If they do, the skins will burst; the wine will run out and the wineskins will be ruined.
No, they pour new wine into new wineskins, and both are preserved.'" - Larry Wall
(L<2019|https://github.com/Raku/problem-solving/pull/89#pullrequestreview-300789072>)
=head1 The Raku community
=head2 Online communities
L<IRC|/language/glossary#IRC> communication has played an integral role in the Raku community for more than a decade. There are various channels for Raku-related activities on C<libera.chat>. There are several L<bots|/language/glossary#Bot> to make IRC activity more convenient and fun. You can read about IRC content L<here|https://raku.org/community/> in greater details.
L<The Raku Discord server|https://discord.gg/VzYpdQ6> serves a similar purpose. Thanks to the bridges written by fellow Raku members, it integrates well with the main IRC channels.
L<StackOverflow|https://stackoverflow.com/questions/tagged/raku> 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<raku.org community page|https://raku.org/community>.
=head2 Offline communities
Raku is also a common topic at
L<Perl conferences|https://www.perl.org/events.html> and
L<Perl Monger meetings|https://www.pm.org/>.
If you prefer in-person meetings, these are warmly recommended!
=head2 Other resources
L<Camelia|https://raku.org/>, the multi-color butterfly with P 6 in her wings, is the symbol of this diverse and welcoming community.
=head1 Rakudo Weekly
Elizabeth Mattijsen usually posts in L<the "Rakudo Weekly" blog|https://rakudoweekly.blog/>, a summary of Raku posts, tweets, comments and other interesting tidbits.
If you want a single resource to know what is going on in the Raku community now, this is your best resource.
Historical articles (pre name change) can be found archived on
L<the "Perl 6 Weekly" blog|https://p6weekly.wordpress.com/>.
=head1 Raku Advent calendar
The Raku community publishes every December an
L<Advent Calendar|https://raku-advent.blog/>, with Raku tutorials every day until
Christmas. Previous calendars (pre name change) are
L<still available|https://perl6advent.wordpress.com/> and relevant.
Organization and assignment of days is done through the different Raku channels and the
L<Raku/advent|https://github.com/Raku/advent> 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.
=comment HOW TO WRITE: One topic/point/idea per sentence, one sentence per line - to make diffs & translation easier.
=end pod
================================================
FILE: doc/Language/compilation.rakudoc
================================================
=begin pod :kind("Language") :subkind("Language") :category("tutorial")
=TITLE CompUnits and where to find them
=SUBTITLE How and when Raku modules are compiled, where they are stored, and how to access them in compiled form.
=head1 Overview
Programs in Raku, as a member of the Perl language family, tend at the top level to be more at the interpreted
end of the interpreted-compiled spectrum. In this tutorial, an 'interpreted' program means that the source code,
namely the human-readable text such as C<say 'hello world';>, is immediately processed by the C<Raku> program into code
that can be executed by the computer, with any intermediate stages being stored in memory.
A compiled program, by contrast, is one where the human readable source is first processed into machine-executable code
and some form of this code is stored 'on disk'. In order to execute the program, the machine-readable version is loaded
into memory and then run by the computer.
Both compiled and interpreted forms have advantages. Briefly, interpreted programs can be 'whipped up' quickly and
the source changed quickly. Compiled programs can be complex and take a significant time to pre-process into machine-readable
code, but then running them is much faster for a user, who only 'sees' the loading and running time, not the compilation
time.
C<Raku> has both paradigms. At the B<top level> a Raku program is interpreted, but code that is separated out into a
Module will be compiled and the preprocessed version is then loaded when necessary. In practice, Modules that have been
written by the community will only need to be precompiled once by a user when they are 'installed', for example by a
Module manager such as C<zef>. Then they can be C<use>d by a developer in her own program. The effect is to make C<Raku>
top level programs run quickly.
One of the great strengths of the C<Perl> family of languages was the ability to integrate a whole ecosystem of modules
written by competent programmers into a small program. This strength was widely copied and is now the norm for all
languages. C<Raku> takes integration even further, making it relatively easy for C<Raku> programs to incorporate system
libraries written in other languages into C<Raku> programs, see L<Native Call|/language/nativecall>.
The experience from C<Perl> and other languages is that the distributive nature of Modules generate several practical difficulties:
=item a popular module may go through several iterations as the API gets improved, without a guarantee that there is
backward compatibility. So, if a program relies on some specific function or return, then there has to be a way to
specify the L<C<Version>|/type/Version>.
=item a module may have been written by Bob, a very competent programmer, who moves on in life, leaving the module unmaintained,
so Alice takes over. This means that the same module, with the same name, and the same general API may have two
versions in the wild. Alternatively, two developers (e.g., Alice and Bob) who initially cooperated on a module, then part company about its
development. Consequently, it sometimes is necessary for there to be a way to define the B<Auth> of the module.
=item a module may be enhanced over time and the maintainer keeps two versions up to date, but with different APIs. So it is
may be necessary to define the B<API> required.
=item when developing a new program a developer may want to have the modules written by both Alice and Bob installed locally.
So it is not possible simply to have only one version of a module with a single name installed.
C<Raku> 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<elsewhere|/language/typesystem#Versioning,_authorship,_and_API_version.>. This tutorial is about how C<Raku> handles these
possibilities.
=head1 Introduction
Before considering the C<Raku> framework, let's have a look at how languages like C<Perl> or C<Python> handle module
installation and loading.
=begin code :lang<text>
ACME::Foo::Bar -> ACME/Foo/Bar.pm
os.path -> os/path.py
=end code
In those languages, module names have a 1:1 relation with filesystem paths.
We simply replace the double colons or periods with slashes and add a C<.pm> or C<.py>.
Note that these are relative paths.
Both C<Python> and C<Perl> use a list of include paths, to complete these paths.
In C<Perl> they are available in the global C<@INC> array.
=begin code :lang<text>
@INC
/usr/lib/perl5/site_perl/5.22.1/x86_64-linux-thread-multi
/usr/lib/perl5/site_perl/5.22.1/
/usr/lib/perl5/vendor_perl/5.22.1/x86_64-linux-thread-multi
/usr/lib/perl5/vendor_perl/5.22.1/
/usr/lib/perl5/5.22.1/x86_64-linux-thread-multi
/usr/lib/perl5/5.22.1/
=end code
Each of these include directories is checked for whether it contains a relative path determined from the module name.
If the shoe fits, the file is loaded.
Of course that's a bit of a simplified version.
Both languages support caching compiled versions of modules.
So instead of just the C<.pm> file C<Perl> first looks for a C<.pmc> file.
And C<Python> first looks for C<.pyc> files.
Module installation in both cases means mostly copying files into locations determined by the same simple mapping. The
system is easy to explain, easy to understand, simple and robust.
=head2 Why change?
Why would C<Raku> need another framework? The reason is there are features that those languages lack, namely:
=item Unicode module names
=item Modules published under the same names by different authors
=item Having multiple versions of a module installed
The set of 26 Latin characters is too restrictive for virtually all real modern languages, including English, which
have diacritics for many commonly-used words.
With a 1:1 relation between module names and filesystem paths, you enter a world of pain
once you try to support Unicode on multiple platforms and filesystems.
Then there's sharing module names between multiple authors. This one may or may not work out well in practice.
I can imagine using it for example for publishing a module with some fix until the original author includes
the fix in the "official" version.
Finally there's multiple versions. Usually people who need certain versions of modules reach for local::lib or
containers or some home grown workarounds. They all have their own disadvantages. None of them would be necessary
if applications could just say, hey I need good old, trusty version 2.9 or maybe a bug fix release of that branch.
If you had any hopes of continuing using the simple name mapping solution, you probably gave up at the
versioning requirement. Because, how would you find version 3.2 of a module when looking for a 2.9 or higher?
Popular ideas included collecting information about installed modules in JSON files but when those turned out to be
toe-nail growing slow, text files were replace by putting the metadata into SQLite databases.
However, these ideas can be easily shot down by introducing another requirement: distribution packages.
Packages for Linux distributions are mostly just archives containing some files plus some metadata.
Ideally the process of installing such a package means just unpacking the files and updating the central package database.
Uninstalling means deleting the files installed this way and again updating the package database.
Changing existing files on install and uninstall makes packagers' lives much harder, so we really want to avoid that.
Also the names of the installed files may not depend on what was previously installed.
We must know at the time of packaging what the names are going to be.
=head2 Long names
=begin code :lang<text>
Foo::Bar:auth<cpan:nine>:ver<0.3>:api<1>
=end code
Step 0 in getting us back out of this mess is to define a long name.
A full module name in C<Raku> consists of the short-name, auth, version and API
At the same time, the thing you install is usually not a single module but a distribution which probably contains one or more modules.
Distribution names work just the same way as module names.
Indeed, distributions often will just be called after their main module.
An important property of distributions is that they are immutable.
C«Foo:auth<cpan:nine>:ver<0.3>:api<1>» will always be the name for exactly the same code.
=head2 $*REPO
In C<Perl> and C<Python> you deal with include paths pointing to filesystem directories.
In C<Raku> we call such directories "repositories" and each of these repositories is governed by an object that does the
L<C<CompUnit::Repository>|/type/CompUnit::Repository> role.
Instead of an B<C<@INC>> array, there's the C<$*REPO> variable.
It contains a single repository object.
This object has a B<next-repo> attribute that may contain another repository.
In other words: repositories are managed as a I<linked list>.
The important difference to the traditional array is, that when going through the list, each object has a say in whether
to pass along a request to the next-repo or not.
C<Raku> sets up a standard set of repositories, "core", "vendor", and "site".
In addition, there is a "home" repository for the current user.
Repositories must implement the C<need> method.
A C<use> or C<require> statement in C<Raku> code is basically translated to a call to B<C<$*REPO>>'s C<need> method.
This method may in turn delegate the request to the next-repo.
=begin code :preamble<class CompUnit::Store {};> :method
role CompUnit::Repository {
has CompUnit::Repository $.next-repo is rw;
method need(CompUnit::DependencySpecification $spec,
CompUnit::PrecompilationRepository $precomp,
CompUnit::Store :@precomp-stores
--> CompUnit:D
)
{ ... }
method loaded(
--> Iterable
)
{ ... }
method id( --> Str )
{ ... }
}
=end code
=head2 Repositories
Rakudo comes with several classes that can be used for repositories.
The most important ones are L<C<CompUnit::Repository::FileSystem>|/type/CompUnit::Repository::FileSystem> and L<C<CompUnit::Repository::Installation>|/type/CompUnit::Repository::Installation>.
The FileSystem repo is meant to be used during module development and actually works just like C<Perl> when
looking for a module.
It doesn't support versions or C<auth>s and simply maps the short-name to a filesystem path.
The Installation repository is where the real smarts are. When requesting a module, you will usually either do it
via its exact long name, or you say something along the lines of "give me a module that matches this filter."
Such a filter is given by way of a C<CompUnit::DependencySpecification> object which has fields for
=item short-name,
=item auth-matcher,
=item version-matcher and
=item api-matcher.
When looking through candidates, the Installation repository will smartmatch a module's long name against this
DependencySpecification or rather the individual fields against the individual matchers.
Thus a matcher may be some concrete value, a version range, or even a regex (though an arbitrary regex, such as C<.*>,
would not produce a useful result, but something like C<3.20.1+> will only find candidates higher than 3.20.1).
Loading the metadata of all installed distributions would be prohibitively slow. The current implementation of
the C<Raku> framework uses
the filesystem as a kind of database. However, another implementation may use another strategy. The following description
shows how one implementation works and is included here to illustrate what is happening.
We store not only a distribution's files but also create indices for speeding up lookups.
One of these indices comes in the form of directories named after the short-name of installed modules.
However most of the filesystems in common use today cannot handle Unicode names, so we cannot just use
module names directly.
This is where the now infamous SHA-1 hashes enter the game.
The directory names are the ASCII encoded SHA-1 hashes of the UTF-8 encoded module short-names.
In these directories we find one file per distribution that contains a module with a matching short name.
These files again contain the ID of the dist and the other fields that make up the long name: auth, version, and api.
So by reading these files we have a usually short list of auth-version-api triplets which we can match against our
DependencySpecification.
We end up with the winning distribution's ID, which we use to look up the metadata, stored in a JSON encoded file.
This metadata contains the name of the file in the sources/ directory containing the requested module's code.
This is what we can load.
Finding names for source files is again a bit tricky, as there's still the Unicode issue and in addition the same
relative file names may be used by different installed distributions (think versions).
So for now at least, we use SHA-1 hashes of the long-names.
=head2 Resources
=begin code :lang<text>
%?RESOURCES
%?RESOURCES<libraries/p5helper>
%?RESOURCES<icons/foo.png>
%?RESOURCES<schema.sql>
Foo
|___ lib
| |____ Foo.rakumod
|
|___ resources
|___ schema.sql
|
|___ libraries
|____ p5helper
| |___
|___ icons
|___ foo.png
=end code
It's not only source files that are stored and found this way.
Distributions may also contain arbitrary resource files.
These could be images, language files or shared libraries that are compiled on installation.
They can be accessed from within the module through the C<%?RESOURCES> hash.
As long as you stick to the standard layout conventions for distributions, this even works during development
without installing anything.
A nice result of this architecture is that it's fairly easy to create special purpose repositories.
=head2 Dependencies
Luckily precompilation at least works quite well in most cases. Yet it comes with its own set of challenges.
Loading a single module is easy.
The fun starts when a module has dependencies and those dependencies have again dependencies of their own.
When loading a precompiled file in C<Raku> we need to load the precompiled files of all its dependencies, too.
And those dependencies B<must> be precompiled, we cannot load them from source files.
Even worse, the precomp files of the dependencies B<must> be exactly the same files we used for precompiling our
module in the first place.
To top it off, precompiled files work only with the exact C<Raku> binary, that was used for compilation.
All of that would still be quite manageable if it weren't for an additional requirement: as a user you expect a new
version of a module you just installed to be actually used, don't you?
In other words: if you upgrade a dependency of a precompiled module, we have to detect this and precompile the module
again with the new dependency.
=head2 Precomp stores
Now remember that while we have a standard repository chain, the user may prepend additional repositories by way of
C<-I> on the command line or "use lib" in the code.
These repositories may contain the dependencies of precompiled modules.
Our first solution to this riddle was that each repository gets its own precomp store where precompiled files are stored.
We only ever load precomp files from the precomp store of the very first repository in the chain because this is the
only repository that has direct or at least indirect access to all the candidates.
If this repository is a FileSystem repository, we create a precomp store in a C<.precomp> directory.
While being the safe option, this has the consequence that whenever you use a new repository, we will start out
without access to precompiled files.
Instead, we will precompile the modules used when they are first loaded.
=head2 Credit
This tutorial is based on a C<niner> L<talk|http://niner.name/talks/A%20look%20behind%20the%20curtains%20-%20module%20loading%20in%20Perl%206/>.
=end pod
================================================
FILE: doc/Language/concurrency.rakudoc
================================================
=begin pod :kind("Language") :subkind("Language") :category("tutorial")
=TITLE Concurrency
=SUBTITLE Concurrency and asynchronous programming
In common with most modern programming languages, Raku is designed to support
parallelism, asynchronicity and
L<concurrency|https://en.wikipedia.org/wiki/Concurrent_computing>. Parallelism
is about doing multiple things at once. I<Asynchronous programming>, which is
sometimes called event driven or reactive programming, is about supporting
changes in the program flow caused by events triggered elsewhere in the program.
Finally, concurrency is about the coordination of access and modification of
some shared resources.
The aim of the Raku concurrency design is to provide a high-level,
composable and consistent interface, regardless of how a virtual machine
may implement it for a particular operating system, through layers of
facilities as described below.
=begin comment
I'm not quite clear which specific features should be included below
hyper-operators, autothreading junctions?
=end comment
Additionally, certain Raku features may implicitly operate in an asynchronous
fashion, so in order to ensure predictable interoperation with these features,
user code should, where possible, avoid the lower level concurrency APIs (e.g.,
L<C<Thread>|/type/Thread> and L<C<Scheduler>|/type/Scheduler>) and use the
higher-level interfaces.
=head1 High-level APIs
X<|Other languages,Futures>
=head2 Promises
A L<C<Promise>|/type/Promise> (also called I<future> in other programming
environments) encapsulates the result of a computation that may not
have completed or even started at the time the promise is obtained.
A L<C<Promise>|/type/Promise> starts from a C<Planned> status and can result in either a
C<Kept> status, meaning the promise has been successfully completed, or
a C<Broken> status meaning that the promise has failed.
Usually this is much of the functionality that user code needs to operate
in a concurrent or asynchronous manner.
=begin code
my $p1 = Promise.new;
say $p1.status; # OUTPUT: «Planned»
$p1.keep('Result');
say $p1.status; # OUTPUT: «Kept»
say $p1.result; # OUTPUT: «Result»
# (since it has been kept, a result is available!)
my $p2 = Promise.new;
$p2.break('oh no');
say $p2.status; # OUTPUT: «Broken»
say $p2.result; # dies, because the promise has been broken
CATCH { default { say .^name, ': ', .Str } };
# OUTPUT: «X::AdHoc+{X::Promise::Broken}: oh no»
=end code
Promises gain much of their power by being composable, for example by
chaining, usually by the L<then|/type/Promise#method_then> method:
my $promise1 = Promise.new();
my $promise2 = $promise1.then(
-> $v { say $v.result; "Second Result" }
);
$promise1.keep("First Result");
say $promise2.result; # OUTPUT: «First ResultSecond Result»
Here the L<then|/type/Promise#method_then> method schedules code to be executed
when the first L<C<Promise>|/type/Promise> is kept or broken, itself returning a
new L<C<Promise>|/type/Promise> which will be kept with the result of the code when
it is executed (or broken if the code fails). C<keep> changes the status of the
promise to C<Kept> setting the result to the positional argument. C<result>
blocks the current thread of execution until the promise is kept or broken, if
it was kept then it will return the result (that is the value passed to
C<keep>), otherwise it will throw an exception based on the value passed to
C<break>. The latter behavior is illustrated with:
my $promise1 = Promise.new();
my $promise2 = $promise1.then(-> $v { say "Handled but : "; say $v.result});
$promise1.break("First Result");
try $promise2.result;
say $promise2.cause; # OUTPUT: «Handled but : First Result»
Here the C<break> will cause the code block of the C<then> to throw an exception
when it calls the C<result> method on the original promise that was passed as an
argument, which will subsequently cause the second promise to be broken, raising
an exception in turn when its result is taken. The actual
L<C<Exception>|/type/Exception> object will then be available from C<cause>. If the
promise had not been broken C<cause> would raise an
L<C<X::Promise::CauseOnlyValidOnBroken>|/type/X::Promise::CauseOnlyValidOnBroken> exception.
A L<C<Promise>|/type/Promise> can also be scheduled to be automatically kept at a
future time:
my $promise1 = Promise.in(5);
my $promise2 = $promise1.then(-> $v { say $v.status; 'Second Result' });
say $promise2.result;
The L<method in|/type/Promise#method_in> creates a new promise and
schedules a new task to call C<keep> on it no earlier than the supplied
number of seconds, returning the new L<C<Promise>|/type/Promise> object.
A very frequent use of promises is to run a piece of code, and keep the
promise once it returns successfully, or break it when the code dies.
The L<start method|/type/Promise#method_start> provides a shortcut
for that:
my $promise = Promise.start(
{ my $i = 0; for 1 .. 10 { $i += $_ }; $i}
);
say $promise.result; # OUTPUT: «55»
Here the C<result> of the promise returned is the value returned from
the code. Similarly if the code fails (and the promise is thus broken),
then C<cause> will be the L<C<Exception>|/type/Exception> object that was thrown:
my $promise = Promise.start({ die "Broken Promise" });
try $promise.result;
say $promise.cause;
This is considered to be such a commonly required pattern that it is
also provided as a keyword:
my $promise = start {
my $i = 0;
for 1 .. 10 {
$i += $_
}
$i
}
my $result = await $promise;
say $result;
The subroutine L<await|/type/Promise#sub_await> is almost equivalent to
calling C<result> on the promise object returned by C<start> but it will
also take a list of promises and return the result of each:
my $p1 = start {
my $i = 0;
for 1 .. 10 {
$i += $_
}
$i
};
my $p2 = start {
my $i = 0;
for 1 .. 10 {
$i -= $_
}
$i
};
my @result = await $p1, $p2;
say @result; # OUTPUT: «[55 -55]»
In addition to C<await>, two class methods combine several
L<C<Promise>|/type/Promise> objects into a new promise: C<allof> returns a promise
that is kept when all the original promises are kept or broken:
my $promise = Promise.allof(
Promise.in(2),
Promise.in(3)
);
await $promise;
say "All done"; # Should be not much more than three seconds later
And C<anyof> returns a new promise that will be kept when any of the
original promises is kept or broken:
my $promise = Promise.anyof(
Promise.in(3),
Promise.in(8600)
);
await $promise;
say "All done"; # Should be about 3 seconds later
Unlike C<await> however the results of the original kept promises are not
available without referring to the original, so these are more useful
when the completion or otherwise of the tasks is more important to the
consumer than the actual results, or when the results have been collected
by other means. You may, for example, want to create a dependent Promise
that will examine each of the original promises:
my @promises;
for 1..5 -> $t {
push @promises, start {
sleep $t;
Bool.pick;
};
}
say await Promise.allof(@promises).then({ so all(@promises>>.result) });
Which will give True if all of the promises were kept with True, False
otherwise.
If you are creating a promise that you intend to keep or break yourself
then you probably don't want any code that might receive the promise to
inadvertently (or otherwise) keep or break the promise before you do.
For this purpose there is the L<method vow|/type/Promise#method_vow>, which
returns a Vow object which becomes the only mechanism by which the promise
can be kept or broken. If an attempt to keep or break the Promise is made
directly then the exception L<C<X::Promise::Vowed>|/type/X::Promise::Vowed> will be thrown, as long
as the vow object is kept private, the status of the promise is safe:
sub get_promise {
my $promise = Promise.new;
my $vow = $promise.vow;
Promise.in(10).then({$vow.keep});
$promise;
}
my $promise = get_promise();
# Will throw an exception
# "Access denied to keep/break this Promise; already vowed"
$promise.keep;
CATCH { default { say .^name, ': ', .Str } };
# OUTPUT: «X::Promise::Vowed: Access denied to keep/break this Promise; already vowed»
The methods that return a promise that will be kept or broken
automatically such as C<in> or C<start> will do this, so it is not
necessary to do it for these.
=head2 Supplies
A L<C<Supply>|/type/Supply> is an asynchronous data streaming mechanism that can be
consumed by one or more consumers simultaneously in a manner similar to
"events" in other programming languages and can be seen as enabling
I<event driven> or reactive designs.
At its simplest, a L<C<Supply>|/type/Supply> is a message stream that can have
multiple subscribers created with the method C<tap> on to which data items can
be placed with C<emit>.
There are two types of Supplies: C<live> and C<on demand>. A C<live>
supply is like a TV broadcast: those who tune in don't get previously emitted
values. An C<on-demand> broadcast is like a video streaming service:
everyone who starts streaming a movie (taps a L<C<Supply>|/type/Supply>),
always starts it from the beginning (gets all the values),
regardless of how many people are watching it right now.
Note that no
history is kept for C<on-demand> supplies, instead, the C<supply> block is run
for each tap of the supply.
A C<live> L<C<Supply>|/type/Supply>
is created by the L<C<Supplier>|/type/Supplier> factory, each emitted value is passed to
all the active tappers as they are added:
my $supplier = Supplier.new;
my $supply = $supplier.Supply;
$supply.tap( -> $v { say $v });
for 1 .. 10 {
$supplier.emit($_);
}
Note that the C<tap> is called on a L<C<Supply>|/type/Supply> object created by the
L<C<Supplier>|/type/Supplier> and new values are emitted on the
L<C<Supplier>|/type/Supplier>.
X<|Reference,supply (on-demand)>
An C<on-demand> L<C<Supply>|/type/Supply> is created by the C<supply> keyword:
my $supply = supply {
for 1 .. 10 {
emit($_);
}
}
$supply.tap( -> $v { say $v });
In this case the code in the supply block is executed every time the
L<C<Supply>|/type/Supply> returned by C<supply> is tapped, as demonstrated by:
my $supply = supply {
for 1 .. 10 {
emit($_);
}
}
$supply.tap( -> $v { say "First : $v" });
$supply.tap( -> $v { say "Second : $v" });
The C<tap> method returns a L<C<Tap>|/type/Tap> object which can be used to obtain
information about the tap and also to turn it off when we are no longer
interested in the events:
my $supplier = Supplier.new;
my $supply = $supplier.Supply;
my $tap = $supply.tap( -> $v { say $v });
$supplier.emit("OK");
$tap.close;
$supplier.emit("Won't trigger the tap");
Calling C<done> on the supply object calls the C<done> callback that
may be specified for any taps, but does not prevent any further events
being emitted to the stream, or taps receiving them.
The method C<interval> returns a new C<on-demand> supply which periodically
emits a new event at the specified interval. The data that is emitted
is an integer starting at 0 that is incremented for each event. The
following code outputs 0 .. 5 :
my $supply = Supply.interval(2);
$supply.tap(-> $v { say $v });
sleep 10;
A second argument can be supplied to C<interval> which specifies a delay
in seconds before the first event is fired. Each tap of a supply created
by C<interval> has its own sequence starting from 0, as illustrated by
the following:
my $supply = Supply.interval(2);
$supply.tap(-> $v { say "First $v" });
sleep 6;
$supply.tap(-> $v { say "Second $v"});
sleep 10;
A live L<C<Supply>|/type/Supply> that keeps values until first tapped can be created with
L<C<Supplier::Preserving>|/type/Supplier::Preserving>.
=head3 X<C<whenever>|Control flow,whenever>
The C<whenever> keyword can be used in supply blocks or in react
blocks. From the 6.d version, it needs to be used within the lexical scope of
them. It introduces a block of code that will be run when prompted by an
asynchronous event that it specifies - that could be a L<C<Supply>|/type/Supply>, a
L<C<Channel>|/type/Channel>, a L<C<Promise>|/type/Promise> or an
L<C<Iterable>|/type/Iterable>.
Please note that one should keep the code inside the C<whenever> as small as
possible, as only one C<whenever> block will be executed at any time. One can
use a C<start> block inside the C<whenever> block to run longer running code.
In this example we are watching two supplies.
=begin code
my $bread-supplier = Supplier.new;
my $vegetable-supplier = Supplier.new;
my $supply = supply {
whenever $bread-supplier.Supply {
emit("We've got bread: " ~ $_);
};
whenever $vegetable-supplier.Supply {
emit("We've got a vegetable: " ~ $_);
};
}
$supply.tap( -> $v { say "$v" });
$vegetable-supplier.emit("Radish"); # OUTPUT: «We've got a vegetable: Radish»
$bread-supplier.emit("Thick sliced"); # OUTPUT: «We've got bread: Thick sliced»
$vegetable-supplier.emit("Lettuce"); # OUTPUT: «We've got a vegetable: Lettuce»
=end code
=head3 X<C<react>|Control flow,react>
The C<react> keyword introduces a block of code containing one or more
C<whenever> keywords to watch asynchronous events. The main difference between a
supply block and a react block is that the code in a react block runs where it
appears in the code flow, whereas a supply block has to be tapped before it does
anything.
Another difference is that a supply block can be used without the C<whenever>
keyword, but a react block requires at least one C<whenever> to be of any real
use.
react {
whenever Supply.interval(2) -> $v {
say $v;
done() if $v == 4;
}
}
Here the C<whenever> keyword uses L«C<.act>|/type/Supply#method_act» to create a
tap on the L<C<Supply>|/type/Supply> from the provided block. The C<react> block is
exited when C<done()> is called in one of the taps.
An C<on-demand> L<C<Supply>|/type/Supply> can also be created from a list of values
that will be emitted in turn, thus the first C<on-demand> example could be
written as:
react {
whenever Supply.from-list(1..10) -> $v {
say $v;
}
}
=head3 Transforming supplies
An existing supply object can be filtered or transformed, using the methods
C<grep> and C<map> respectively, to create a new supply in a manner like
the similarly named list methods: C<grep> returns a supply such that only
those events emitted on the source stream for which the C<grep> condition
is true is emitted on the second supply:
my $supplier = Supplier.new;
my $supply = $supplier.Supply;
$supply.tap(-> $v { say "Original : $v" });
my $odd_supply = $supply.grep({ $_ % 2 });
$odd_supply.tap(-> $v { say "Odd : $v" });
my $even_supply = $supply.grep({ not $_ % 2 });
$even_supply.tap(-> $v { say "Even : $v" });
for 0 .. 10 {
$supplier.emit($_);
}
C<map> returns a new supply such that for each item emitted to the
original supply a new item which is the result of the expression passed
to the C<map> is emitted:
my $supplier = Supplier.new;
my $supply = $supplier.Supply;
$supply.tap(-> $v { say "Original : $v" });
my $half_supply = $supply.map({ $_ / 2 });
$half_supply.tap(-> $v { say "Half : $v" });
for 0 .. 10 {
$supplier.emit($_);
}
=head3 Ending a supply
If you need to have an action that runs when the supply finishes, you can do so
by setting the C<done> and C<quit> options in the call to C<tap>:
=begin code :preamble<my $supply; class X::MyApp::Error is Exception {}>
$supply.tap: { ... },
done => { say 'Job is done.' },
quit => {
when X::MyApp::Error { say "App Error: ", $_.message }
};
=end code
The C<quit> block works very similar to a C<CATCH>. If the exception is marked
as seen by a C<when> or C<default> block, the exception is caught and handled.
Otherwise, the exception continues to up the call tree (i.e., the same behavior
as when C<quit> is not set).
=head3 Phasers in a supply or react block
If you are using the C<react> or C<supply> block syntax with C<whenever>, you
can add phasers within your C<whenever> blocks to handle the C<done> and C<quit>
messages from the tapped supply:
=begin code :preamble<my $supply; class X::MyApp::Error is Exception {}>
react {
whenever $supply {
...; # your usual supply tap code here
LAST { say 'Job is done.' }
QUIT { when X::MyApp::Error { say "App Error: ", $_.message } }
}
}
=end code
The behavior here is the same as setting C<done> and C<quit> on C<tap>.
=head2 Channels
A L<C<Channel>|/type/Channel> is a thread-safe queue that can have multiple readers and
writers that could be considered to be similar in operation to a "fifo" or
named pipe except it does not enable inter-process communication. It should
be noted that, being a true queue, each value sent to the L<C<Channel>|/type/Channel> will only
be available to a single reader on a first read, first served basis: if you
want multiple readers to be able to receive every item sent you probably
want to consider a L<C<Supply>|/type/Supply>.
An item is queued onto the L<C<Channel>|/type/Channel> with the
L<method send|/type/Channel#method_send>, and the L<method
receive|/type/Channel#method_receive> removes an item from the queue
and returns it, blocking until a new item is sent if the queue is empty:
my $channel = Channel.new;
$channel.send('Channel One');
say $channel.receive; # OUTPUT: «Channel One»
If the channel has been closed with the L<method
close|/type/Channel#method_close> then any C<send> will cause the
exception L<C<X::Channel::SendOnClosed>|/type/X::Channel::SendOnClosed> to be thrown, and a C<receive>
will throw an L<C<X::Channel::ReceiveOnClosed>|/type/X::Channel::ReceiveOnClosed>.
The L<method list|/type/Channel#method_list> returns all the items on
the L<C<Channel>|/type/Channel> and will block until further items are queued unless the
channel is closed:
my $channel = Channel.new;
await (^10).map: -> $r {
start {
sleep $r;
$channel.send($r);
}
}
$channel.close;
for $channel.list -> $r {
say $r;
}
There is also the non-blocking L<method poll|/type/Channel#method_poll>
that returns an available item from the channel or L<C<Nil>|/type/Nil> if there
is no item or the channel is closed. This does mean that the
channel must be checked to determine whether it is closed:
my $c = Channel.new;
# Start three Promises that sleep for 1..3 seconds, and then
# send a value to our Channel
^3 .map: -> $v {
start {
sleep 3 - $v;
$c.send: "$v from thread {$*THREAD.id}";
}
}
# Wait 3 seconds before closing the channel
Promise.in(3).then: { $c.close }
# Continuously loop and poll the channel, until it's closed
my $is-closed = $c.closed;
loop {
if $c.poll -> $item {
say "$item received after {now - INIT now} seconds";
}
elsif $is-closed {
last;
}
say 'Doing some unrelated things...';
sleep .6;
}
# Doing some unrelated things...
# Doing some unrelated things...
# 2 from thread 5 received after 1.2063182 seconds
# Doing some unrelated things...
# Doing some unrelated things...
# 1 from thread 4 received after 2.41117376 seconds
# Doing some unrelated things...
# 0 from thread 3 received after 3.01364461 seconds
# Doing some unrelated things...
The L<method closed|/type/Channel#method_closed> returns a L<C<Promise>|/type/Promise> that
will be kept (and consequently will evaluate to True in a Boolean context)
when the channel is closed.
The C<.poll> method can be used in combination with C<.receive> method, as a
caching mechanism where lack of value returned by C<.poll> is a signal that
more values need to be fetched and loaded into the channel:
=begin code :preamble<my $c; sub slowly-fetch-a-thing {};>
sub get-value {
return $c.poll // do { start replenish-cache; $c.receive };
}
sub replenish-cache {
for ^20 {
$c.send: $_ for slowly-fetch-a-thing();
}
}
=end code
Channels can be used in place of the L<C<Supply>|/type/Supply> in the C<whenever> of a
C<react> block described earlier:
=begin code
my $channel = Channel.new;
my $p = start {
react {
whenever $channel {
say $_;
}
}
}
await (^10).map: -> $r {
start {
sleep $r;
$channel.send($r);
}
}
$channel.close;
await $p;
=end code
It is also possible to obtain a L<C<Channel>|/type/Channel> from a L<C<Supply>|/type/Supply> using the
L<Channel method|/type/Supply#method_Channel> which returns a L<C<Channel>|/type/Channel>
which is fed by a C<tap> on the L<C<Supply>|/type/Supply>:
my $supplier = Supplier.new;
my $supply = $supplier.Supply;
my $channel = $supply.Channel;
my $p = start {
react {
whenever $channel -> $item {
say "via Channel: $item";
}
}
}
await (^10).map: -> $r {
start {
sleep $r;
$supplier.emit($r);
}
}
$supplier.done;
await $p;
L<C<Channel>|/type/Channel> will return a different L<C<Channel>|/type/Channel> fed with the same data
each time it is called. This could be used, for instance, to fan-out a
L<C<Supply>|/type/Supply> to one or more L<C<Channel>|/type/Channel>s to provide for different interfaces
in a program.
=head2 Proc::Async
L<C<Proc::Async>|/type/Proc::Async> builds on the facilities described to run and interact with
an external program asynchronously:
my $proc = Proc::Async.new('echo', 'foo', 'bar');
$proc.stdout.tap(-> $v { print "Output: $v" });
$proc.stderr.tap(-> $v { print "Error: $v" });
say "Starting...";
my $promise = $proc.start;
await $promise;
say "Done.";
# Output:
# Starting...
# Output: foo bar
# Done.
The path to the command as well as any arguments to the command are
supplied to the constructor. The command will not be executed until
L<start|/type/Proc::Async#method_start> is called, which will return
a L<C<Promise>|/type/Promise> that will be kept when the program exits. The standard
output and standard error of the program are available as L<C<Supply>|/type/Supply>
objects from the methods L<stdout|/type/Proc::Async#method_stdout>
and L<stderr|/type/Proc::Async#method_stderr> respectively which can be
tapped as required.
If you want to write to the standard input of the program
you can supply the C<:w> adverb to the constructor and use
the methods L<write|/type/Proc::Async#method_write>,
L<print|/type/Proc::Async#method_print> or
L<say|/type/Proc::Async#method_say> to write to the opened pipe once
the program has been started:
my $proc = Proc::Async.new(:w, 'grep', 'foo');
$proc.stdout.tap(-> $v { print "Output: $v" });
say "Starting...";
my $promise = $proc.start;
$proc.say("this line has foo");
$proc.say("this one doesn't");
$proc.close-stdin;
await $promise;
say "Done.";
# Output:
# Starting...
# Output: this line has foo
# Done.
Some programs (such as C<grep> without a file argument in this
example, ) won't exit until their standard input is closed so
L<close-stdin|/type/Proc::Async#method_close-stdin> can be called when
you are finished writing to allow the L<C<Promise>|/type/Promise> returned by C<start>
to be kept.
=head1 Low-level APIs
=head2 Threads
The lowest level interface for concurrency is provided by L<C<Thread>|/type/Thread>. A
thread can be thought of as a piece of code that may eventually be run
on a processor, the arrangement for which is made almost entirely by the
virtual machine and/or operating system. Threads should be considered,
for all intents, largely un-managed and their direct use should be
avoided in user code.
A thread can either be created and then actually run later:
my $thread = Thread.new(code => { for 1 .. 10 -> $v { say $v }});
# ...
$thread.run;
Or can be created and run at a single invocation:
my $thread = Thread.start({ for 1 .. 10 -> $v { say $v }});
In both cases the completion of the code encapsulated by the L<C<Thread>|/type/Thread>
object can be waited on with the C<finish> method which will block until
the thread completes:
=for code :preamble<my $thread;>
$thread.finish;
Beyond that there are no further facilities for synchronization or resource
sharing which is largely why it should be emphasized that threads are unlikely
to be useful directly in user code.
=head2 Schedulers
The next level of the concurrency API is supplied by classes that
implement the interface defined by the role L<C<Scheduler>|/type/Scheduler>. The intent
of the scheduler interface is to provide a mechanism to determine which
resources to use to run a particular task and when to run it. The majority
of the higher level concurrency APIs are built upon a scheduler and it
may not be necessary for user code to use them at all, although some
methods such as those found in L<C<Proc::Async>|/type/Proc::Async>, L<C<Promise>|/type/Promise> and L<C<Supply>|/type/Supply>
allow you to explicitly supply a scheduler.
The current default global scheduler is available in the variable
C<$*SCHEDULER>.
The primary interface of a scheduler (indeed the only method required
by the L<C<Scheduler>|/type/Scheduler> interface) is the C<cue> method:
method cue(:&code, Instant :$at, :$in, :$every, :$times = 1; :&catch)
This will schedule the L<C<Callable>|/type/Callable> in C<&code> to be executed in the
manner determined by the adverbs (as documented in L<C<Scheduler>|/type/Scheduler>) using
the execution scheme as implemented by the scheduler. For example:
my $i = 0;
my $cancellation = $*SCHEDULER.cue({ say $i++}, every => 2 );
sleep 20;
Assuming that the C<$*SCHEDULER> hasn't been changed from the default,
will print the numbers 0 to 10 approximately (i.e with operating system
scheduling tolerances) every two seconds. In this case the code will
be scheduled to run until the program ends normally, however the method
returns a L<C<Cancellation>|/type/Cancellation> object which can be used to cancel the scheduled
execution before normal completion:
my $i = 0;
my $cancellation = $*SCHEDULER.cue({ say $i++}, every => 2 );
sleep 10;
$cancellation.cancel;
sleep 10;
should only output 0 to 5.
Despite the apparent advantage the L<C<Scheduler>|/type/Scheduler> interface provides over
that of L<C<Thread>|/type/Thread> all of functionality is available through higher level
interfaces and it shouldn't be necessary to use a scheduler directly,
except perhaps in the cases mentioned above where a scheduler can be
supplied explicitly to certain methods.
A library may wish to provide an alternative scheduler implementation if
it has special requirements, for instance a UI library may want all code
to be run within a single UI thread, or some custom priority mechanism
may be required, however the implementations provided as standard and
described below should suffice for most user code.
=head3 ThreadPoolScheduler
The L<C<ThreadPoolScheduler>|/type/ThreadPoolScheduler> is the default scheduler, it maintains a pool
of threads that are allocated on demand, creating new ones as necessary.
Rakudo allows the maximum number of threads allowed in the default scheduler
to be set by the environment variable C<RAKUDO_MAX_THREADS> at the time
the program is started.
If the maximum is exceeded then C<cue> may queue the code until a thread
becomes available.
=head3 CurrentThreadScheduler
The L<C<CurrentThreadScheduler>|/type/CurrentThreadScheduler> is a very simple scheduler that will always
schedule code to be run straight away on the current thread. The implication
is that C<cue> on this scheduler will block until the code finishes
execution, limiting its utility to certain special cases such as testing.
=head2 Locks
The class L<C<Lock>|/type/Lock> provides the low level mechanism that protects
shared data in a concurrent environment and is thus key to supporting
thread-safety in the high level API, this is sometimes known as a
"Mutex" in other programming languages. Because the higher level classes
(L<C<Promise>|/type/Promise>, L<C<Supply>|/type/Supply> and L<C<Channel>|/type/Channel>) use a L<C<Lock>|/type/Lock> where required it
is unlikely that user code will need to use a L<C<Lock>|/type/Lock> directly.
The primary interface to L<C<Lock>|/type/Lock> is the method
L<protect|/type/Lock#method_protect> which ensures that a block of code
(commonly called a "critical section") is only executed in one thread
at a time:
my $lock = Lock.new;
my $a = 0;
await (^10).map: {
start {
$lock.protect({
my $r = rand;
sleep $r;
$a++;
});
}
}
say $a; # OUTPUT: «10»
C<protect> returns whatever the code block returns.
Because C<protect> will block any threads that are waiting to execute
the critical section the code should be as quick as possible.
=head2 Lock::Async
L<C<Lock::Async>|/type/Lock::Async> is a mutual exclusion mechanism much like
Lock, but it exposes its functionality through L<C<Promise>|/type/Promise>s, allowing the use of
C<await> when waiting for a lock to become available, instead of blocking an
entire thread.
Another difference is that it is not re-entrant, meaning that the lock is not
considered available to code that is C<protect>ed by the lock.
L<C<Lock::Async>|/type/Lock::Async> is more high-level than L<C<Lock>|/type/Lock>, but it is still considered a
low-level primitive. Higher-level primitives should be preferred over mutating
shared data inside critical sections.
=head1 Safety concerns
Some shared data concurrency issues are less obvious than others.
For a good general write-up on this subject see this L<blog post|https://raku.github.io/CCR/Remaster/Jonathan%20Worthington/Racing-to-writeness-to-wrongness-leads.html>.
One particular issue of note is when container autovivification or extension
takes place. When an L<C<Array>|/type/Array> or a L<C<Hash>|/type/Hash> entry is initially assigned the
underlying structure is altered and that operation is not async safe. For
example, in this code:
my @array;
my $slot := @array[20];
$slot = 'foo';
The third line is the critical section as that is when the array is extended.
The simplest fix is to use a L<C<Lock>|/type/Lock> to protect the critical section. A
possibly better fix would be to refactor the code so that sharing a container
is not necessary.
=end pod
================================================
FILE: doc/Language/containers.rakudoc
================================================
=begin pod :kind("Language") :subkind("Language") :category("fundamental")
=TITLE Containers
=SUBTITLE A low-level explanation of Raku containers
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<ordered> containers in
Raku, see the overview of L<lists, sequences, and arrays|/language/list>; for
I<unordered> containers, see L<sets, bags, and mixes|/language/setbagmix>.
=head1 What is a variable?
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 scope declaration like C<my $x>, 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.
At runtime, a variable appears as an entry in a I<lexical pad>, or
I<lexpad> for short. This is a per-scope data structure that stores a
pointer for each variable.
In the case of C<my $x>, the lexpad entry for the variable C<$x> is a
pointer to an object of type L<C<Scalar>|/type/Scalar>, usually just called I<the
container>.
=head1 Scalar containers
Although objects of type L<C<Scalar>|/type/Scalar> are everywhere in Raku, you
rarely see them directly as objects, because most operations I<decontainerize>,
which means they act on the L<C<Scalar>|/type/Scalar> container's contents instead of the
container itself.
In code like
my $x = 42;
say $x;
the assignment C<$x = 42> stores a pointer to the L<C<Int>|/type/Int> object 42 in the
scalar container to which the lexpad entry for C<$x> points.
The assignment operator asks the container on the left to store the value on
its right. What exactly that means is up to the container type. For
L<C<Scalar>|/type/Scalar> it means "replace the previously stored value with the new one".
Note that subroutine signatures allow passing containers around:
sub f($a is rw) {
$a = 23;
}
my $x = 42;
f($x);
say $x; # OUTPUT: «23»
Inside the subroutine, the lexpad entry for C<$a> points to the same
container that C<$x> points to outside the subroutine. Which is why
assignment to C<$a> also modifies the contents of C<$x>.
Likewise, a routine can return a container if it is marked as C<is rw>:
my $x = 23;
sub f() is rw { $x };
f() = 42;
say $x; # OUTPUT: «42»
For explicit returns, C<return-rw> instead of C<return> must be used.
Returning a container is how C<is rw> attribute accessors work. So
class A {
has $.attr is rw;
}
is equivalent to
class A {
has $!attr;
method attr() is rw { $!attr }
}
Scalar containers are transparent to type checks and most kinds of read-only
accesses. A C<.VAR> makes them visible:
my $x = 42;
say $x.^name; # OUTPUT: «Int»
say $x.VAR.^name; # OUTPUT: «Scalar»
And C<is rw> on a parameter requires the presence of a writable Scalar
container:
sub f($x is rw) { say $x };
f 42;
CATCH { default { say .^name, ': ', .Str } };
# OUTPUT: «X::Parameter::RW: Parameter '$x' expected a writable container, but got Int value»
=head1 Callable containers
Callable containers provide a bridge between the syntax of a
L<C<Routine>|/type/Routine> call and the actual call of the method
L<CALL-ME|/type/Callable#method_CALL-ME> of the object that is stored in the
container. The sigil C<&> is required when declaring the container and has to be
omitted when executing the L<C<Callable>|/type/Callable>. The default type constraint is
L<C<Callable>|/type/Callable>.
my &callable = -> $ν { say "$ν is ", $ν ~~ Int ?? "whole" !! "not whole" }
callable(⅓); # OUTPUT: «0.333333 is not whole»
callable(3); # OUTPUT: «3 is whole»
The sigil has to be provided when referring to the value stored in the
container. This in turn allows L<C<Routine>|/type/Routine>s to be used as
L<arguments|/language/signatures#Constraining_signatures_of_Callables> to calls.
sub f() {}
my &g = sub {}
sub caller(&c1, &c2){ c1, c2 }
caller(&f, &g);
=head1 Binding
Next to assignment, Raku also supports I<binding> with the C<:=> operator.
When binding a value or a container to a variable, the lexpad entry of the
variable is modified (and not just the container it points to). If you write
my $x := 42;
then the lexpad entry for C<$x> directly points to the L<C<Int>|/type/Int> 42. Which
means that you cannot assign to it anymore:
my $x := 42;
$x = 23;
CATCH { default { say .^name, ': ', .Str } };
# OUTPUT: «X::AdHoc: Cannot assign to an immutable value»
You can also bind variables to other variables:
my $a = 0;
my $b = 0;
$a := $b;
$b = 42;
say $a; # OUTPUT: «42»
Here, after the initial binding, the lexpad entries for C<$a> and C<$b> both
point to the same scalar container, so assigning to one variable also
changes the contents of the other.
You've seen this situation before: it is exactly what happened with the
signature parameter marked as C<is rw>.
X<|Language,\ (container binding)>
Sigilless variables and parameters with the trait C<is raw> always
bind (whether C<=> or C<:=> is used):
my $a = 42;
my \b = $a;
b++;
say $a; # OUTPUT: «43»
sub f($c is raw) { $c++ }
f($a);
say $a; # OUTPUT: «44»
=head1 Scalar containers and listy things
There are a number of positional container types with slightly different
semantics in Raku. The most basic one is L<C<List>|/type/List>, which
is created by the comma operator.
say (1, 2, 3).^name; # OUTPUT: «List»
A list is immutable, which means you cannot change the number of elements
in a list. But if one of the elements happens to be a scalar container,
you can still assign to it:
my $x = 42;
($x, 1, 2)[0] = 23;
say $x; # OUTPUT: «23»
($x, 1, 2)[1] = 23; # Cannot modify an immutable value
CATCH { default { say .^name, ': ', .Str } };
# OUTPUT: «X::Assignment::RO: Cannot modify an immutable Int»
So the list doesn't care about whether its elements are values or
containers, they just store and retrieve whatever was given to them.
Lists can also be lazy; in that case, elements at the end are generated on
demand from an iterator.
An L<C<Array>|/type/Array> is just like a list, except that it forces all its elements to
be containers, which means that you can always assign to elements:
my @a = 1, 2, 3;
@a[0] = 42;
say @a; # OUTPUT: «[42 2 3]»
C<@a> actually stores three scalar containers. C<@a[0]> returns one of
them, and the assignment operator replaces the integer value stored in that
container with the new one, C<42>.
=head1 Assigning and binding to array variables
Assignment to a scalar variable and to an array variable both do
the same thing: discard the old value(s), and enter some new value(s).
Nevertheless, it's easy to observe how different they are:
my $x = 42; say $x.^name; # OUTPUT: «Int»
my @a = 42; say @a.^name; # OUTPUT: «Array»
This is because the L<C<Scalar>|/type/Scalar> container type hides itself well, but L<C<Array>|/type/Array>
makes no such effort. Also assignment to an array variable is coercive, so
you can assign a non-array value to an array variable.
To place a non-L<C<Array>|/type/Array> into an array variable, binding works:
my @a := (1, 2, 3);
say @a.^name; # OUTPUT: «List»
=head1 Binding to array elements
As a curious side note, Raku supports binding to array elements:
my @a = (1, 2, 3);
@a[0] := my $x;
$x = 42;
say @a; # OUTPUT: «[42 2 3]»
If you've read and understood the previous explanations, it is now time to
wonder how this can possibly work. After all, binding to a variable requires a
lexpad entry for that variable, and while there is one for an array, there
aren't lexpad entries for each array element, because you cannot expand the
lexpad at runtime.
The answer is that binding to array elements is recognized at the syntax
level and instead of emitting code for a normal binding operation, a special
method (called L<C<BIND-POS>|/routine/BIND-POS>) is called on the
array. This method handles binding to array elements. There is also an
equivalent method for binding to hash elements as well (called
L<C<BIND-KEY>|/routine/BIND-KEY>)
Note that, while supported, one should generally avoid directly binding
uncontainerized things into array elements. Doing so may produce
counter-intuitive results when the array is used later.
my @a = (1, 2, 3);
@a[0] := 42; # This is not recommended, use assignment instead.
my $b := 42;
@a[1] := $b; # Nor is this.
@a[2] = $b; # ...but this is fine.
@a[1, 2] := 1, 2; # runtime error: X::Bind::Slice
CATCH { default { say .^name, ': ', .Str } };
# OUTPUT: «X::Bind::Slice: Cannot bind to Array slice»
Operations that mix Lists and Arrays generally protect against such
a thing happening accidentally.
=head1 Flattening, items and containers
The C<%> and C<@> sigils in Raku generally indicate multiple values
to an iteration construct, whereas the C<$> sigil indicates only one value.
my @a = 1, 2, 3;
for @a { }; # 3 iterations
my $a = (1, 2, 3);
for $a { }; # 1 iteration
C<@>-sigiled variables do not flatten in list context:
my @a = 1, 2, 3;
my @b = @a, 4, 5;
say @b.elems; # OUTPUT: «3»
There are operations that flatten out sublists that are not inside a scalar
container: slurpy parameters (C<*@a>) and explicit calls to C<flat>:
my @a = 1, 2, 3;
say (flat @a, 4, 5).elems; # OUTPUT: «5»
sub f(*@x) { @x.elems };
say f @a, 4, 5; # OUTPUT: «5»
You can also use C<|> to create a L<C<Slip>|/type/Slip>, introducing a list into
the other.
my @l := 1, 2, (3, 4, (5, 6)), [7, 8, (9, 10)];
say (|@l, 11, 12); # OUTPUT: «(1 2 (3 4 (5 6)) [7 8 (9 10)] 11 12)»
say (flat @l, 11, 12) # OUTPUT: «(1 2 3 4 5 6 7 8 (9 10) 11 12)»
In the first case, every element of C<@l> is I<slipped> as the corresponding
elements of the resulting list. C<flat>, in the other hand, I<flattens> all
elements including the elements of the included array, except for C«(9 10)».
As hinted above, scalar containers prevent that flattening:
sub f(*@x) { @x.elems };
my @a = 1, 2, 3;
say f $@a, 4, 5; # OUTPUT: «3»
The C<@> character can also be used as a prefix to coerce the argument to a
list, thus removing a scalar container:
my $x = (1, 2, 3);
.say for @$x; # 3 iterations
However, the I<decont> operator C«<>» is more appropriate to decontainerize
items that aren't lists:
my $x = ^Inf .grep: *.is-prime;
say "$_ is prime" for @$x; # WRONG! List keeps values, thus leaking memory
say "$_ is prime" for $x<>; # RIGHT. Simply decontainerize the Seq
my $y := ^Inf .grep: *.is-prime; # Even better; no Scalars involved at all
Methods generally don't care whether their invocant is in a scalar, so
my $x = (1, 2, 3);
$x.map(*.say); # 3 iterations
maps over a list of three elements, not of one.
=head1 Self-referential data
Container types, including L<C<Array>|/type/Array> and L<C<Hash>|/type/Hash>, allow you to create
self-referential structures.
my @a;
@a[0] = @a;
put @a.raku;
# OUTPUT: «((my @Array_75093712) = [@Array_75093712,])»
Although Raku does not prevent you from creating and using self-referential
data, by doing so you may end up in a loop trying to dump the data. As a
last resort, you can use Promises to L<handle|/type/Promise#method_in> timeouts.
=head1 Type constraints
Any container can have a type constraint in the form of a L<type
object|/language/typesystem#Type_objects> or a
L<subset|/language/typesystem#subset>. Both can be placed between a declarator
and the variable name or after the trait L<of|/type/Variable#trait_of>.
The constraint is a property of the variable, not the container.
subset Three-letter of Str where .chars == 3;
my Three-letter $acronym = "ÞFL";
In this case, the type constraint is the (compile-type defined) subset
C<Three-letter>.
The default type constraint of a L<C<Scalar>|/type/Scalar> container is L<C<Mu>|/type/Mu>.
Introspection of type constraints on containers is provided by C<.VAR.of>
method, which for C<@> and C<%> sigiled variables gives the constraint for
values:
my Str $x;
say $x.VAR.of; # OUTPUT: «(Str)»
my Num @a;
say @a.VAR.of; # OUTPUT: «(Num)»
my Int %h;
say %h.VAR.of; # OUTPUT: «(Int)»
=head2 Definedness constraints
A container can also enforce a variable to be defined. Put a smiley in the
declaration:
my Int:D $def = 3;
say $def; # OUTPUT: «3»
$def = Int; # Typecheck failure
=comment ^^^ fails at runtime, so xt/example-compilation still passes
You'll also need to initialize the variable in the declaration, it can't be
left undefined after all.
It's also possible to have this constraint enforced in all variables declared
in a scope with the
L<default defined variables pragma|/language/variables#Default_defined_variables_pragma>.
People coming from other languages where variables are always defined will
want to have a look.
=head1 Custom containers
To provide custom containers Raku employs the class L<C<Proxy>|/type/Proxy>. Its
constructor takes two arguments, C<FETCH> AND C<STORE>, that point to methods
that are called when values are fetched or stored from the container. Type
checks are not done by the container itself and other restrictions like
readonlyness can be broken. The returned value must therefore be of the same
type as the type of the variable it is bound to. We can use
L<type captures|/language/signatures#Type_captures> to work with types in Raku.
sub lucky(::T $type) {
my T $c-value; # closure variable
return-rw Proxy.new(
FETCH => method () { $c-value },
STORE => method (T $new-value) {
X::OutOfRange.new(what => 'number', got => '13', range => '-∞..12, 14..∞').throw
if $new-value == 13;
$c-value = $new-value;
}
);
}
my Int $a := lucky(Int);
say $a = 12; # OUTPUT: «12»
say $a = 'FOO'; # X::TypeCheck::Binding
say $a = 13; # X::OutOfRange
CATCH { default { say .^name, ': ', .Str } };
=end pod
================================================
FILE: doc/Language/contexts.rakudoc
================================================
=begin pod :kind("Language") :subkind("Language") :category("fundamental")
=TITLE Contexts and contextualizers
=SUBTITLE What are contexts and how to switch into them
Contexts interpret the value of a container.
In Raku, we use the active context to coerce the value of a container into a type
or class, or to decide what to do with it.
Usually, a context receiving an object will, if necessary,
coerce the object by implicitly calling a specific method on it.
=head1 X<Sink|Language,sink context>
The I<sink> context is equivalent to what other languages call C<void>
context. It is the context which does nothing with the
result or return of any code: a term, an operation or a block. In general, when this
context consumes a value or variable a warning or error is issued because the value is being
ignored. Mnemonics for I<sink> relate to being rid of something: water down a
sink's drain; a ship sinking; a heatsink removing warmth.
=begin code
my $sub = -> $a { $a² };
$sub; # OUTPUT: «WARNINGS:Useless use of $sub in sink context (line 1)»
=end code
X<|Language,sinking>
You can force that sink context on L<C<Iterator>|/type/Iterator>s, by
using the L<C<sink-all>|/routine/sink-all> method. L<C<Proc>|/type/Proc>s can also
be L<sunk via the C<sink> method|/type/Proc#method_sink>, forcing them to raise
an exception and not return anything.
Most blocks will warn if evaluated in sink context; however,
L<gather/take blocks|/language/control#gather/take> are explicitly
evaluated in sink context, with values returned explicitly using C<take>:
=for code
my @results = gather for 1..1 { ^10 .map: *.take };
say @results; # OUTPUT: «[0 1 2 3 4 5 6 7 8 9]»
In this example, C<for> is run in sink context, and within it, C<map> is too.
Results are taken explicitly from the loop via gather/take.
In sink context, an object will call its C<sink> method if present:
=begin code
sub foo {
return [<a b c>] does role {
method sink { say "sink called" }
}
}
foo; # OUTPUT: «sink called»
=end code
=head1 X<Number|Language,number context>
This context, and probably all other contexts except I<sink> above, are
I<conversion> or I<interpretation> contexts in the sense that they take an
untyped or typed variable and duck-type it to whatever is needed to perform the
operation. In some cases that will imply a conversion (from L<C<Str>|/type/Str> to
L<C<Numeric>|/type/Numeric>, for instance); in other cases simply an interpretation
(L<C<IntStr>|/type/IntStr> will be interpreted as L<C<Int>|/type/Int> or as
L<C<Str>|/type/Str>).
I<Number context> is called whenever we need to apply a numerical operation on a
variable.
=begin code
my $stringone = "1 ";
my $stringthree = "3 ";
say $stringone + $stringthree; # OUTPUT: «4»
=end code
In the code above, strings will be interpreted in numeric context as long as
there are only a few digits and no other characters. It can have any number of
leading or trailing whitespace, however.
Numeric context can be forced by using arithmetic operators such as C<+> or
C<->. In that context, the L<C<Numeric>|/routine/Numeric> method will be called
if available and the value returned used as the numeric value of the object.
=begin code
my $t = True;
my $f = False;
say $t + $f; # OUTPUT: «1»
say $t.Numeric; # OUTPUT: «1»
say $f.Numeric; # OUTPUT: «0»
my $list= <a b c>;
say True + $list; # OUTPUT: «4»
say +" \n "; # OUTPUT: «0»
=end code
Whitespace in any quantity will be converted to 0, as is shown in the last
statement. In the case of I<listy> things, the numeric value will be in general
equivalent to C<.elems>; in some cases, like
L<C<Thread.numeric>|/routine/Numeric#(Thread)_method_Numeric>, it will return a unique
thread identifier.
=head1 X<String|Language,string context>
In a I<string context>, values can be manipulated as strings. This context is
used, for instance, for coercing non-string values so that they can be printed
to standard output.
=for code :preamble<my $very-complicated-and-hairy-object>
put $very-complicated-and-hairy-object; # OUTPUT: something meaningful
Or when smartmatching to a regular expression:
put 333444777 ~~ /(3+)/; # OUTPUT: «333»
In general, the L<C<Str> routine|/routine/Str> will be called on a variable to
contextualize it; since this method is inherited from L<C<Mu>|/type/Mu>, it is
always present, but it is not always guaranteed to work. In some core classes it
will issue a warning.
L<C<~>|/routine/~> is the (unary) string contextualizer. As an operator, it
concatenates strings, but as a prefix operator it becomes the string context
operator.
=begin code
my @array = [ [1,2,3], [4,5,6]];
say ~@array; # OUTPUT: «1 2 3 4 5 6»
=end code
This will happen also in a
L<I<reduction>|/language/operators#Reduction_operators>
context, when C<[~]> is applied to a list
say [~] [ 3, 5+6i, Set(<a b c>), [1,2,3] ]; # OUTPUT: «35+6ic a b1 2 3»
In that sense, empty lists or other containers will stringify to an empty
string:
say [~] [] ; # OUTPUT: «»
Since
L<C<~> acts also as buffer concatenation operator|/routine/~#(Operators)_infix_~>,
it will have to check that every element is not empty, since a single empty
buffer in string context will behave as a string, thus yielding an error.
say [~] Buf.new(0x3,0x33), Buf.new(0x2,0x22);
# OUTPUT: «Buf:0x<03 33 02 22>»
However,
=begin code
my $non-empty = Buf.new(0x3, 0x33);
my $empty = [];
my $non-empty-also = Buf.new(0x2,0x22);
say [~] $non-empty, $empty, $non-empty-also;
# OUTPUT: «Cannot use a Buf as a string, but you called the Stringy method on it
=end code
Since C<~> is putting in string context the second element of this list,
L<C<~>|/routine/~#(Operators)_infix_~> is going to be
using the second form that applies to strings, thus yielding the shown error.
Simply making sure that everything you concatenate is a buffer will avoid this
problem.
=for code
my $non-empty = Buf.new(0x3, 0x33);
my $empty = Buf.new();
my $non-empty-also = Buf.new(0x2,0x22);
say [~] $non-empty, $empty, $non-empty-also; # OUTPUT: «Buf:0x<03 33 02 22>»
In general, a context will coerce a variable to a particular type by calling the
contextualizer; in the case of mixins, if the context class is mixed in, it will
behave in that way.
my $described-number = 1i but 'Unity in complex plane';
put $described-number; # OUTPUT: «Unity in complex plane»
C<but> creates a mixin, which endows the complex number with a L<C<Str>|/type/Str> method.
C<put> contextualizes it into a string, that is, it calls L<C<Str>|/type/Str>, the string
contextualizer, with the result shown above.
=head1 X<Boolean|Language,Boolean context>
This context will force a variable to be interpreted as C<True> or C<False>.
say "Hey" if 7; # OUTPUT: «Hey»
say "Ahoy" if "";
This context appears in expressions such as C<if> or C<while>, and is
equivalent to calling C<so> on these values.
=for code
say "Hey" if 7.so; # OUTPUT: «Hey»
say "Ahoy" if not set().so; # OUTPUT: «Ahoy»
In general, non-zero, non-empty will be converted to C<True>; zero or empty
will be equivalent to C<False>. But C<.so> can be defined to return any Boolean
value we want, so this is just a rule of thumb.
The L«C<?>|/language/operators#prefix_?» Boolean context operator
and the L«C<!>|/language/operators#prefix_!» negated Boolean context
operator will force the Boolean context on an object.
=for code
say ? 0i; # OUTPUT: «False»
say ! :true; # OUTPUT: «False»
=head1 X<List|Language,list context>
There are actually several different
L<list contexts|/language/list#List_contexts>, which are better explained in
that page. In general, the list contextualizer is the comma C<,>
say (3,).^name; # OUTPUT: «List»
and the method called in that case is also C<.list>
=for code
Any.list.^name; # OUTPUT: «List»
say 3.list.^name; # OUTPUT: «List»
say (^3).list; # OUTPUT: «(0 1 2)»
=head1 Item context
Item or scalar context will deal with complex pieces of data as if they were
a single item. It is forced when you try to assign to a scalar variable
=for code
my $scalar-context = <1 2 3>;
say "→ $_" for $scalar-context; # OUTPUT: «→ 1 2 3»
It can be induced using the C<$> operator, that acts as the contextualizer
operator by calling C<item> as a method or routine
=for code
.say for $(1,2,3); # OUTPUT: «(1 2 3)»
.say for (1,2,3).item; # OUTPUT: «(1 2 3)»
.say for item( 1..3 ); # OUTPUT: «1..3»
Itemization affects only their behavior in list context; however, they will
still keep their L<C<Positional>|/type/Positional> role or other roles they might have:
=for code
$(1,2,3).elems.say; # OUTPUT: «3»
say (1,2,3).item[2]; # OUTPUT: «3»
say $( key => 'value')<key>; # OUTPUT: «value»
Itemization I<containerizes> values in a data structure, keeping them, for
instance, from being flattened into the surrounding list or data structure:
=for code
.say for (1, $(2,3), 4).flat; # OUTPUT: «1(2 3)4»
say (1, $<a b>, 2).elems; # OUTPUT: «3»
The itemizer operator will call the C<.item> method on the object; it can also
be called as a subroutine. Since
L<that is a method inherited from C<Mu>|/type/Mu#method_item>, objects of any
class can be itemized.
=end pod
================================================
FILE: doc/Language/control.rakudoc
================================================
=begin pod :kind("Language") :subkind("Language") :category("fundamental")
=TITLE Control flow
=SUBTITLE Statements used to control the flow of execution
=head1 X<Statements|Control flow,statements>
Raku programs consist of one or more statements. Simple statements
are separated by semicolons. The following program will print "Hello"
and then "World" on the next line.
say "Hello";
say "World";
In most places where spaces appear in a statement, and before the
semicolon, they may be split up over many lines. Also, multiple statements
may appear on the same line. It would be awkward, but the above example could
also be written as:
say
"Hello"; say "World";
=head1 X<Blocks|Control flow,blocks>
Like many other languages, Raku uses C<blocks> enclosed by C<{> and C<}> to
turn a sequence of statements into a
L<C<Block>|/type/Block> that acts as a single one. It is OK
to omit the semicolon between the last statement in a block and the closing
C<}>.
{ say "Hello"; say "World" }
When a block stands alone as a statement, it will be entered immediately
after the previous statement finishes, and the statements inside it will be
executed.
say 1; # OUTPUT: «1»
{ say 2; say 3 }; # OUTPUT: «23»
say 4; # OUTPUT: «4»
Unless it stands alone as a statement, a block simply creates a closure. The
statements inside are not executed immediately. Closures are another topic
and how they are used is explained
L<elsewhere|/language/functions#Closures>. For now it is just
important to understand when blocks run and when they do not:
=for code
say "We get here";
{ say "then here." };
{ say "not here"; 0; } or die;
In the above example, after running the first statement, the first block stands
alone as a second statement, so we run the statement inside it. The second
block is a closure, so instead, it makes an object of type L<C<Block>|/type/Block> but does
not run it. Object instances are usually considered to be true, so the code
does not die, even though that block would evaluate to 0, were it to be
executed. The example does not say what to do with the L<C<Block>|/type/Block> object, so it
just gets thrown away.
Most of the flow control constructs covered below are just ways to tell Raku
when, how, and how many times, to enter blocks like that second block.
Before we go into those, an important side-note on syntax: If there is
nothing (or nothing but comments) on a line after a closing curly brace where
you would normally put semicolon, then you do not need the semicolon:
# All three of these lines can appear as a group, as is, in a program
{ 42.say } # OUTPUT: «42»
{ 43.say } # OUTPUT: «43»
{ 42.say }; { 43.say } # OUTPUT: «4243»
...but:
=begin code :skip-test<syntax error>
{ 42.say } { 43.say } # Syntax error
{ 42.say; } { 43.say } # Also a syntax error, of course
=end code
So, be careful when you backspace in a line-wrapping editor:
=begin code :skip-test<syntax error>
{ "Without semicolons line-wrapping can be a bit treacherous.".say } \
{ 43.say } # Syntax error
=end code
You have to watch out for this in most languages anyway to prevent things
from getting accidentally commented out. Many of the examples below may
have unnecessary semicolons for clarity.
Class bodies behave like simple blocks for any top level expression; same goes
to roles and other packages, like grammars (which are actually classes)
or modules.
=begin code :skip-test<dies deliberately>
class C {
say "I live";
die "I will never live!"
};
my $c = C.new; │
# OUTPUT: Fails and writes «I liveI will never live!
=end code
This block will first run the first statement, and then C<die> printing the
second statement. C<$c> will never get a value.
=head1 X<Phasers|Control flow,Phasers>
Blocks may have I<phasers>: special labeled blocks that break their execution
into phases that run in particular phases. See the page
L<phasers|/language/phasers> for the details.
=head1 X<do|Control flow,do>
The simplest way to run a block where it cannot be a stand-alone statement
is by writing C<do> before it:
=for code
# This dies half of the time
do { say "Heads I win, tails I die."; Bool.pick } or die; say "I win.";
Note that you need a space between the C<do> and the block.
The whole C<do {...}> evaluates to the final value of the block. The block
will be run when that value is needed in order to evaluate the rest of the
expression. So:
False and do { 42.say };
...will not say 42. However, the block is only evaluated once each time
the expression it is contained in is evaluated:
# This says "(..1 ..2 ..3)" not "(..1 ...2 ....3)"
my $f = "."; say do { $f ~= "." } X~ 1, 2, 3;
In other words, it follows the same
L<reification|/language/glossary#Reify> rules as everything else.
Technically, C<do> is a loop which runs exactly one iteration.
A C<do> may also be used on a bare statement (without curly braces)
but this is mainly just useful for avoiding the syntactical need to
parenthesize a statement if it is the last thing in an expression:
=for code
3, do if 1 { 2 } ; # OUTPUT: «(3, 2)»
3, (if 1 { 2 }) ; # OUTPUT: «(3, 2)»
=for code :skip-test<syntax error>
3, if 1 { 2 } ; # Syntax error
As a consequence, C<do> does not run blocks that, by their syntax, must
be functions. For example, if C«->» is used to specify a
L<signature|/language/syntax#Block_declaration>, C<do> treats these as
single-expression statements.
Thus, adding C«->» to our first example prevents the closure from
being evaluated:
=for code
# This never dies and never prints "Heads I win, tails I die."
do -> { say "Heads I win, tails I die."; Bool.pick } or die; say "I win.";
=head1 X<start|Control flow,start>
The simplest way to run a statement or block B<asynchronously> is by writing C<start>
before it:
=for code
start { sleep 1; say "done" }
say "working";
# working, done
Note that you need a space between the C<start> and the block. In the example
above, the C<start> block is in sink context since it's not assigned to a
variable. From version 6.d, these sunk blocks have an exception handler
attached:
=for code
start { die "We're dead"; }
say "working";
sleep 10;
This code will print C<Unhandled exception in code scheduled on thread 4 We're
dead> in version 6.d, while it will simply get out after waiting for 10 seconds
in version 6.c.
The C<start {...}> immediately returns a L<C<Promise>|/type/Promise> that can be safely ignored
if you are not interested in the result of the block. If you B<are> interested
in the final value of the block, you can call the C<.result> method on the
returned promise. So:
my $promise = start { sleep 10; 42 }
# ... do other stuff
say "The result is $promise.result()";
If the code inside the block has not finished, the call to C<.result> will
wait until it is done.
A C<start> used on a bare statement is useful when the only thing to do
asynchronously is a subroutine or method:
sub get42 { 42 }
my $promise = start get42;
say $promise.result; # OUTPUT: «42»
Note that start code does not have access to the special
variables L«C<$!>|/syntax/$!» and L«C<$/>|/syntax/$$SOLIDUS» of its outer
block, but receives new ones, so every asynchronous task has its
per-task state.
Thus, C<try> expressions and regex matches executed in the
asynchronous task have their per-task state.
'a' ~~ /a/; # $/ is set to 「a」
try die; # $! is defined now with an anonymous AdHoc exception
# as a code block
await start { say $! }; # OUTPUT: «Nil»
await start { say $/ }; # OUTPUT: «Nil»
# as a single statement
await start $!.say; # OUTPUT: «Nil»
await start $/.say; # OUTPUT: «Nil»
=head1 X<if|Control flow,if>
To conditionally run a block of code, use an C<if> followed by a condition.
The condition, an expression, will be evaluated immediately after the
statement before the C<if> finishes. The block attached to the condition will
only be evaluated if the condition means C<True> when coerced to L<C<Bool>|/type/Bool>.
Unlike some languages the condition does not have to be parenthesized,
instead the C<{> and C<}> around the block are mandatory:
=for code
if 1 { "1 is true".say } ; # says "1 is true"
=for code :skip-test<syntax error>
if 1 "1 is true".say ; # syntax error, missing block
=for code
if 0 { "0 is true".say } ; # does not say anything, because 0 is false
=for code
if 42.say and 0 { 43.say }; # says "42" but does not say "43"
There is also a form of C<if> called a "statement modifier" form. In this
case, the C<if> and the condition come after the code you want to run
conditionally. Do note that the condition is still always evaluated first:
43.say if 42.say and 0; # says "42" but does not say "43"
43.say if 42.say and 1; # says "42" and then says "43"
say "It is easier to read code when 'if's are kept on left of screen"
if True; # says the above, because it is true
{ 43.say } if True; # says "43" as well
The statement modifier form is probably best used sparingly.
The C<if> statement itself will either L<C<Slip>|/type/Slip> us an empty list, if
it does not run the block, or it will return the value which the block produces:
my $d = 0; say (1, (if 0 { $d += 42; 2; }), 3, $d); # says "(1 3 0)"
my $c = 0; say (1, (if 1 { $c += 42; 2; }), 3, $c); # says "(1 2 3 42)"
say (1, (if 1 { 2, 2 }), 3); # does not slip, says "(1 (2 2) 3)"
For the statement modifier it is the same, except you have the value
of the statement instead of a block:
say (1, (42 if True) , 2); # says "(1 42 2)"
say (1, (42 if False), 2); # says "(1 2)"
say (1, 42 if False , 2); # says "(1 42)" because "if False, 2" is true
The C<if> does not change the topic (C<$_>) by default. In order to access
the value which the conditional expression produced, you have to ask
for it more strongly:
$_ = 1; if 42 { $_.say } ; # says "1"
$_ = 1; if 42 -> $_ { $_.say } ; # says "42"
$_ = 1; if 42 -> $a { $_.say; $a.say } ; # says "1" then says "42"
$_ = 1; if 42 { $_.say; $^a.say } ; # says "1" then says "42"
This is especially useful for patterns of the kind
"if something does not evaluate to False, do something with it":
sub get-user-id($username) { #`(return 0 if no such username exists) }
if prompt 'Enter username: ' -> $username {
if get-user-id($username) -> $user-id {
say "Found id $user-id for name $username";
}
}
Here C<$username> and C<$user-id> are only defined inside
their respective C<if> block that guarantees their being C<True>.
This gives this solution an advantage
over the more conventional C<my $username = …; if $username {…}>.
Compare L<C<with>|/language/control#with>, which tests
for definedness rather than truth, and topicalizes by default.
(The second C<if> in the above example could be replaced by C<with> if the routine
C<get-user-id> returned L<C<Nil>|/type/Nil> rather than 0 for nonexistent usernames.)
=head2 X<C<else/elsif>|Control flow,else elsif>
A compound conditional may be produced by following an C<if> conditional
with C<else> to provide an alternative block to run when the conditional
expression is false:
=for code
if 0 { say "no" } else { say "yes" } ; # says "yes"
if 0 { say "no" } else{ say "yes" } ; # says "yes", space is not required
The C<else> cannot be separated from the conditional statement by a
semicolon, but as a special case, it is OK to have a newline.
=for code :skip-test<syntax error>
if 0 { say "no" }; else { say "yes" } ; # syntax error
=for code
if 0 { say "no" }
else { say "yes" } ; # says "yes"
Additional conditions may be sandwiched between the C<if> and the C<else> using
C<elsif>. An extra condition will only be evaluated if all the conditions
before it were false, and only the block next to the first true condition will
be run. You can end with an C<elsif> instead of an C<else> if you want.
if 0 { say "no" } elsif False { say "NO" } else { say "yes" } # says "yes"
if 0 { say "no" } elsif True { say "YES" } else { say "yes" } # says "YES"
if 0 { say "no" } elsif False { say "NO" } # does not say anything
sub right { "Right!".say; True }
sub wrong { "Wrong!".say; False }
if wrong() { say "no" } elsif right() { say "yes" } else { say "maybe" }
# The above says "Wrong!" then says "Right!" then says "yes"
You cannot use the statement modifier form with C<else> or C<elsif>:
=for code :skip-test<syntax error>
42.say if 0 else { 43.say } # syntax error
All the same rules for semicolons and newlines apply, consistently
=for code :skip-test<syntax error>
if 0 { say 0 }; elsif 1 { say 1 } else { say "how?" } ; # syntax error
if 0 { say 0 } elsif 1 { say 1 }; else { say "how?" } ; # syntax error
=for code
if 0 { say 0 } elsif 1 { say 1 } else { say "how?" } ; # says "1"
if 0 { say 0 } elsif 1 { say 1 }
else { say "how?" } ; # says "1"
if 0 { say 0 }
elsif 1 { say 1 } else { say "how?" } ; # says "1"
if 0 { say "no" }
elsif False { say "NO" }
else { say "yes" } ; # says "yes"
The whole thing either L<C<Slip>|/type/Slip>s us an empty list (if no blocks
were run) or returns the value produced by the block that did run:
my $d = 0; say (1,
(if 0 { $d += 42; "two"; } elsif False { $d += 43; 2; }),
3, $d); # says "(1 3 0)"
my $c = 0; say (1,
(if 0 { $c += 42; "two"; } else { $c += 43; 2; }),
3, $c); # says "(1 2 3 43)"
It's possible to obtain the value of the previous expression inside an
C<else>, which could be from C<if> or the last C<elsif> if any are
present:
$_ = 1; if 0 { } else -> $a { "$_ $a".say } ; # says "1 0"
$_ = 1; if False { } else -> $a { "$_ $a".say } ; # says "1 False"
if False { } elsif 0 { } else -> $a { $a.say } ; # says "0"
=head1 X<C<unless>|Control flow,unless>
When you get sick of typing "if not (X)" you may use C<unless> to invert
the sense of a conditional statement. You cannot use C<else> or C<elsif>
with C<unless> because that ends up getting confusing. Other than those
two differences C<unless> works the same as L<if|#if>:
=for code
unless 1 { "1 is false".say } ; # does not say anything, since 1 is true
=for code :skip-test<syntax error>
unless 1 "1 is false".say ; # syntax error, missing block
=for code
unless 0 { "0 is false".say } ; # says "0 is false"
unless 42.say and 1 { 43.say } ; # says "42" but does not say "43"
43.say unless 42.say and 0; # says "42" and then says "43"
43.say unless 42.say and 1; # says "42" but does not say "43"
$_ = 1; unless 0 { $_.say } ; # says "1"
$_ = 1; unless 0 -> $_ { $_.say } ; # says "0"
$_ = 1; unless False -> $a { $a.say } ; # says "False"
my $c = 0; say (1, (unless 0 { $c += 42; 2; }), 3, $c); # says "(1 2 3 42)"
my $d = 0; say (1, (unless 1 { $d += 42; 2; }), 3, $d); # says "(1 3 0)"
=head1 X<C<with orwith without>|Control flow,with orwith without>
The C<with> statement is like C<if>, but tests for definedness rather than
truth, and it topicalizes on the condition, much like C<given>:
with "abc".index("a") { .say } # prints 0
Similarly to C<elsif>, C<orwith> may be used to chain definedness tests:
# The below code says "Found 'a' at 0"
my $s = "abc";
with $s.index("a") { say "Found 'a' at $_" }
orwith $s.index("b") { say "Found 'b' at $_" }
orwith $s.index("c") { say "Found 'c' at $_" }
else { say "Didn't find 'a', 'b' or 'c'" }
You may intermix C<if>-based and C<with>-based clauses.
# This says "Yes"
if 0 { say "No" } orwith Nil { say "No" } orwith 0 { say "Yes" };
As with C<un
gitextract_770pvioc/
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ └── bug-report-or-feature-request.md
│ ├── pull_request_template.md
│ └── workflows/
│ └── test.yml
├── .gitignore
├── Build.rakumod
├── CONTRIBUTING.md
├── CREDITS
├── LICENSE
├── META6.json
├── Makefile
├── README.md
├── doc/
│ ├── Language/
│ │ ├── 101-basics.rakudoc
│ │ ├── REPL.rakudoc
│ │ ├── about.rakudoc
│ │ ├── brackets.rakudoc
│ │ ├── classtut.rakudoc
│ │ ├── community.rakudoc
│ │ ├── compilation.rakudoc
│ │ ├── concurrency.rakudoc
│ │ ├── containers.rakudoc
│ │ ├── contexts.rakudoc
│ │ ├── control.rakudoc
│ │ ├── create-cli.rakudoc
│ │ ├── distributions/
│ │ │ ├── configuration-structure.rakudoc
│ │ │ ├── introduction.rakudoc
│ │ │ ├── testing.rakudoc
│ │ │ ├── tools.rakudoc
│ │ │ └── uploading.rakudoc
│ │ ├── enumeration.rakudoc
│ │ ├── exceptions.rakudoc
│ │ ├── experimental.rakudoc
│ │ ├── faq.rakudoc
│ │ ├── filename-extensions.rakudoc
│ │ ├── functions.rakudoc
│ │ ├── glossary.rakudoc
│ │ ├── grammar_tutorial.rakudoc
│ │ ├── grammars.rakudoc
│ │ ├── hashmap.rakudoc
│ │ ├── haskell-to-p6.rakudoc
│ │ ├── intro.rakudoc
│ │ ├── io-guide.rakudoc
│ │ ├── io.rakudoc
│ │ ├── ipc.rakudoc
│ │ ├── iterating.rakudoc
│ │ ├── js-nutshell.rakudoc
│ │ ├── list.rakudoc
│ │ ├── making-modules/
│ │ │ ├── code.rakudoc
│ │ │ └── introduction.rakudoc
│ │ ├── math.rakudoc
│ │ ├── module-packages.rakudoc
│ │ ├── modules-core.rakudoc
│ │ ├── modules-extra.rakudoc
│ │ ├── modules.rakudoc
│ │ ├── mop.rakudoc
│ │ ├── nativecall.rakudoc
│ │ ├── nativetypes.rakudoc
│ │ ├── newline.rakudoc
│ │ ├── numerics.rakudoc
│ │ ├── objects.rakudoc
│ │ ├── operators.rakudoc
│ │ ├── optut.rakudoc
│ │ ├── packages.rakudoc
│ │ ├── performance.rakudoc
│ │ ├── perl-func.rakudoc
│ │ ├── perl-nutshell.rakudoc
│ │ ├── perl-op.rakudoc
│ │ ├── perl-overview.rakudoc
│ │ ├── perl-syn.rakudoc
│ │ ├── perl-var.rakudoc
│ │ ├── phasers.rakudoc
│ │ ├── pod.rakudoc
│ │ ├── pragmas.rakudoc
│ │ ├── py-nutshell.rakudoc
│ │ ├── quoting.rakudoc
│ │ ├── rb-nutshell.rakudoc
│ │ ├── regexes-best-practices.rakudoc
│ │ ├── regexes.rakudoc
│ │ ├── setbagmix.rakudoc
│ │ ├── signatures.rakudoc
│ │ ├── slangs.rakudoc
│ │ ├── statement-prefixes.rakudoc
│ │ ├── structures.rakudoc
│ │ ├── subscripts.rakudoc
│ │ ├── syntax.rakudoc
│ │ ├── system.rakudoc
│ │ ├── tables.rakudoc
│ │ ├── temporal.rakudoc
│ │ ├── terms.rakudoc
│ │ ├── testing.rakudoc
│ │ ├── traits.rakudoc
│ │ ├── traps.rakudoc
│ │ ├── typesystem.rakudoc
│ │ ├── unicode.rakudoc
│ │ ├── unicode_ascii.rakudoc
│ │ ├── unicode_entry.rakudoc
│ │ ├── using-modules/
│ │ │ ├── code.rakudoc
│ │ │ ├── finding-installing.rakudoc
│ │ │ └── introduction.rakudoc
│ │ └── variables.rakudoc
│ ├── Native/
│ │ └── int.rakudoc
│ ├── Programs/
│ │ ├── 01-debugging.rakudoc
│ │ ├── 02-reading-docs.rakudoc
│ │ ├── 03-environment-variables.rakudoc
│ │ ├── 04-running-raku.rakudoc
│ │ └── README.md
│ ├── Type/
│ │ ├── AST.rakudoc
│ │ ├── Allomorph.rakudoc
│ │ ├── Any.rakudoc
│ │ ├── Array.rakudoc
│ │ ├── Associative.rakudoc
│ │ ├── Attribute.rakudoc
│ │ ├── Backtrace/
│ │ │ └── Frame.rakudoc
│ │ ├── Backtrace.rakudoc
│ │ ├── Bag.rakudoc
│ │ ├── BagHash.rakudoc
│ │ ├── Baggy.rakudoc
│ │ ├── Blob.rakudoc
│ │ ├── Block.rakudoc
│ │ ├── Bool.rakudoc
│ │ ├── Buf.rakudoc
│ │ ├── CX/
│ │ │ ├── Done.rakudoc
│ │ │ ├── Emit.rakudoc
│ │ │ ├── Last.rakudoc
│ │ │ ├── Next.rakudoc
│ │ │ ├── Proceed.rakudoc
│ │ │ ├── Redo.rakudoc
│ │ │ ├── Return.rakudoc
│ │ │ ├── Succeed.rakudoc
│ │ │ ├── Take.rakudoc
│ │ │ └── Warn.rakudoc
│ │ ├── CallFrame.rakudoc
│ │ ├── Callable.rakudoc
│ │ ├── Cancellation.rakudoc
│ │ ├── Capture.rakudoc
│ │ ├── Channel.rakudoc
│ │ ├── Code.rakudoc
│ │ ├── Collation.rakudoc
│ │ ├── CompUnit/
│ │ │ ├── PrecompilationRepository.rakudoc
│ │ │ ├── Repository/
│ │ │ │ ├── FileSystem.rakudoc
│ │ │ │ ├── Installation.rakudoc
│ │ │ │ └── Unknown.rakudoc
│ │ │ └── Repository.rakudoc
│ │ ├── CompUnit.rakudoc
│ │ ├── Compiler.rakudoc
│ │ ├── Complex.rakudoc
│ │ ├── ComplexStr.rakudoc
│ │ ├── Cool.rakudoc
│ │ ├── CurrentThreadScheduler.rakudoc
│ │ ├── Date.rakudoc
│ │ ├── DateTime.rakudoc
│ │ ├── Dateish.rakudoc
│ │ ├── Distribution/
│ │ │ ├── Hash.rakudoc
│ │ │ ├── Locally.rakudoc
│ │ │ ├── Path.rakudoc
│ │ │ └── Resource.rakudoc
│ │ ├── Distribution.rakudoc
│ │ ├── Distro.rakudoc
│ │ ├── Duration.rakudoc
│ │ ├── Encoding/
│ │ │ └── Registry.rakudoc
│ │ ├── Encoding.rakudoc
│ │ ├── Endian.rakudoc
│ │ ├── Enumeration.rakudoc
│ │ ├── Exception.rakudoc
│ │ ├── Failure.rakudoc
│ │ ├── FatRat.rakudoc
│ │ ├── ForeignCode.rakudoc
│ │ ├── Format.rakudoc
│ │ ├── Formatter.rakudoc
│ │ ├── Grammar.rakudoc
│ │ ├── Hash.rakudoc
│ │ ├── HyperSeq.rakudoc
│ │ ├── HyperWhatever.rakudoc
│ │ ├── IO/
│ │ │ ├── ArgFiles.rakudoc
│ │ │ ├── CatHandle.rakudoc
│ │ │ ├── Handle.rakudoc
│ │ │ ├── Notification/
│ │ │ │ └── Change.rakudoc
│ │ │ ├── Notification.rakudoc
│ │ │ ├── Path/
│ │ │ │ ├── Cygwin.rakudoc
│ │ │ │ ├── Parts.rakudoc
│ │ │ │ ├── QNX.rakudoc
│ │ │ │ ├── Unix.rakudoc
│ │ │ │ └── Win32.rakudoc
│ │ │ ├── Path.rakudoc
│ │ │ ├── Pipe.rakudoc
│ │ │ ├── Socket/
│ │ │ │ ├── Async/
│ │ │ │ │ └── ListenSocket.rakudoc
│ │ │ │ ├── Async.rakudoc
│ │ │ │ └── INET.rakudoc
│ │ │ ├── Socket.rakudoc
│ │ │ ├── Spec/
│ │ │ │ ├── Cygwin.rakudoc
│ │ │ │ ├── QNX.rakudoc
│ │ │ │ ├── Unix.rakudoc
│ │ │ │ └── Win32.rakudoc
│ │ │ ├── Spec.rakudoc
│ │ │ └── Special.rakudoc
│ │ ├── IO.rakudoc
│ │ ├── Instant.rakudoc
│ │ ├── Int.rakudoc
│ │ ├── IntStr.rakudoc
│ │ ├── Iterable.rakudoc
│ │ ├── IterationBuffer.rakudoc
│ │ ├── Iterator.rakudoc
│ │ ├── Junction.rakudoc
│ │ ├── Kernel.rakudoc
│ │ ├── Label.rakudoc
│ │ ├── List.rakudoc
│ │ ├── Lock/
│ │ │ ├── Async.rakudoc
│ │ │ └── ConditionVariable.rakudoc
│ │ ├── Lock.rakudoc
│ │ ├── Macro.rakudoc
│ │ ├── Map.rakudoc
│ │ ├── Match.rakudoc
│ │ ├── Metamodel/
│ │ │ ├── AttributeContainer.rakudoc
│ │ │ ├── C3MRO.rakudoc
│ │ │ ├── ClassHOW.rakudoc
│ │ │ ├── ConcreteRoleHOW.rakudoc
│ │ │ ├── CurriedRoleHOW.rakudoc
│ │ │ ├── DefiniteHOW.rakudoc
│ │ │ ├── Documenting.rakudoc
│ │ │ ├── EnumHOW.rakudoc
│ │ │ ├── Finalization.rakudoc
│ │ │ ├── MROBasedMethodDispatch.rakudoc
│ │ │ ├── MethodContainer.rakudoc
│ │ │ ├── MethodDelegation.rakudoc
│ │ │ ├── Mixins.rakudoc
│ │ │ ├── MultipleInheritance.rakudoc
│ │ │ ├── Naming.rakudoc
│ │ │ ├── PackageHOW.rakudoc
│ │ │ ├── ParametricRoleGroupHOW.rakudoc
│ │ │ ├── ParametricRoleHOW.rakudoc
│ │ │ ├── Primitives.rakudoc
│ │ │ ├── PrivateMethodContainer.rakudoc
│ │ │ ├── RoleContainer.rakudoc
│ │ │ ├── RolePunning.rakudoc
│ │ │ ├── Stashing.rakudoc
│ │ │ ├── Trusting.rakudoc
│ │ │ ├── TypePretense.rakudoc
│ │ │ └── Versioning.rakudoc
│ │ ├── Method.rakudoc
│ │ ├── Mix.rakudoc
│ │ ├── MixHash.rakudoc
│ │ ├── Mixy.rakudoc
│ │ ├── Mu.rakudoc
│ │ ├── NFC.rakudoc
│ │ ├── NFD.rakudoc
│ │ ├── NFKC.rakudoc
│ │ ├── NFKD.rakudoc
│ │ ├── Nil.rakudoc
│ │ ├── Num.rakudoc
│ │ ├── NumStr.rakudoc
│ │ ├── Numeric.rakudoc
│ │ ├── ObjAt.rakudoc
│ │ ├── Order.rakudoc
│ │ ├── Pair.rakudoc
│ │ ├── Parameter.rakudoc
│ │ ├── Perl.rakudoc
│ │ ├── Pod/
│ │ │ ├── Block/
│ │ │ │ ├── Code.rakudoc
│ │ │ │ ├── Comment.rakudoc
│ │ │ │ ├── Declarator.rakudoc
│ │ │ │ ├── Named.rakudoc
│ │ │ │ ├── Para.rakudoc
│ │ │ │ └── Table.rakudoc
│ │ │ ├── Block.rakudoc
│ │ │ ├── Defn.rakudoc
│ │ │ ├── FormattingCode.rakudoc
│ │ │ ├── Heading.rakudoc
│ │ │ └── Item.rakudoc
│ │ ├── Positional.rakudoc
│ │ ├── PositionalBindFailover.rakudoc
│ │ ├── PredictiveIterator.rakudoc
│ │ ├── Proc/
│ │ │ └── Async.rakudoc
│ │ ├── Proc.rakudoc
│ │ ├── Promise.rakudoc
│ │ ├── PromiseStatus.rakudoc
│ │ ├── Proxy.rakudoc
│ │ ├── PseudoStash.rakudoc
│ │ ├── QuantHash.rakudoc
│ │ ├── RaceSeq.rakudoc
│ │ ├── Raku.rakudoc
│ │ ├── RakuAST/
│ │ │ ├── Doc/
│ │ │ │ ├── Block.rakudoc
│ │ │ │ ├── Declarator.rakudoc
│ │ │ │ ├── DeclaratorTarget.rakudoc
│ │ │ │ ├── Markup.rakudoc
│ │ │ │ └── Paragraph.rakudoc
│ │ │ └── Doc.rakudoc
│ │ ├── RakuAST.rakudoc
│ │ ├── Range.rakudoc
│ │ ├── Rat.rakudoc
│ │ ├── RatStr.rakudoc
│ │ ├── Rational.rakudoc
│ │ ├── Real.rakudoc
│ │ ├── Regex.rakudoc
│ │ ├── Routine/
│ │ │ └── WrapHandle.rakudoc
│ │ ├── Routine.rakudoc
│ │ ├── Scalar.rakudoc
│ │ ├── Scheduler.rakudoc
│ │ ├── Semaphore.rakudoc
│ │ ├── Seq.rakudoc
│ │ ├── Sequence.rakudoc
│ │ ├── Set.rakudoc
│ │ ├── SetHash.rakudoc
│ │ ├── Setty.rakudoc
│ │ ├── Signal.rakudoc
│ │ ├── Signature.rakudoc
│ │ ├── Slip.rakudoc
│ │ ├── Stash.rakudoc
│ │ ├── Str.rakudoc
│ │ ├── StrDistance.rakudoc
│ │ ├── Stringy.rakudoc
│ │ ├── Sub.rakudoc
│ │ ├── Submethod.rakudoc
│ │ ├── Supplier/
│ │ │ └── Preserving.rakudoc
│ │ ├── Supplier.rakudoc
│ │ ├── Supply.rakudoc
│ │ ├── Systemic.rakudoc
│ │ ├── Tap.rakudoc
│ │ ├── Telemetry/
│ │ │ ├── Instrument/
│ │ │ │ ├── Thread.rakudoc
│ │ │ │ ├── ThreadPool.rakudoc
│ │ │ │ └── Usage.rakudoc
│ │ │ ├── Period.rakudoc
│ │ │ └── Sampler.rakudoc
│ │ ├── Telemetry.rakudoc
│ │ ├── Test.rakudoc
│ │ ├── Thread.rakudoc
│ │ ├── ThreadPoolScheduler.rakudoc
│ │ ├── UInt.rakudoc
│ │ ├── Uni.rakudoc
│ │ ├── Unicode.rakudoc
│ │ ├── VM.rakudoc
│ │ ├── ValueObjAt.rakudoc
│ │ ├── Variable.rakudoc
│ │ ├── Version.rakudoc
│ │ ├── Whatever.rakudoc
│ │ ├── WhateverCode.rakudoc
│ │ ├── X/
│ │ │ ├── AdHoc.rakudoc
│ │ │ ├── Anon/
│ │ │ │ ├── Augment.rakudoc
│ │ │ │ └── Multi.rakudoc
│ │ │ ├── Assignment/
│ │ │ │ └── RO.rakudoc
│ │ │ ├── Attribute/
│ │ │ │ ├── NoPackage.rakudoc
│ │ │ │ ├── Package.rakudoc
│ │ │ │ ├── Required.rakudoc
│ │ │ │ └── Undeclared.rakudoc
│ │ │ ├── Augment/
│ │ │ │ └── NoSuchType.rakudoc
│ │ │ ├── Bind/
│ │ │ │ ├── NativeType.rakudoc
│ │ │ │ └── Slice.rakudoc
│ │ │ ├── Bind.rakudoc
│ │ │ ├── Caller/
│ │ │ │ └── NotDynamic.rakudoc
│ │ │ ├── Cannot/
│ │ │ │ ├── Empty.rakudoc
│ │ │ │ └── Lazy.rakudoc
│ │ │ ├── Channel/
│ │ │ │ ├── ReceiveOnClosed.rakudoc
│ │ │ │ └── SendOnClosed.rakudoc
│ │ │ ├── Comp.rakudoc
│ │ │ ├── Composition/
│ │ │ │ └── NotComposable.rakudoc
│ │ │ ├── Constructor/
│ │ │ │ └── Positional.rakudoc
│ │ │ ├── Control.rakudoc
│ │ │ ├── ControlFlow/
│ │ │ │ └── Return.rakudoc
│ │ │ ├── ControlFlow.rakudoc
│ │ │ ├── DateTime/
│ │ │ │ └── TimezoneClash.rakudoc
│ │ │ ├── Declaration/
│ │ │ │ ├── Scope/
│ │ │ │ │ └── Multi.rakudoc
│ │ │ │ └── Scope.rakudoc
│ │ │ ├── Does/
│ │ │ │ └── TypeObject.rakudoc
│ │ │ ├── Dynamic/
│ │ │ │ └── NotFound.rakudoc
│ │ │ ├── Eval/
│ │ │ │ └── NoSuchLang.rakudoc
│ │ │ ├── Export/
│ │ │ │ └── NameClash.rakudoc
│ │ │ ├── IO/
│ │ │ │ ├── BinaryMode.rakudoc
│ │ │ │ ├── Chdir.rakudoc
│ │ │ │ ├── Chmod.rakudoc
│ │ │ │ ├── Chown.rakudoc
│ │ │ │ ├── Copy.rakudoc
│ │ │ │ ├── Cwd.rakudoc
│ │ │ │ ├── Dir.rakudoc
│ │ │ │ ├── DoesNotExist.rakudoc
│ │ │ │ ├── Flush.rakudoc
│ │ │ │ ├── Link.rakudoc
│ │ │ │ ├── Lock.rakudoc
│ │ │ │ ├── Mkdir.rakudoc
│ │ │ │ ├── Move.rakudoc
│ │ │ │ ├── Rename.rakudoc
│ │ │ │ ├── Rmdir.rakudoc
│ │ │ │ ├── Symlink.rakudoc
│ │ │ │ └── Unlink.rakudoc
│ │ │ ├── IO.rakudoc
│ │ │ ├── Inheritance/
│ │ │ │ ├── NotComposed.rakudoc
│ │ │ │ └── Unsupported.rakudoc
│ │ │ ├── Method/
│ │ │ │ ├── InvalidQualifier.rakudoc
│ │ │ │ ├── NotFound.rakudoc
│ │ │ │ └── Private/
│ │ │ │ ├── Permission.rakudoc
│ │ │ │ └── Unqualified.rakudoc
│ │ │ ├── Mixin/
│ │ │ │ └── NotComposable.rakudoc
│ │ │ ├── NYI.rakudoc
│ │ │ ├── NoDispatcher.rakudoc
│ │ │ ├── Numeric/
│ │ │ │ ├── CannotConvert.rakudoc
│ │ │ │ ├── DivideByZero.rakudoc
│ │ │ │ └── Real.rakudoc
│ │ │ ├── OS.rakudoc
│ │ │ ├── Obsolete.rakudoc
│ │ │ ├── OutOfRange.rakudoc
│ │ │ ├── Package/
│ │ │ │ └── Stubbed.rakudoc
│ │ │ ├── Parameter/
│ │ │ │ ├── Default.rakudoc
│ │ │ │ ├── MultipleTypeConstraints.rakudoc
│ │ │ │ ├── Placeholder.rakudoc
│ │ │ │ ├── Twigil.rakudoc
│ │ │ │ └── WrongOrder.rakudoc
│ │ │ ├── Phaser/
│ │ │ │ ├── Multiple.rakudoc
│ │ │ │ └── PrePost.rakudoc
│ │ │ ├── Placeholder/
│ │ │ │ ├── Block.rakudoc
│ │ │ │ └── Mainline.rakudoc
│ │ │ ├── Pod.rakudoc
│ │ │ ├── Proc/
│ │ │ │ ├── Async/
│ │ │ │ │ ├── AlreadyStarted.rakudoc
│ │ │ │ │ ├── BindOrUse.rakudoc
│ │ │ │ │ ├── CharsOrBytes.rakudoc
│ │ │ │ │ ├── MustBeStarted.rakudoc
│ │ │ │ │ ├── OpenForWriting.rakudoc
│ │ │ │ │ └── TapBeforeSpawn.rakudoc
│ │ │ │ ├── Async.rakudoc
│ │ │ │ └── Unsuccessful.rakudoc
│ │ │ ├── Promise/
│ │ │ │ ├── CauseOnlyValidOnBroken.rakudoc
│ │ │ │ └── Vowed.rakudoc
│ │ │ ├── Redeclaration.rakudoc
│ │ │ ├── Role/
│ │ │ │ └── Initialization.rakudoc
│ │ │ ├── Scheduler/
│ │ │ │ └── CueInNaNSeconds.rakudoc
│ │ │ ├── Seq/
│ │ │ │ └── Consumed.rakudoc
│ │ │ ├── Sequence/
│ │ │ │ └── Deduction.rakudoc
│ │ │ ├── Signature/
│ │ │ │ ├── NameClash.rakudoc
│ │ │ │ └── Placeholder.rakudoc
│ │ │ ├── Str/
│ │ │ │ ├── Match/
│ │ │ │ │ └── x.rakudoc
│ │ │ │ └── Numeric.rakudoc
│ │ │ ├── StubCode.rakudoc
│ │ │ ├── Syntax/
│ │ │ │ ├── Augment/
│ │ │ │ │ └── WithoutMonkeyTyping.rakudoc
│ │ │ │ ├── Comment/
│ │ │ │ │ └── Embedded.rakudoc
│ │ │ │ ├── Confused.rakudoc
│ │ │ │ ├── InfixInTermPosition.rakudoc
│ │ │ │ ├── Malformed.rakudoc
│ │ │ │ ├── Missing.rakudoc
│ │ │ │ ├── NegatedPair.rakudoc
│ │ │ │ ├── NoSelf.rakudoc
│ │ │ │ ├── Number/
│ │ │ │ │ └── RadixOutOfRange.rakudoc
│ │ │ │ ├── P5.rakudoc
│ │ │ │ ├── Perl5Var.rakudoc
│ │ │ │ ├── Regex/
│ │ │ │ │ ├── Adverb.rakudoc
│ │ │ │ │ └── SolitaryQuantifier.rakudoc
│ │ │ │ ├── Reserved.rakudoc
│ │ │ │ ├── Self/
│ │ │ │ │ └── WithoutObject.rakudoc
│ │ │ │ ├── Signature/
│ │ │ │ │ └── InvocantMarker.rakudoc
│ │ │ │ ├── Term/
│ │ │ │ │ └── MissingInitializer.rakudoc
│ │ │ │ ├── UnlessElse.rakudoc
│ │ │ │ └── Variable/
│ │ │ │ ├── Match.rakudoc
│ │ │ │ ├── Numeric.rakudoc
│ │ │ │ └── Twigil.rakudoc
│ │ │ ├── Syntax.rakudoc
│ │ │ ├── Temporal/
│ │ │ │ └── InvalidFormat.rakudoc
│ │ │ ├── Temporal.rakudoc
│ │ │ ├── TypeCheck/
│ │ │ │ ├── Assignment.rakudoc
│ │ │ │ ├── Binding.rakudoc
│ │ │ │ ├── Return.rakudoc
│ │ │ │ └── Splice.rakudoc
│ │ │ ├── TypeCheck.rakudoc
│ │ │ └── Undeclared.rakudoc
│ │ ├── atomicint.rakudoc
│ │ ├── independent-routines.rakudoc
│ │ └── utf8.rakudoc
│ └── announcements.rakudoc
├── lib/
│ └── Pod/
│ ├── Cache.rakumod
│ └── Convenience.rakumod
├── resources/
│ └── i18n/
│ ├── de/
│ │ └── README.de.md
│ ├── es/
│ │ └── README.es.md
│ ├── fr/
│ │ └── README.fr.md
│ ├── it/
│ │ └── README.it.md
│ ├── jp/
│ │ └── README.jp.md
│ ├── nl/
│ │ └── README.nl.md
│ ├── pt/
│ │ └── README.pt.md
│ └── zh/
│ └── README.zh.md
├── t/
│ ├── 00-meta.rakutest
│ ├── 02-pod-valid.rakutest
│ ├── 03-tests-valid.rakutest
│ ├── 04-trailing-whitespace.rakutest
│ ├── 05-tabs.rakutest
│ ├── 06-double-dots.rakutest
│ ├── 07-duplicates.rakutest
│ ├── 08-headings.rakutest
│ ├── 09-final-newline.rakutest
│ ├── 10-vim-mode.rakutest
│ ├── 11-return-type.rakutest
│ ├── 12-perl-nbsp.rakutest
│ ├── 13-braces.rakutest
│ ├── 14-routine-definitions.rakutest
│ ├── 15-word-variants.rakutest
│ ├── 16-an-grammar.rakutest
│ ├── 17-space-after-comma.rakutest
│ ├── 18-rakuast-validate.rakutest
│ ├── 19-examples-compilation.rakutest
│ ├── 20-camelia-invocations.rakutest
│ ├── 21-version-release.rakutest
│ ├── 22-glossary-sorted.rakutest
│ ├── 23-aspell.rakutest
│ ├── 24-words.rakutest
│ └── pws/
│ ├── code.pws
│ └── words.pws
├── type-graph.txt
├── util/
│ ├── clean-spell
│ ├── create-brackets-table.raku
│ ├── dumpast.raku
│ ├── github-action-test.sh
│ ├── missing-types.raku
│ ├── new-type.raku
│ ├── perl-nbsp.raku
│ ├── sort-words.raku
│ ├── test-modified.sh
│ ├── test-website.raku
│ ├── unskip.raku
│ └── update-and-test
├── writing-docs/
│ ├── CREATING-NEW-DOCS.md
│ ├── EXAMPLES.md
│ ├── INDEXING.md
│ ├── README.md
│ ├── STYLEGUIDE.md
│ └── TESTING.md
└── xt/
├── 01-raku-version.rakutest
├── check-signatures.rakutest
├── rakuast-compare.rakutest
├── rakudoc-l.rakutest
├── rakudoc-types.rakutest
├── search-categories.rakutest
└── type-graph.rakutest
Condensed preview — 523 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (3,692K chars).
[
{
"path": ".github/ISSUE_TEMPLATE/bug-report-or-feature-request.md",
"chars": 329,
"preview": "---\nname: Bug report or feature request\nabout: Create a report to help us improve\ntitle: ''\nlabels: docs\nassignees: ''\n\n"
},
{
"path": ".github/pull_request_template.md",
"chars": 393,
"preview": "## The problem\n\n\n## Solution provided\n\n<!--\n\n The template below contains optional suggestions. Simply omit it\n if"
},
{
"path": ".github/workflows/test.yml",
"chars": 926,
"preview": "name: test\non:\n push:\n branches: [ main ]\n paths:\n - '**'\n pull_request:\n branches: [ main ]\n paths:\n"
},
{
"path": ".gitignore",
"chars": 219,
"preview": "# Precompilation folders\n.precomp/\n.pod-precomp\n.pod-cache\n\n# Generated files for testing\nt/pws/aspell.pws\nretest\n\n# Cac"
},
{
"path": "Build.rakumod",
"chars": 278,
"preview": "class Build {\n BEGIN {\n note q:to/END/;\n This repository is not intended to be installed!\n "
},
{
"path": "CONTRIBUTING.md",
"chars": 7984,
"preview": "# Contributing\n\nYour patches to `Raku/doc` are very welcome, and if you want to\nhelp,\n[please read this guide](https://g"
},
{
"path": "CREDITS",
"chars": 5750,
"preview": "=pod\n\n Following in the steps of other open source projects that\n eventually take over the world, here is the part"
},
{
"path": "LICENSE",
"chars": 8894,
"preview": "\t\t The Artistic License 2.0\n\n\t Copyright (c) 2000-2006, The Perl Foundation.\n\n Everyone is permitted to cop"
},
{
"path": "META6.json",
"chars": 707,
"preview": "{\n \"name\": \"Raku doc\",\n \"description\": \"Raku™ documentation\",\n \"version\": \"2.0\",\n \"raku\": \"6.*\",\n \"authors\": [\n "
},
{
"path": "Makefile",
"chars": 674,
"preview": ".PHONY: test xtest push help\n\nhelp:\n\t@echo \"Usage: make [test|xtest|push]\"\n\t@echo \"\"\n\t@echo \"Options:\"\n\t@echo \" test: "
},
{
"path": "README.md",
"chars": 2715,
"preview": "# Official Documentation of Raku™\n\n["
},
{
"path": "doc/Language/101-basics.rakudoc",
"chars": 20730,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"beginning\")\n\n=TITLE Raku by example 101\n\n=SUBTITLE A basic"
},
{
"path": "doc/Language/REPL.rakudoc",
"chars": 2814,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"tutorial\")\n\n=TITLE REPL\n\n=SUBTITLE Interactive Raku, read-e"
},
{
"path": "doc/Language/about.rakudoc",
"chars": 1412,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"beginning\")\n\n=TITLE About the docs\n\n=SUBTITLE How to locall"
},
{
"path": "doc/Language/brackets.rakudoc",
"chars": 15275,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"reference\")\n\n=TITLE Brackets\n\n=SUBTITLE Valid opening/closi"
},
{
"path": "doc/Language/classtut.rakudoc",
"chars": 36877,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"tutorial\")\n\n=TITLE Classes and objects\n\n=SUBTITLE A tutoria"
},
{
"path": "doc/Language/community.rakudoc",
"chars": 3233,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"reference\")\n\n=TITLE Community\n\n=SUBTITLE Information about "
},
{
"path": "doc/Language/compilation.rakudoc",
"chars": 16102,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"tutorial\")\n\n=TITLE CompUnits and where to find them\n\n=SUBTI"
},
{
"path": "doc/Language/concurrency.rakudoc",
"chars": 31598,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"tutorial\")\n\n=TITLE Concurrency\n\n=SUBTITLE Concurrency and a"
},
{
"path": "doc/Language/containers.rakudoc",
"chars": 14820,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"fundamental\")\n\n=TITLE Containers\n\n=SUBTITLE A low-level exp"
},
{
"path": "doc/Language/contexts.rakudoc",
"chars": 9302,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"fundamental\")\n\n=TITLE Contexts and contextualizers\n\n=SUBTIT"
},
{
"path": "doc/Language/control.rakudoc",
"chars": 45862,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"fundamental\")\n\n=TITLE Control flow\n\n=SUBTITLE Statements us"
},
{
"path": "doc/Language/create-cli.rakudoc",
"chars": 22568,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"tutorial\")\n\n=TITLE Command line interface\n\n=SUBTITLE Creati"
},
{
"path": "doc/Language/distributions/configuration-structure.rakudoc",
"chars": 18368,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Modules\") :category(\"tutorial\")\n\n=TITLE Distributing modules: the configuration a"
},
{
"path": "doc/Language/distributions/introduction.rakudoc",
"chars": 5114,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Modules\") :category(\"tutorial\")\n\n=TITLE Distributions: an introduction\n\n=SUBTITLE"
},
{
"path": "doc/Language/distributions/testing.rakudoc",
"chars": 5284,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Modules\") :category(\"tutorial\")\n\n=TITLE Distributions: testing\n\n=SUBTITLE Testing"
},
{
"path": "doc/Language/distributions/tools.rakudoc",
"chars": 4983,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Modules\") :category(\"tutorial\")\n\n=TITLE Distributions: the tools\n\n=SUBTITLE What "
},
{
"path": "doc/Language/distributions/uploading.rakudoc",
"chars": 3774,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Modules\") :category(\"tutorial\")\n\n=TITLE Distributions: uploading\n\n=SUBTITLE How t"
},
{
"path": "doc/Language/enumeration.rakudoc",
"chars": 1955,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"fundamental\")\n\n=TITLE Enumeration\n\n=SUBTITLE An example usi"
},
{
"path": "doc/Language/exceptions.rakudoc",
"chars": 16430,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"fundamental\")\n\n=TITLE Exceptions\n\n=SUBTITLE Using exception"
},
{
"path": "doc/Language/experimental.rakudoc",
"chars": 6109,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"advanced\")\n\n=TITLE Experimental features\n\n=SUBTITLE Preview"
},
{
"path": "doc/Language/faq.rakudoc",
"chars": 40163,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"reference\")\n\n=TITLE FAQ\n\n=SUBTITLE Frequently asked questio"
},
{
"path": "doc/Language/filename-extensions.rakudoc",
"chars": 1254,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"beginning\")\n\n=TITLE Filename extensions\n\n=SUBTITLE The exte"
},
{
"path": "doc/Language/functions.rakudoc",
"chars": 46029,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"fundamental\")\n\n=TITLE Functions\n\n=SUBTITLE Functions and fu"
},
{
"path": "doc/Language/glossary.rakudoc",
"chars": 43332,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"reference\")\n\n=TITLE Glossary\n\n=SUBTITLE Glossary of Raku te"
},
{
"path": "doc/Language/grammar_tutorial.rakudoc",
"chars": 25265,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"tutorial\")\n\n=TITLE Grammar tutorial\n\n=SUBTITLE An introduct"
},
{
"path": "doc/Language/grammars.rakudoc",
"chars": 24859,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"fundamental\")\n\n=TITLE Grammars\n\n=SUBTITLE Parsing and inter"
},
{
"path": "doc/Language/hashmap.rakudoc",
"chars": 20576,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"fundamental\")\n\n=TITLE Hashes and maps\n\n=SUBTITLE Working wi"
},
{
"path": "doc/Language/haskell-to-p6.rakudoc",
"chars": 18489,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"migration\")\n\n=TITLE Haskell to Raku - nutshell\n\n=SUBTITLE L"
},
{
"path": "doc/Language/intro.rakudoc",
"chars": 3300,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"beginning\")\n\n=TITLE Brief introduction\n\n=SUBTITLE Using Rak"
},
{
"path": "doc/Language/io-guide.rakudoc",
"chars": 15007,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"fundamental\")\n\n=TITLE Input/Output the definitive guide\n\n=S"
},
{
"path": "doc/Language/io.rakudoc",
"chars": 6854,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"tutorial\")\n\n=TITLE Input/Output\n\n=SUBTITLE File-related ope"
},
{
"path": "doc/Language/ipc.rakudoc",
"chars": 5180,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"tutorial\")\n\n=TITLE Inter-process communication\n\n=SUBTITLE P"
},
{
"path": "doc/Language/iterating.rakudoc",
"chars": 7264,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"tutorial\")\n\n=TITLE Iterating\n\n=SUBTITLE Functionalities ava"
},
{
"path": "doc/Language/js-nutshell.rakudoc",
"chars": 39449,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"migration\")\n\n=TITLE JavaScript (Node.js) to Raku - nutshell"
},
{
"path": "doc/Language/list.rakudoc",
"chars": 34329,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"fundamental\")\n\n=TITLE Lists, sequences, and arrays\n\n=SUBTIT"
},
{
"path": "doc/Language/making-modules/code.rakudoc",
"chars": 5568,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Modules\") :category(\"tutorial\")\n\n=TITLE Making modules: the code\n\n=SUBTITLE How t"
},
{
"path": "doc/Language/making-modules/introduction.rakudoc",
"chars": 3438,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Modules\") :category(\"tutorial\")\n\n=TITLE Making modules: an introduction\n\n=SUBTITL"
},
{
"path": "doc/Language/math.rakudoc",
"chars": 19159,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"tutorial\")\n\n=TITLE Doing math with Raku\n\n=SUBTITLE Differen"
},
{
"path": "doc/Language/module-packages.rakudoc",
"chars": 986,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"tutorial\")\n\n=TITLE Module packages\n\n=SUBTITLE Creating modu"
},
{
"path": "doc/Language/modules-core.rakudoc",
"chars": 228,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"tutorial\")\n\n=TITLE Core modules\n\n=SUBTITLE Core modules tha"
},
{
"path": "doc/Language/modules-extra.rakudoc",
"chars": 246,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"tutorial\")\n\n=TITLE Module development utilities\n\n=SUBTITLE "
},
{
"path": "doc/Language/modules.rakudoc",
"chars": 2241,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"tutorial\")\n\n=TITLE Modules\n\n=SUBTITLE How to use, create, a"
},
{
"path": "doc/Language/mop.rakudoc",
"chars": 15674,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"fundamental\")\n\n=TITLE Metaobject protocol (MOP)\n\n=SUBTITLE "
},
{
"path": "doc/Language/nativecall.rakudoc",
"chars": 47246,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"fundamental\")\n\n=TITLE Native calling interface\n\n=SUBTITLE C"
},
{
"path": "doc/Language/nativetypes.rakudoc",
"chars": 8928,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"fundamental\")\n\n=TITLE Raku native types\n\n=SUBTITLE Using th"
},
{
"path": "doc/Language/newline.rakudoc",
"chars": 2386,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"fundamental\")\n\n=TITLE Newline handling in Raku\n\n=SUBTITLE H"
},
{
"path": "doc/Language/numerics.rakudoc",
"chars": 31706,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"fundamental\")\n\n=TITLE Numerics\n\n=SUBTITLE Numeric types ava"
},
{
"path": "doc/Language/objects.rakudoc",
"chars": 50134,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"fundamental\")\n\n=TITLE Object orientation\n\n=SUBTITLE Object "
},
{
"path": "doc/Language/operators.rakudoc",
"chars": 133760,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"fundamental\")\n\n=TITLE Operators\n\n=SUBTITLE Common Raku infi"
},
{
"path": "doc/Language/optut.rakudoc",
"chars": 1989,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"tutorial\")\n\n=TITLE Creating operators\n\n=SUBTITLE A short tu"
},
{
"path": "doc/Language/packages.rakudoc",
"chars": 11540,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"fundamental\")\n\n=TITLE Packages\n\n=SUBTITLE Organizing and re"
},
{
"path": "doc/Language/performance.rakudoc",
"chars": 11960,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"fundamental\")\n\n=TITLE Performance\n\n=SUBTITLE Measuring and "
},
{
"path": "doc/Language/perl-func.rakudoc",
"chars": 72948,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"migration\")\n\n=TITLE Perl to Raku guide - functions\n\n=SUBTIT"
},
{
"path": "doc/Language/perl-nutshell.rakudoc",
"chars": 58930,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"migration\")\n\n=TITLE Perl to Raku guide - in a nutshell\n\n=SU"
},
{
"path": "doc/Language/perl-op.rakudoc",
"chars": 14661,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"migration\")\n\n=TITLE Perl to Raku guide - operators\n\n=SUBTIT"
},
{
"path": "doc/Language/perl-overview.rakudoc",
"chars": 2674,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"migration\")\n\n=TITLE Perl to Raku guide - overview\n\n=SUBTITL"
},
{
"path": "doc/Language/perl-syn.rakudoc",
"chars": 6186,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"migration\")\n\n=TITLE Perl to Raku guide - syntax\n\n=SUBTITLE "
},
{
"path": "doc/Language/perl-var.rakudoc",
"chars": 15473,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"migration\")\n\n=TITLE Perl to Raku guide - special variables\n"
},
{
"path": "doc/Language/phasers.rakudoc",
"chars": 17161,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"fundamental\")\n\n=TITLE Phasers\n\n=SUBTITLE Program execution "
},
{
"path": "doc/Language/pod.rakudoc",
"chars": 26282,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"reference\")\n\n=TITLE Rakudoc (aka Pod6)\n\n=SUBTITLE A markup "
},
{
"path": "doc/Language/pragmas.rakudoc",
"chars": 9466,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"fundamental\")\n\n=TITLE Pragmas\n\n=SUBTITLE Special modules th"
},
{
"path": "doc/Language/py-nutshell.rakudoc",
"chars": 18553,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"migration\")\n\n=TITLE Python to Raku - nutshell\n\n=SUBTITLE Le"
},
{
"path": "doc/Language/quoting.rakudoc",
"chars": 24357,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"fundamental\")\n\n=TITLE Quoting constructs\n\n=SUBTITLE Writing"
},
{
"path": "doc/Language/rb-nutshell.rakudoc",
"chars": 35485,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"migration\")\n\n=TITLE Ruby to Raku - nutshell\n\n=SUBTITLE Lear"
},
{
"path": "doc/Language/regexes-best-practices.rakudoc",
"chars": 6064,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"tutorial\")\n\n=TITLE Regexes: best practices and gotchas\n\n=SU"
},
{
"path": "doc/Language/regexes.rakudoc",
"chars": 125658,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"fundamental\")\n\n=TITLE Regexes\n\n=SUBTITLE Pattern matching a"
},
{
"path": "doc/Language/setbagmix.rakudoc",
"chars": 10643,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"fundamental\")\n\n=TITLE Sets, bags, and mixes\n\n=SUBTITLE Unor"
},
{
"path": "doc/Language/signatures.rakudoc",
"chars": 49637,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"fundamental\")\n\n=TITLE Signature literals\n\n=SUBTITLE A guide"
},
{
"path": "doc/Language/slangs.rakudoc",
"chars": 12081,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"tutorial\")\n\n=TITLE Slangs\n\n=SUBTITLE Slangs in Raku\n\nThe te"
},
{
"path": "doc/Language/statement-prefixes.rakudoc",
"chars": 5982,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"fundamental\")\n\n=TITLE Statement prefixes\n\n=SUBTITLE Prefixe"
},
{
"path": "doc/Language/structures.rakudoc",
"chars": 21501,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"fundamental\")\n\n=TITLE Data structures\n\n=SUBTITLE How Raku d"
},
{
"path": "doc/Language/subscripts.rakudoc",
"chars": 45533,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"fundamental\")\n\n=TITLE Subscripts\n\n=SUBTITLE Accessing data "
},
{
"path": "doc/Language/syntax.rakudoc",
"chars": 42796,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"fundamental\")\n\n=TITLE Syntax\n\n=SUBTITLE General rules of Ra"
},
{
"path": "doc/Language/system.rakudoc",
"chars": 3857,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"fundamental\")\n\n=TITLE System interaction\n\n=SUBTITLE Working"
},
{
"path": "doc/Language/tables.rakudoc",
"chars": 8509,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"reference\")\n\n=TITLE Pod6 tables\n\n=SUBTITLE Valid, invalid, "
},
{
"path": "doc/Language/temporal.rakudoc",
"chars": 4961,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"fundamental\")\n\n=TITLE Date and time functions\n\n=SUBTITLE Pr"
},
{
"path": "doc/Language/terms.rakudoc",
"chars": 10715,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"reference\")\n\n=TITLE Terms\n\n=SUBTITLE Raku terms\n\nMost synta"
},
{
"path": "doc/Language/testing.rakudoc",
"chars": 9257,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"reference\")\n\n=TITLE Testing\n\n=SUBTITLE Writing and running "
},
{
"path": "doc/Language/traits.rakudoc",
"chars": 6051,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"fundamental\")\n\n=TITLE Traits\n\n=SUBTITLE Compile-time specif"
},
{
"path": "doc/Language/traps.rakudoc",
"chars": 72869,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"reference\")\n\n=TITLE Traps to avoid\n\n=SUBTITLE Traps to avoi"
},
{
"path": "doc/Language/typesystem.rakudoc",
"chars": 34646,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"fundamental\")\n\n=TITLE Type system\n\n=SUBTITLE Introduction t"
},
{
"path": "doc/Language/unicode.rakudoc",
"chars": 10509,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"fundamental\")\n\n=TITLE Unicode\n\n=SUBTITLE Unicode support in"
},
{
"path": "doc/Language/unicode_ascii.rakudoc",
"chars": 7733,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"fundamental\")\n\n=TITLE Unicode versus ASCII symbols\n\n=SUBTIT"
},
{
"path": "doc/Language/unicode_entry.rakudoc",
"chars": 28677,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"tutorial\")\n\n=TITLE Entering unicode characters\n\n=SUBTITLE I"
},
{
"path": "doc/Language/using-modules/code.rakudoc",
"chars": 15045,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Modules\") :category(\"tutorial\")\n\n=TITLE Using modules: the code\n\n=SUBTITLE How to"
},
{
"path": "doc/Language/using-modules/finding-installing.rakudoc",
"chars": 3085,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Modules\") :category(\"tutorial\")\n\n=TITLE Using modules: finding and installing\n\n=S"
},
{
"path": "doc/Language/using-modules/introduction.rakudoc",
"chars": 3285,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Modules\") :category(\"tutorial\")\n\n=TITLE Modules: an introduction\n\n=SUBTITLE Modul"
},
{
"path": "doc/Language/variables.rakudoc",
"chars": 70683,
"preview": "=begin pod :kind(\"Language\") :subkind(\"Language\") :category(\"fundamental\")\n\n=TITLE Variables\n\n=SUBTITLE Variables in Rak"
},
{
"path": "doc/Native/int.rakudoc",
"chars": 434,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"basic\")\n\n=TITLE class int\n\n=SUBTITLE Native integer\n\n class int i"
},
{
"path": "doc/Programs/01-debugging.rakudoc",
"chars": 3181,
"preview": "=begin pod :kind(\"Programs\") :subkind(\"programs\") :category(\"programs\")\n\n=TITLE Debugging\n\n=SUBTITLE Modules and applica"
},
{
"path": "doc/Programs/02-reading-docs.rakudoc",
"chars": 2107,
"preview": "=begin pod :kind(\"Programs\") :subkind(\"programs\") :category(\"programs\")\n\n=TITLE Reading the docs\n\n=SUBTITLE rakudoc - th"
},
{
"path": "doc/Programs/03-environment-variables.rakudoc",
"chars": 9727,
"preview": "=begin pod :kind(\"Programs\") :subkind(\"programs\") :category(\"programs\")\n\n=TITLE Environment variables used by the C<raku"
},
{
"path": "doc/Programs/04-running-raku.rakudoc",
"chars": 4918,
"preview": "=begin pod :kind(\"Programs\") :subkind(\"programs\") :category(\"programs\")\n\n=TITLE Running Raku\n\n=SUBTITLE How to run Rakud"
},
{
"path": "doc/Programs/README.md",
"chars": 230,
"preview": "Attention contributors\n======================\n\nFiles in this directory are sorted by file name to generate the index\nfor"
},
{
"path": "doc/Type/AST.rakudoc",
"chars": 528,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"basic\")\n\n=TITLE class AST\n\n=SUBTITLE Abstract representation of a "
},
{
"path": "doc/Type/Allomorph.rakudoc",
"chars": 7777,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"basic\")\n\n=TITLE class Allomorph\n\n=SUBTITLE Dual value number and s"
},
{
"path": "doc/Type/Any.rakudoc",
"chars": 56074,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"basic\")\n\n=TITLE class Any\n\n=SUBTITLE Thing/object\n\n class Any i"
},
{
"path": "doc/Type/Array.rakudoc",
"chars": 13280,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"composite\")\n\n=TITLE class Array\n\n=SUBTITLE Sequence of itemized va"
},
{
"path": "doc/Type/Associative.rakudoc",
"chars": 3779,
"preview": "=begin pod :kind(\"Type\") :subkind(\"role\") :category(\"composite\")\n\n=TITLE role Associative\n\n=SUBTITLE Object that support"
},
{
"path": "doc/Type/Attribute.rakudoc",
"chars": 12658,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"domain-specific\")\n\n=TITLE class Attribute\n\n=SUBTITLE Member variab"
},
{
"path": "doc/Type/Backtrace/Frame.rakudoc",
"chars": 1750,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"exception\")\n\n=TITLE class Backtrace::Frame\n\n=SUBTITLE Single frame"
},
{
"path": "doc/Type/Backtrace.rakudoc",
"chars": 4904,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"exception\")\n\n=TITLE class Backtrace\n\n=SUBTITLE Snapshot of the dyn"
},
{
"path": "doc/Type/Bag.rakudoc",
"chars": 5463,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"composite\")\n\n=TITLE class Bag\n\n=SUBTITLE Immutable collection of d"
},
{
"path": "doc/Type/BagHash.rakudoc",
"chars": 8237,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"composite\")\n\n=TITLE class BagHash\n\n=SUBTITLE Mutable collection of"
},
{
"path": "doc/Type/Baggy.rakudoc",
"chars": 17323,
"preview": "=begin pod :kind(\"Type\") :subkind(\"role\") :category(\"composite\")\n\n=TITLE role Baggy\n\n=SUBTITLE Collection of distinct we"
},
{
"path": "doc/Type/Blob.rakudoc",
"chars": 12898,
"preview": "=begin pod :kind(\"Type\") :subkind(\"role\") :category(\"composite\")\n\n=TITLE role Blob\n\n=SUBTITLE Immutable buffer for binar"
},
{
"path": "doc/Type/Block.rakudoc",
"chars": 1855,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"basic\")\n\n=TITLE class Block\n\n=SUBTITLE Code object with its own le"
},
{
"path": "doc/Type/Bool.rakudoc",
"chars": 4413,
"preview": "=begin pod :kind(\"Type\") :subkind(\"enum\") :category(\"basic\")\n\n=TITLE enum Bool\n\n=SUBTITLE Logical Boolean\n\n enum Bool"
},
{
"path": "doc/Type/Buf.rakudoc",
"chars": 13956,
"preview": "=begin pod :kind(\"Type\") :subkind(\"role\") :category(\"composite\")\n\n=TITLE role Buf\n\n=SUBTITLE Mutable buffer for binary d"
},
{
"path": "doc/Type/CX/Done.rakudoc",
"chars": 408,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"exception\")\n\n=TITLE class CX::Done\n\n=SUBTITLE Done control excepti"
},
{
"path": "doc/Type/CX/Emit.rakudoc",
"chars": 408,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"exception\")\n\n=TITLE role CX::Emit\n\n=SUBTITLE Emit control exceptio"
},
{
"path": "doc/Type/CX/Last.rakudoc",
"chars": 546,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"exception\")\n\n=TITLE role CX::Last\n\n=SUBTITLE Last control exceptio"
},
{
"path": "doc/Type/CX/Next.rakudoc",
"chars": 660,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"exception\")\n\n=TITLE role CX::Next\n\n=SUBTITLE Next control exceptio"
},
{
"path": "doc/Type/CX/Proceed.rakudoc",
"chars": 421,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"exception\")\n\n=TITLE role CX::Proceed\n\n=SUBTITLE Proceed control ex"
},
{
"path": "doc/Type/CX/Redo.rakudoc",
"chars": 368,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"exception\")\n\n=TITLE role CX::Redo\n\n=SUBTITLE Redo control exceptio"
},
{
"path": "doc/Type/CX/Return.rakudoc",
"chars": 397,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"exception\")\n\n=TITLE role CX::Return\n\n=SUBTITLE Return control exce"
},
{
"path": "doc/Type/CX/Succeed.rakudoc",
"chars": 415,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"exception\")\n\n=TITLE role CX::Succeed\n\n=SUBTITLE Succeed control ex"
},
{
"path": "doc/Type/CX/Take.rakudoc",
"chars": 359,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"exception\")\n\n=TITLE role CX::Take\n\n=SUBTITLE Take control exceptio"
},
{
"path": "doc/Type/CX/Warn.rakudoc",
"chars": 408,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"exception\")\n\n=TITLE role CX::Warn\n\n=SUBTITLE Control exception war"
},
{
"path": "doc/Type/CallFrame.rakudoc",
"chars": 4668,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"basic\")\n\n=TITLE class CallFrame\n\n=SUBTITLE Captures the current fr"
},
{
"path": "doc/Type/Callable.rakudoc",
"chars": 2089,
"preview": "=begin pod :kind(\"Type\") :subkind(\"role\") :category(\"basic\")\n\n=TITLE role Callable\n\n=SUBTITLE Invocable code object\n\n "
},
{
"path": "doc/Type/Cancellation.rakudoc",
"chars": 754,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"domain-specific\")\n\n=TITLE class Cancellation\n\n=SUBTITLE Removal of"
},
{
"path": "doc/Type/Capture.rakudoc",
"chars": 7827,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"composite\")\n\n=TITLE class Capture\n\n=SUBTITLE Argument list suitabl"
},
{
"path": "doc/Type/Channel.rakudoc",
"chars": 6001,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"domain-specific\")\n\n=TITLE class Channel\n\n=SUBTITLE Thread-safe que"
},
{
"path": "doc/Type/Code.rakudoc",
"chars": 7661,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"basic\")\n\n=TITLE class Code\n\n=SUBTITLE Code object\n\n class Code "
},
{
"path": "doc/Type/Collation.rakudoc",
"chars": 1392,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"basic\")\n\n=TITLE class Collation\n\n=SUBTITLE Encapsulates instructio"
},
{
"path": "doc/Type/CompUnit/PrecompilationRepository.rakudoc",
"chars": 2388,
"preview": "=begin pod :kind(\"Type\") :subkind(\"role\") :category(\"domain-specific\")\n\n=TITLE role CompUnit::PrecompilationRepository\n\n"
},
{
"path": "doc/Type/CompUnit/Repository/FileSystem.rakudoc",
"chars": 3981,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"domain-specific\")\n\n=TITLE class CompUnit::Repository::FileSystem\n\n"
},
{
"path": "doc/Type/CompUnit/Repository/Installation.rakudoc",
"chars": 4843,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"domain-specific\")\n\n=TITLE class CompUnit::Repository::Installation"
},
{
"path": "doc/Type/CompUnit/Repository/Unknown.rakudoc",
"chars": 1194,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"domain-specific\")\n\n=TITLE class CompUnit::Repository::Unknown\n\n=SU"
},
{
"path": "doc/Type/CompUnit/Repository.rakudoc",
"chars": 1293,
"preview": "=begin pod :kind(\"Type\") :subkind(\"role\") :category(\"domain-specific\")\n\n=TITLE role CompUnit::Repository\n\n=SUBTITLE Comp"
},
{
"path": "doc/Type/CompUnit.rakudoc",
"chars": 1667,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"domain-specific\")\n\n=TITLE class CompUnit\n\n=SUBTITLE CompUnit\n\n "
},
{
"path": "doc/Type/Compiler.rakudoc",
"chars": 1751,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"basic\")\n\n=TITLE class Compiler\n\n=SUBTITLE Information related to t"
},
{
"path": "doc/Type/Complex.rakudoc",
"chars": 6208,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"basic\")\n\n=TITLE class Complex\n\n=SUBTITLE Complex number\n\n class"
},
{
"path": "doc/Type/ComplexStr.rakudoc",
"chars": 2515,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"basic\")\n\n=TITLE class ComplexStr\n\n=SUBTITLE Dual value complex num"
},
{
"path": "doc/Type/Cool.rakudoc",
"chars": 51281,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"basic\")\n\n=TITLE class Cool\n\n=SUBTITLE Object that can be treated a"
},
{
"path": "doc/Type/CurrentThreadScheduler.rakudoc",
"chars": 443,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"basic\")\n\n=TITLE class CurrentThreadScheduler\n\n=SUBTITLE Scheduler "
},
{
"path": "doc/Type/Date.rakudoc",
"chars": 8055,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"basic\")\n\n=TITLE class Date\n\n=SUBTITLE Calendar date\n\n class Dat"
},
{
"path": "doc/Type/DateTime.rakudoc",
"chars": 16743,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"basic\")\n\n=TITLE class DateTime\n\n=SUBTITLE Calendar date with time\n"
},
{
"path": "doc/Type/Dateish.rakudoc",
"chars": 12498,
"preview": "=begin pod :kind(\"Type\") :subkind(\"role\") :category(\"basic\")\n\n=TITLE role Dateish\n\n=SUBTITLE Object that can be treated "
},
{
"path": "doc/Type/Distribution/Hash.rakudoc",
"chars": 1107,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"basic\")\n\n=TITLE class Distribution::Hash\n\n=SUBTITLE Distribution::"
},
{
"path": "doc/Type/Distribution/Locally.rakudoc",
"chars": 979,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"basic\")\n\n=TITLE class Distribution::Locally\n\n=SUBTITLE Distributio"
},
{
"path": "doc/Type/Distribution/Path.rakudoc",
"chars": 1164,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"basic\")\n\n=TITLE class Distribution::Path\n\n=SUBTITLE Distribution::"
},
{
"path": "doc/Type/Distribution/Resource.rakudoc",
"chars": 6025,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"basic\")\n\n=TITLE class Distribution::Resource\n\n=SUBTITLE Every one "
},
{
"path": "doc/Type/Distribution.rakudoc",
"chars": 1221,
"preview": "=begin pod :kind(\"Type\") :subkind(\"role\") :category(\"basic\")\n\n=TITLE role Distribution\n\n=SUBTITLE Distribution\n\n role"
},
{
"path": "doc/Type/Distro.rakudoc",
"chars": 800,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"domain-specific\")\n\n=TITLE class Distro\n\n=SUBTITLE Distribution rel"
},
{
"path": "doc/Type/Duration.rakudoc",
"chars": 847,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"basic\")\n\n=TITLE class Duration\n\n=SUBTITLE Length of time\n\n clas"
},
{
"path": "doc/Type/Encoding/Registry.rakudoc",
"chars": 982,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"basic\")\n\n=TITLE class Encoding::Registry\n\n=SUBTITLE Management of "
},
{
"path": "doc/Type/Encoding.rakudoc",
"chars": 1768,
"preview": "=begin pod :kind(\"Type\") :subkind(\"role\") :category(\"basic\")\n\n=TITLE role Encoding\n\n=SUBTITLE Support for character enco"
},
{
"path": "doc/Type/Endian.rakudoc",
"chars": 830,
"preview": "=begin pod :kind(\"Type\") :subkind(\"enum\") :category(\"basic\")\n\n=TITLE enum Endian\n\n=SUBTITLE Indicate endianness (6.d, 20"
},
{
"path": "doc/Type/Enumeration.rakudoc",
"chars": 6625,
"preview": "=begin pod :kind(\"Type\") :subkind(\"role\") :category(\"composite\")\n\n=TITLE role Enumeration\n\n=SUBTITLE Working with the ro"
},
{
"path": "doc/Type/Exception.rakudoc",
"chars": 5504,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"exception\")\n\n=TITLE class Exception\n\n=SUBTITLE Anomalous event cap"
},
{
"path": "doc/Type/Failure.rakudoc",
"chars": 7584,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"exception\")\n\n=TITLE class Failure\n\n=SUBTITLE Delayed exception\n\n "
},
{
"path": "doc/Type/FatRat.rakudoc",
"chars": 1191,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"basic\")\n\n=TITLE class FatRat\n\n=SUBTITLE Rational number (arbitrary"
},
{
"path": "doc/Type/ForeignCode.rakudoc",
"chars": 1692,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"basic\")\n\n=TITLE class ForeignCode\n\n=SUBTITLE Rakudo-specific class"
},
{
"path": "doc/Type/Format.rakudoc",
"chars": 2295,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"basic\")\n\n=TITLE class Format\n\n=SUBTITLE Convert values to a string"
},
{
"path": "doc/Type/Formatter.rakudoc",
"chars": 1546,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"basic\")\n\n=TITLE class Formatter\n\n=SUBTITLE Produce Callable for gi"
},
{
"path": "doc/Type/Grammar.rakudoc",
"chars": 4595,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"domain-specific\")\n\n=TITLE class Grammar\n\n=SUBTITLE Formal grammar "
},
{
"path": "doc/Type/Hash.rakudoc",
"chars": 19753,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"composite\")\n\n=TITLE class Hash\n\n=SUBTITLE Mapping from strings to "
},
{
"path": "doc/Type/HyperSeq.rakudoc",
"chars": 1719,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"basic\")\n\n=TITLE class HyperSeq\n\n=SUBTITLE An object for performing"
},
{
"path": "doc/Type/HyperWhatever.rakudoc",
"chars": 1934,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"basic\")\n\n=TITLE class HyperWhatever\n\n=SUBTITLE Placeholder for mul"
},
{
"path": "doc/Type/IO/ArgFiles.rakudoc",
"chars": 2590,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"domain-specific\")\n\n=TITLE class IO::ArgFiles\n\n=SUBTITLE Iterate ov"
},
{
"path": "doc/Type/IO/CatHandle.rakudoc",
"chars": 24883,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"domain-specific\")\n\n=TITLE class IO::CatHandle\n\n=SUBTITLE Use multi"
},
{
"path": "doc/Type/IO/Handle.rakudoc",
"chars": 40742,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"domain-specific\")\n\n=TITLE class IO::Handle\n\n=SUBTITLE Opened file "
},
{
"path": "doc/Type/IO/Notification/Change.rakudoc",
"chars": 1499,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"domain-specific\")\n\n=TITLE class IO::Notification::Change\n\n=SUBTITL"
},
{
"path": "doc/Type/IO/Notification.rakudoc",
"chars": 2225,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"domain-specific\")\n\n=TITLE class IO::Notification\n\n=SUBTITLE Asynch"
},
{
"path": "doc/Type/IO/Path/Cygwin.rakudoc",
"chars": 1068,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"domain-specific\")\n\n=TITLE class IO::Path::Cygwin\n\n=SUBTITLE IO::Pa"
},
{
"path": "doc/Type/IO/Path/Parts.rakudoc",
"chars": 2615,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"domain-specific\")\n\n=TITLE class IO::Path::Parts\n\n=SUBTITLE IO::Pat"
},
{
"path": "doc/Type/IO/Path/QNX.rakudoc",
"chars": 1038,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"domain-specific\")\n\n=TITLE class IO::Path::QNX\n\n=SUBTITLE IO::Path "
},
{
"path": "doc/Type/IO/Path/Unix.rakudoc",
"chars": 1048,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"domain-specific\")\n\n=TITLE class IO::Path::Unix\n\n=SUBTITLE IO::Path"
},
{
"path": "doc/Type/IO/Path/Win32.rakudoc",
"chars": 1063,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"domain-specific\")\n\n=TITLE class IO::Path::Win32\n\n=SUBTITLE IO::Pat"
},
{
"path": "doc/Type/IO/Path.rakudoc",
"chars": 43157,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"domain-specific\")\n\n=TITLE class IO::Path\n\n=SUBTITLE File or direct"
},
{
"path": "doc/Type/IO/Pipe.rakudoc",
"chars": 1056,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"domain-specific\")\n\n=TITLE class IO::Pipe\n\n=SUBTITLE Buffered inter"
},
{
"path": "doc/Type/IO/Socket/Async/ListenSocket.rakudoc",
"chars": 1929,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"domain-specific\")\n\n=TITLE class IO::Socket::Async::ListenSocket\n\n="
},
{
"path": "doc/Type/IO/Socket/Async.rakudoc",
"chars": 10642,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"domain-specific\")\n\n=TITLE class IO::Socket::Async\n\n=SUBTITLE Async"
},
{
"path": "doc/Type/IO/Socket/INET.rakudoc",
"chars": 2921,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"domain-specific\")\n\n=TITLE class IO::Socket::INET\n\n=SUBTITLE TCP So"
},
{
"path": "doc/Type/IO/Socket.rakudoc",
"chars": 2815,
"preview": "=begin pod :kind(\"Type\") :subkind(\"role\") :category(\"domain-specific\")\n\n=TITLE role IO::Socket\n\n=SUBTITLE Network socket"
},
{
"path": "doc/Type/IO/Spec/Cygwin.rakudoc",
"chars": 3880,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"domain-specific\")\n\n=TITLE class IO::Spec::Cygwin\n\n=SUBTITLE Platfo"
},
{
"path": "doc/Type/IO/Spec/QNX.rakudoc",
"chars": 1034,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"domain-specific\")\n\n=TITLE class IO::Spec::QNX\n\n=SUBTITLE Platform "
},
{
"path": "doc/Type/IO/Spec/Unix.rakudoc",
"chars": 10449,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"domain-specific\")\n\n=TITLE class IO::Spec::Unix\n\n=SUBTITLE Platform"
},
{
"path": "doc/Type/IO/Spec/Win32.rakudoc",
"chars": 8905,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"domain-specific\")\n\n=TITLE class IO::Spec::Win32\n\n=SUBTITLE Platfor"
},
{
"path": "doc/Type/IO/Spec.rakudoc",
"chars": 1131,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"domain-specific\")\n\n=TITLE class IO::Spec\n\n=SUBTITLE Platform speci"
},
{
"path": "doc/Type/IO/Special.rakudoc",
"chars": 3363,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"domain-specific\")\n\n=TITLE class IO::Special\n\n=SUBTITLE Path to spe"
},
{
"path": "doc/Type/IO.rakudoc",
"chars": 492,
"preview": "=begin pod :kind(\"Type\") :subkind(\"role\") :category(\"domain-specific\")\n\n=TITLE role IO\n\n=SUBTITLE Input/output related r"
},
{
"path": "doc/Type/Instant.rakudoc",
"chars": 5755,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"basic\")\n\n=TITLE class Instant\n\n=SUBTITLE Specific moment in time\n\n"
},
{
"path": "doc/Type/Int.rakudoc",
"chars": 8081,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"basic\")\n\n=TITLE class Int\n\n=SUBTITLE Integer (arbitrary-precision)"
},
{
"path": "doc/Type/IntStr.rakudoc",
"chars": 1932,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"basic\")\n\n=TITLE class IntStr\n\n=SUBTITLE Dual value integer and str"
},
{
"path": "doc/Type/Iterable.rakudoc",
"chars": 6439,
"preview": "=begin pod :kind(\"Type\") :subkind(\"role\") :category(\"composite\")\n\n=TITLE role Iterable\n\n=SUBTITLE Interface for containe"
},
{
"path": "doc/Type/IterationBuffer.rakudoc",
"chars": 3939,
"preview": "=begin pod :kind(\"Type\") :subkind(\"class\") :category(\"composite\")\n\n=TITLE class IterationBuffer\n\n=SUBTITLE Low level sto"
}
]
// ... and 323 more files (download for full content)
About this extraction
This page contains the full source code of the perl6/doc GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 523 files (3.3 MB), approximately 902.6k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.