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 ================================================ 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™ [![artistic](https://img.shields.io/badge/license-Artistic%202.0-blue.svg?style=flat)](https://opensource.org/licenses/Artistic-2.0) [![test](https://github.com/Raku/doc/actions/workflows/test.yml/badge.svg)](https://github.com/Raku/doc/actions/workflows/test.yml) An HTML version of this documentation can be found at [https://docs.raku.org/](https://docs.raku.org/). 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, which means that C won against C 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) looks like this: =for code :lang 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 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|Tutorial,v6 (Basics)> =begin code :solo use v6; =end code Every Raku program should begin with a line similar to C. 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 =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 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. The compiler doesn't evaluate comments as program text and they're only intended for human readers. =head1 X and X =begin code my $file = open 'scores.txt'; =end code C 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 and X A variable name begins with a I, which is a non-alpha-numeric symbol such as C<$>, C<@>, C<%>, or C<&> E 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, which may consist of letters, digits and the underscore. Between letters you can also use a dash C<-> or an apostrophe C<'>, so C and C are valid identifiers. =head2 X 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|/type/Array> or a L|/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|/type/Array> or L|/type/Hash>). =head2 X and X The built-in function C opens a file, here named C, and returns a I E an object representing that file. The assignment operator C<=> I that filehandle to the variable on the left, which means that C<$file> now stores the filehandle. =head2 X C<'scores.txt'> is a I. 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. =head1 X, X and X =begin code :preamble my @names = $file.get.words; =end code The right-hand side calls a I E a named group of behavior E named C on the filehandle stored in C<$file>. The C method reads and returns one line from the file, removing the line ending. If you print the contents of C<$file> after calling C, you will see that the first line is no longer in there. C is also a method, called on the string returned from C. C decomposes its I E the string on which it operates E 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|/type/Array> C<@names>. The C<@> sigil marks the declared variable as an L|/type/Array>. Arrays store ordered lists. =head1 X =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|/type/Hash>. A L|/type/Hash> is an unordered collection of key-value pairs. Other programming languages call that a I, I, or I. 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|Tutorial,for (Basics)> and blocks =begin code :preamble for $file.lines -> $line { ... } =end code C produces a loop that runs the I 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, 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; during the second, C, and so on. =begin code :preamble my ($pairing, $result) = $line.split(' | '); =end code C can declare multiple variables simultaneously. The right-hand side of the assignment is a call to a method named C, passing along the string C<' | '> as an argument. C 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 and C<$result> will hold C<3:0>. The next two lines follow the same pattern: =begin code :preamble 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 %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 %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|Tutorial,Any (Basics)> and X|Tutorial,+= (Basics)> =begin code :preamble %sets{$p1} += $r1; %sets{$p2} += $r2; =end code C<%sets{$p1} += $r1> means I. In the first iteration C<%sets{$p1}> is not yet defined, so it defaults to a special value called L|/type/Any>. The C<+=> operator conveniently treats the undefined value L|/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, X and X 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. 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|/type/Pair>.) =head2 X and X =begin code :preamble 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 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 prints C<2>. =head1 X =begin code :preamble my @sorted = @names.sort({ %sets{$_} }).sort({ %matches{$_} }).reverse; =end code This line consists of three individually simple steps. An array's C 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 of the players, not their names. The C method's argument is a I 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 C<$_>. =head2 Blocks You have seen blocks before: both the C loop C<<-> $line { ... }>> and the C 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 leaves them in the same order as it found them. Computer scientists call this a I. The program takes advantage of this property of Raku's C to achieve the goal by sorting twice: first by the number of sets won (the secondary criterion), then by the number of matches won (the primary criterion). After the first sorting step, the names are in the order C. After the second sorting step, it's still the same, because no one has won fewer matches but more sets than someone else. Such a situation is entirely possible, especially at larger tournaments. C 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 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 if the player has won a single match or I if the player has won zero or more matches. In order to do this, the I operator (C) is used. If C<%matches{$n} == 1> evaluates to C, then I is returned. Otherwise, I is returned. Either way, the returned value is stored in C<$match-noun>. The same approach applies to C<$set-noun>. The statement C prints its arguments to the standard output (the screen, normally), followed by a newline. (Use C if you don't want the newline at the end.) Note that C will truncate certain data structures by calling the C<.gist> method so C is safer if you want exact output. =head2 X When you run the program, you'll see that C doesn't print the contents of that string verbatim. In place of C<$n> it prints the contents of the variable C<$n> E a player's name stored in C<$n>. This automatic substitution of code with its contents is called I. This interpolation happens only in strings delimited by double quotes C<"...">. Single quoted strings C<'...'> do not interpolate: =head2 X and X =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|/type/Array>s and L|/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 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 say "Math: { 1 + 2 }"; # OUTPUT: «Math: 3␤» my @people = ; 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 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 = ; 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 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 > 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 After removing the first line in C, remove the line C (which would read it), and change: =begin code :preamble my @sorted = @names.sort({ %sets{$_} }).sort({ %matches{$_} }).reverse; =end code ... into: =begin code :preamble 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. B 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. =begin code :preamble ...; 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 is an interactive Raku prompt. Each line of code you enter in the C is executed, and if no output was generated, the value returned by the expression is output. =head1 Trap B: Running code in the C 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 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 ✗ 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, 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. =for code :lang $ 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 in Independent Routines for more information. =head1 ENVIRONMENT Variables See L. =head2 Get command line history In a fresh install, there is no command history. Running the C 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 zef install Terminal::LineEditor =item 2 =for code :lang zef install Linenoise This requires a working C toolchain. =item 3 =for code :lang zef install Readline This requires an installation of the C development library. =item 4 An alternative for UNIX-like systems is to install C. This can be done on Debian-ish systems by running: =for code :lang sudo apt-get install rlwrap And then use it to invoke the C: =for code :lang 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 is available. The official source for this documentation is located at L. =head1 Structure All of the documentation is written in Raku Pod and kept in the C 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. =head1 Contributing For a quick introduction to Raku Pod, see L. For historic details about the Raku Pod specification, see L. For information on how to contribute to the documentation, please read L. =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. 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 module in the I 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 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 =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 class using the L keyword. It has two L, C<$!length> and C<$!width> introduced with the L 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 named C will return the area of the rectangle. It is rarely necessary to explicitly write a constructor. An automatically inherited default constructor called L 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 X<|Tutorial,state> Raku, like many other languages, uses the C 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 keyword, and behaviors, introduced through the C keyword. =head1 X X<|Tutorial,encapsulation> X<|Tutorial,has> In the C class, the first three lines inside the block all declare attributes (called I or I in other languages) using the C declarator. Just as a C 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 is one of the key principles of object oriented design. =head2 X|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, 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. Private attributes will not be set by the default constructor by default, which is why we add the C trait to allow just that. Mnemonic: C looks like a closed door. The second declaration also uses the private twigil: =for code :preamble 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 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|/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 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 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 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|/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 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|/type/Attribute#trait_is_built> trait allows to do just that. One can use the same trait C 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 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 trait was introduced in Rakudo release 2020.01. =head2 C 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 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 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, declared with C or C, 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 act similarly to I 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 are shared by all subclasses, in this case C. Additionally, when the package scope C declarator is used, the variable is visible via their fully qualified name (FQN), while lexically scoped C variables are "private". This is the exact behavior that C and C also show in non class context. X<|Types,static> I act similarly to I 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 pattern a I 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 example. Let's ignore the C method temporarily; it's a special type of method. Consider the second method, C, which adds a new task to a task's dependency list: =begin code :skip-test method add-dependency(Task $dependency) { push @!dependencies, $dependency; } =end code X<|Tutorial,invocant> In many ways, this looks a lot like a C 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 class can call it with the C<.> method call operator. Second, a method places its invocant into the special variable C. The method itself takes the passed parameter – which must be an instance of the C class – and Ces it onto the invocant's C<@!dependencies> attribute. The C method contains the main logic of the dependency handler: =begin code :skip-test 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 construct to iterate over all of the items in the C<@!dependencies> attribute. This iteration places each item – each a C 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 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'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, so that subsequent invocations of C on this object (if this C is a dependency of another C, for example) will not repeat the task. =head2 X 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 followed by the method's name. In the following implementation of a C class to extract L metadata from an mp3 file, methods C, C, and C are private methods while the remaining ones are public methods: =begin code class MP3TagData { has $.filename where { .IO ~~ :e }; has Str $.title is built(False); has Str $.artist is built(False); has Str $.album is built(False); has Str $.year is built(False); has Str $.comment is built(False); has Int $.genre is built(False); has Int $.track is built(False); has Str $.version is built(False); has Str $.type is built(False) = 'ID3'; submethod TWEAK { with $!filename.IO.open(:r, :bin) -> $fh { $fh.seek(-128, SeekFromEnd); my $tagdata = $fh.read(128); self!parse-data: $tagdata; $fh.close; } else { warn "Failed to open file." } } method !parse-data($data) { if self!can-read-format($data) { my $offset = $data.bytes - 128; $!title = self!trim-nulls: $data.subbuf($offset + 3, 30); $!artist = self!trim-nulls: $data.subbuf($offset + 33, 30); $!album = self!trim-nulls: $data.subbuf($offset + 63, 30); $!year = self!trim-nulls: $data.subbuf($offset + 93, 4); my Int $track-flag = $data.subbuf($offset + 97 + 28, 1).Int; $!track = $data.subbuf($offset + 97 + 29, 1).Int; ($!version, $!comment) = $track-flag == 0 && $!track != 0 ?? ('1.1', self!trim-nulls: $data.subbuf($offset + 97, 28)) !! ('1.0', self!trim-nulls: $data.subbuf($offset + 97, 30)); $!genre = $data.subbuf($offset + 97 + 30, 1).Int; } } method !can-read-format(Buf $data --> Bool) { self!trim-nulls($data.subbuf(0..2)) eq 'TAG' } method !trim-nulls(Buf $data --> Str) { $data.decode('utf-8').subst(/\x[0000]+/, '') } } =end code To call a private method of another class, the caller has to be trusted by the callee. A trust relationship is declared with L|/language/typesystem#trait_trusts> and the class to be trusted must already be declared. Calling a private method of another class requires an instance of that class and the fully qualified name (FQN) of the method. A trust relationship also allows access to private attributes. =begin code class B {...} 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 can be used. =head1 X 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 from the base class L|/type/Mu>, but you are free to override C, 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 method, also inherited from L|/type/Mu>. The C 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 instances. The constructor captures these into the C<@dependencies> slurpy array and passes them as named parameters to C (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 as a C and not as a C prevents access to the default constructor. +So if you intend to keep the default constructor available, use C. =head2 X|Tutorial,TWEAK> After C has initialized the classes attributes from the passed values, it will in turn call C for each class in the inheritance hierarchy. C gets passed all the arguments passed to bless. This is where custom initialization logic should go. Remember to always make C a L and not a normal C. If in a class hierarchy a class contains a C method (declared as a C instead of a C) that method is inherited to its subclass and will thus be called twice during construction of the subclass! =head2 X|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 submethod. There are several edge cases one needs to be aware of and take into account though. This is detailed in the L. Because of the difficulty of using C, it is recommended to only make use of it when none of the other approaches described above suffices. X<|Tutorial,submethod DESTROY> =head1 X 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 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 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 and possibly only kicks in after we have stomped over former instances of C a few thousand times. We also can't rely, on the order of destruction. Same as C: Make sure to always declare C as a C. =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 my $eat = Task.new({ say 'eating dinner. NOM!' }); An earlier section explained that declaring the class C 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 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 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 method call recursively calls the C method on the various other dependencies in order, giving the output: =begin code :lang making some money going to the store buying food cleaning kitchen making dinner eating dinner. NOM! =end code =head2 X X<|Tutorial,DEFINITE> Declaring a class creates a new I which, by default, is installed into the current package (just like a variable declared with C scope). This type object is an "empty instance" of the class. For example, types such as L|/type/Int> and L|/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 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 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 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 my $programmer = Programmer.new( salary => 100_000, known_languages => , 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 class overriding the C's C method. =begin code :preamble 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 => , 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 method on C before it moves up to the parent class the C's C method will be called. To access methods in the inheritance chain, use L or the L. =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 to linearize multiple inheritance hierarchies, which is better than depth-first search for handling multiple inheritance. =begin code :preamble class GeekCook is Programmer is Cook { method new( *%params ) { push( %params, "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 => ); $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. =head2 The X|Tutorial,also declarator> declarator Classes to be inherited from can be listed in the class declaration body by prefixing the C trait with C. This also works for the role composition trait C. =begin code :preamble 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 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 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. So the object in question is of class C or one that inherits from it, but not C. The call C<$o.^name> tells us the type of C<$o>; in this case C. 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 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, which is a class managing the properties of the C class – or any other class you are interested in. This metaclass enables other ways of introspection too: =for code :preamble say $o.^attributes.join(', '); say $o.^parents.map({ $_.^name }).join(', '); Finally C<$o.^name> calls the C method on the metaobject, which unsurprisingly returns the class name. Given an object C<$mp3> and the C class definition from the section L, we can inquire about its public methods with C<.^methods>: =begin code :skip-test my $mp3 = MP3TagData.new(filename => 'football-head.mp3'); say $mp3.^methods(:local); # OUTPUT: (TWEAK filename title artist album year comment genre track version # type Submethod+{is-hidden-from-backtrace}.new) =end code X<|Syntax,^methods> C<$mp3.^methods(:local)> produces a list of L|/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 class and excludes the inherited methods; C 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|/routine/find_method> metamethod, which returns the method object if it exists. Otherwise, it returns L|/type/Mu>. =begin code :skip-test say $mp3.^find_method('name'); # OUTPUT: «(Mu)␤» say $mp3.^find_method('artist'); # OUTPUT: «artist␤» =end code X<|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|/routine/private_methods> and L|/routine/find_private_method>. =begin code :skip-test say $mp3.^private_methods; # OUTPUT: «(parse-data can-read-format trim-nulls)␤» say $mp3.^find_private_method('parse-data'); # OUTPUT: «parse-data␤» say $mp3.^find_private_method('remove-nulls'); # OUTPUT: «(Mu)␤» =end code Introspection is very useful for debugging and for learning the language and new libraries. When a function or method returns an object you don't know about, by finding its type with C<.^name>, seeing a construction recipe 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 Some classes might need their own version of C, which overrides the terse way they are printed when called to provide a default representation of the class. For instance, L might want to write just the C 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 => , 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 last, first #...more fields... Wall, Larry Conway, Damian =end code Load the first record and show its contents: =begin code :preamble 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 list as a constant since its values are the same for all class objects: =begin code constant @fields = ; 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 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. There are several L to make IRC activity more convenient and fun. You can read about IRC content L in greater details. L serves a similar purpose. Thanks to the bridges written by fellow Raku members, it integrates well with the main IRC channels. L is also a great resource for asking questions and helping others with their Raku problems and challenges. More resources can be found in the L. =head2 Offline communities Raku is also a common topic at L and L. If you prefer in-person meetings, these are warmly recommended! =head2 Other resources L, 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, 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. =head1 Raku Advent calendar The Raku community publishes every December an L, with Raku tutorials every day until Christmas. Previous calendars (pre name change) are L and relevant. Organization and assignment of days is done through the different Raku channels and the L repository. If you want to participate, its organization starts by the end of October, so check out the channels above to keep up to date. =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, is immediately processed by the C 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 has both paradigms. At the B 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. Then they can be Cd by a developer in her own program. The effect is to make C top level programs run quickly. One of the great strengths of the C 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 takes integration even further, making it relatively easy for C programs to incorporate system libraries written in other languages into C programs, see L. The experience from C 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|/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 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 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 enables all of these possibilities, allowing for multiple versions, multiple authorities, and multiple APIs to be present, installed, and available locally. The way classes and modules can be accessed with specific attributes is explained L. This tutorial is about how C handles these possibilities. =head1 Introduction Before considering the C framework, let's have a look at how languages like C or C handle module installation and loading. =begin code :lang 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 and C use a list of include paths, to complete these paths. In C they are available in the global C<@INC> array. =begin code :lang @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 first looks for a C<.pmc> file. And C 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 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 Foo::Bar:auth: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 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:ver<0.3>:api<1>» will always be the name for exactly the same code. =head2 $*REPO In C and C you deal with include paths pointing to filesystem directories. In C we call such directories "repositories" and each of these repositories is governed by an object that does the L|/type/CompUnit::Repository> role. Instead of an B> array, there's the C<$*REPO> variable. It contains a single repository object. This object has a B attribute that may contain another repository. In other words: repositories are managed as a I. 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 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 method. A C or C statement in C code is basically translated to a call to B>'s C method. This method may in turn delegate the request to the next-repo. =begin code :preamble :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|/type/CompUnit::Repository::FileSystem> and L|/type/CompUnit::Repository::Installation>. The FileSystem repo is meant to be used during module development and actually works just like C when looking for a module. It doesn't support versions or Cs 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 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 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 %?RESOURCES %?RESOURCES %?RESOURCES %?RESOURCES 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 we need to load the precompiled files of all its dependencies, too. And those dependencies B be precompiled, we cannot load them from source files. Even worse, the precomp files of the dependencies B 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 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 L. =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. Parallelism is about doing multiple things at once. I, 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|/type/Thread> and L|/type/Scheduler>) and use the higher-level interfaces. =head1 High-level APIs X<|Other languages,Futures> =head2 Promises A L|/type/Promise> (also called I 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|/type/Promise> starts from a C status and can result in either a C status, meaning the promise has been successfully completed, or a C 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 method: my $promise1 = Promise.new(); my $promise2 = $promise1.then( -> $v { say $v.result; "Second Result" } ); $promise1.keep("First Result"); say $promise2.result; # OUTPUT: «First Result␤Second Result␤» Here the L method schedules code to be executed when the first L|/type/Promise> is kept or broken, itself returning a new L|/type/Promise> which will be kept with the result of the code when it is executed (or broken if the code fails). C changes the status of the promise to C setting the result to the positional argument. C 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), otherwise it will throw an exception based on the value passed to C. 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 will cause the code block of the C to throw an exception when it calls the C 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|/type/Exception> object will then be available from C. If the promise had not been broken C would raise an L|/type/X::Promise::CauseOnlyValidOnBroken> exception. A L|/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 creates a new promise and schedules a new task to call C on it no earlier than the supplied number of seconds, returning the new L|/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 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 of the promise returned is the value returned from the code. Similarly if the code fails (and the promise is thus broken), then C will be the L|/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 is almost equivalent to calling C on the promise object returned by C 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, two class methods combine several L|/type/Promise> objects into a new promise: C 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 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 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, 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|/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 or C will do this, so it is not necessary to do it for these. =head2 Supplies A L|/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 or reactive designs. At its simplest, a L|/type/Supply> is a message stream that can have multiple subscribers created with the method C on to which data items can be placed with C. There are two types of Supplies: C and C. A C supply is like a TV broadcast: those who tune in don't get previously emitted values. An C broadcast is like a video streaming service: everyone who starts streaming a movie (taps a L|/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 supplies, instead, the C block is run for each tap of the supply. A C L|/type/Supply> is created by the L|/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 is called on a L|/type/Supply> object created by the L|/type/Supplier> and new values are emitted on the L|/type/Supplier>. X<|Reference,supply (on-demand)> An C L|/type/Supply> is created by the C 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|/type/Supply> returned by C 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 method returns a L|/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 on the supply object calls the C 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 returns a new C 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 which specifies a delay in seconds before the first event is fired. Each tap of a supply created by C 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|/type/Supply> that keeps values until first tapped can be created with L|/type/Supplier::Preserving>. =head3 X|Control flow,whenever> The C 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|/type/Supply>, a L|/type/Channel>, a L|/type/Promise> or an L|/type/Iterable>. Please note that one should keep the code inside the C as small as possible, as only one C block will be executed at any time. One can use a C block inside the C 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|Control flow,react> The C keyword introduces a block of code containing one or more C 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 keyword, but a react block requires at least one C to be of any real use. react { whenever Supply.interval(2) -> $v { say $v; done() if $v == 4; } } Here the C keyword uses L«C<.act>|/type/Supply#method_act» to create a tap on the L|/type/Supply> from the provided block. The C block is exited when C is called in one of the taps. An C L|/type/Supply> can also be created from a list of values that will be emitted in turn, thus the first C 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 and C respectively, to create a new supply in a manner like the similarly named list methods: C returns a supply such that only those events emitted on the source stream for which the C 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 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 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 and C options in the call to C: =begin code :preamble $supply.tap: { ... }, done => { say 'Job is done.' }, quit => { when X::MyApp::Error { say "App Error: ", $_.message } }; =end code The C block works very similar to a C. If the exception is marked as seen by a C or C block, the exception is caught and handled. Otherwise, the exception continues to up the call tree (i.e., the same behavior as when C is not set). =head3 Phasers in a supply or react block If you are using the C or C block syntax with C, you can add phasers within your C blocks to handle the C and C messages from the tapped supply: =begin code :preamble 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 and C on C. =head2 Channels A L|/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|/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|/type/Supply>. An item is queued onto the L|/type/Channel> with the L, and the L 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 then any C will cause the exception L|/type/X::Channel::SendOnClosed> to be thrown, and a C will throw an L|/type/X::Channel::ReceiveOnClosed>. The L returns all the items on the L|/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 that returns an available item from the channel or L|/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 returns a L|/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 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|/type/Supply> in the C of a C 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|/type/Channel> from a L|/type/Supply> using the L which returns a L|/type/Channel> which is fed by a C on the L|/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|/type/Channel> will return a different L|/type/Channel> fed with the same data each time it is called. This could be used, for instance, to fan-out a L|/type/Supply> to one or more L|/type/Channel>s to provide for different interfaces in a program. =head2 Proc::Async L|/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 is called, which will return a L|/type/Promise> that will be kept when the program exits. The standard output and standard error of the program are available as L|/type/Supply> objects from the methods L and L 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, L or L 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 without a file argument in this example, ) won't exit until their standard input is closed so L can be called when you are finished writing to allow the L|/type/Promise> returned by C to be kept. =head1 Low-level APIs =head2 Threads The lowest level interface for concurrency is provided by L|/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|/type/Thread> object can be waited on with the C method which will block until the thread completes: =for code :preamble $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|/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|/type/Proc::Async>, L|/type/Promise> and L|/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|/type/Scheduler> interface) is the C method: method cue(:&code, Instant :$at, :$in, :$every, :$times = 1; :&catch) This will schedule the L|/type/Callable> in C<&code> to be executed in the manner determined by the adverbs (as documented in L|/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|/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|/type/Scheduler> interface provides over that of L|/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|/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 at the time the program is started. If the maximum is exceeded then C may queue the code until a thread becomes available. =head3 CurrentThreadScheduler The L|/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 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|/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|/type/Promise>, L|/type/Supply> and L|/type/Channel>) use a L|/type/Lock> where required it is unlikely that user code will need to use a L|/type/Lock> directly. The primary interface to L|/type/Lock> is the method L 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 returns whatever the code block returns. Because C will block any threads that are waiting to execute the critical section the code should be as quick as possible. =head2 Lock::Async L|/type/Lock::Async> is a mutual exclusion mechanism much like Lock, but it exposes its functionality through L|/type/Promise>s, allowing the use of C 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 Ced by the lock. L|/type/Lock::Async> is more high-level than L|/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. One particular issue of note is when container autovivification or extension takes place. When an L|/type/Array> or a L|/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|/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 containers in Raku, see the overview of L; for I containers, see L. =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, 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, or I for short. This is a per-scope data structure that stores a pointer for each variable. In the case of C, the lexpad entry for the variable C<$x> is a pointer to an object of type L|/type/Scalar>, usually just called I. =head1 Scalar containers Although objects of type L|/type/Scalar> are everywhere in Raku, you rarely see them directly as objects, because most operations I, which means they act on the L|/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|/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|/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: my $x = 23; sub f() is rw { $x }; f() = 42; say $x; # OUTPUT: «42␤» For explicit returns, C instead of C must be used. Returning a container is how C 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 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|/type/Routine> call and the actual call of the method L 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|/type/Callable>. The default type constraint is L|/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|/type/Routine>s to be used as L 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 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|/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. X<|Language,\ (container binding)> Sigilless variables and parameters with the trait C 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|/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|/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|/type/Scalar> container type hides itself well, but L|/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|/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|/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|/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: 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|/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 as the corresponding elements of the resulting list. C, in the other hand, I 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 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|/type/Array> and L|/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 timeouts. =head1 Type constraints Any container can have a type constraint in the form of a L or a L. Both can be placed between a declarator and the variable name or after the trait L. 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. The default type constraint of a L|/type/Scalar> container is L|/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. 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|/type/Proxy>. Its constructor takes two arguments, C AND C, 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 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 The I context is equivalent to what other languages call C 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 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|/type/Iterator>s, by using the L|/routine/sink-all> method. L|/type/Proc>s can also be L 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 are explicitly evaluated in sink context, with values returned explicitly using C: =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 is run in sink context, and within it, C is too. Results are taken explicitly from the loop via gather/take. In sink context, an object will call its C method if present: =begin code sub foo { return [] does role { method sink { say "sink called" } } } foo; # OUTPUT: «sink called␤» =end code =head1 X This context, and probably all other contexts except I above, are I or I 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|/type/Str> to L|/type/Numeric>, for instance); in other cases simply an interpretation (L|/type/IntStr> will be interpreted as L|/type/Int> or as L|/type/Str>). I 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|/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= ; 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 things, the numeric value will be in general equivalent to C<.elems>; in some cases, like L|/routine/Numeric#(Thread)_method_Numeric>, it will return a unique thread identifier. =head1 X In a I, 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 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 routine|/routine/Str> will be called on a variable to contextualize it; since this method is inherited from L|/type/Mu>, it is always present, but it is not always guaranteed to work. In some core classes it will issue a warning. L|/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|/language/operators#Reduction_operators> context, when C<[~]> is applied to a list say [~] [ 3, 5+6i, Set(), [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 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|/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 creates a mixin, which endows the complex number with a L|/type/Str> method. C contextualizes it into a string, that is, it calls L|/type/Str>, the string contextualizer, with the result shown above. =head1 X This context will force a variable to be interpreted as C or C. say "Hey" if 7; # OUTPUT: «Hey␤» say "Ahoy" if ""; This context appears in expressions such as C or C, and is equivalent to calling C 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; zero or empty will be equivalent to C. 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 There are actually several different L, 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 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|/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'); # OUTPUT: «value␤» Itemization I 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, $, 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|/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 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 Like many other languages, Raku uses C enclosed by C<{> and C<}> to turn a sequence of statements into a L|/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: «2␤3␤» 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. 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|/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|/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: «42␤43␤» ...but: =begin code :skip-test { 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 { "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 class C { say "I live"; die "I will never live!" }; my $c = C.new; │ # OUTPUT: Fails and writes «I live␤I will never live!␤ =end code This block will first run the first statement, and then C printing the second statement. C<$c> will never get a value. =head1 X Blocks may have I: special labeled blocks that break their execution into phases that run in particular phases. See the page L for the details. =head1 X The simplest way to run a block where it cannot be a stand-alone statement is by writing C 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 and the block. The whole C 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 rules as everything else. Technically, C is a loop which runs exactly one iteration. A C 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 3, if 1 { 2 } ; # Syntax error As a consequence, C does not run blocks that, by their syntax, must be functions. For example, if C«->» is used to specify a L, C 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 The simplest way to run a statement or block B is by writing C before it: =for code start { sleep 1; say "done" } say "working"; # working, done Note that you need a space between the C and the block. In the example above, the C 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 in version 6.d, while it will simply get out after waiting for 10 seconds in version 6.c. The C immediately returns a L|/type/Promise> that can be safely ignored if you are not interested in the result of the block. If you B 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 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 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 To conditionally run a block of code, use an C followed by a condition. The condition, an expression, will be evaluated immediately after the statement before the C finishes. The block attached to the condition will only be evaluated if the condition means C when coerced to L|/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 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 called a "statement modifier" form. In this case, the C 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 statement itself will either L|/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 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 block that guarantees their being C. This gives this solution an advantage over the more conventional C. Compare L|/language/control#with>, which tests for definedness rather than truth, and topicalizes by default. (The second C in the above example could be replaced by C if the routine C returned L|/type/Nil> rather than 0 for nonexistent usernames.) =head2 X|Control flow,else elsif> A compound conditional may be produced by following an C conditional with C 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 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 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 and the C using C. 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 instead of an C 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 or C: =for code :skip-test 42.say if 0 else { 43.say } # syntax error All the same rules for semicolons and newlines apply, consistently =for code :skip-test 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|/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, which could be from C or the last C 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|Control flow,unless> When you get sick of typing "if not (X)" you may use C to invert the sense of a conditional statement. You cannot use C or C with C because that ends up getting confusing. Other than those two differences C works the same as L: =for code unless 1 { "1 is false".say } ; # does not say anything, since 1 is true =for code :skip-test 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|Control flow,with orwith without> The C statement is like C, but tests for definedness rather than truth, and it topicalizes on the condition, much like C: with "abc".index("a") { .say } # prints 0 Similarly to C, C 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-based and C-based clauses. # This says "Yes" if 0 { say "No" } orwith Nil { say "No" } orwith 0 { say "Yes" }; As with C, you may use C to check for undefinedness, but you may not add an C clause: my $answer = Any; without $answer { warn "Got: {$_.raku}" } There are also C and C statement modifiers: my $answer = (Any, True).roll; say 42 with $answer; warn "undefined answer" without $answer; As with the other chainable constructs, an C completing a C..C chain will itself topicalize to the value of the prior (failed) condition's topic (either the topic of C or the final C or C). In the case of an C following a C or C, topicalizing a value guaranteed to be undefined may seem useless. But it makes for a useful idiom when used in conjunction with operations that may fail, because L|/type/Failure> values are always undefined: =begin code sub may_fail( --> Numeric:D ) { my $value = (^10).pick || fail "Zero is unacceptable"; fail "Odd is also not okay" if $value % 2; return $value; } with may_fail() -> $value { # defined, so didn't fail say "I know $value isn't zero or odd." } else { # undefined, so failed, and the Failure is the topic say "Uh-oh: {.exception.message}." } =end code Note that while topicalizing a L|/type/Failure> marks it L|/type/Failure#method_handled>—so you can use the C/C to proceed safely with execution—it doesn't make the I safe. Even within the C clause, if you try to use the value directly, it will result in your C clause itself failing (or, in Rakudo, "promoting" the Failure into a thrown exception). But as seen above, you I use the methods of a handled L|/type/Failure> object the C topicalizes, such as L|/type/Failure#method_exception>, if you wish to provide diagnostics or interrogate the underlying L|/type/Exception>. =head1 X The C block is similar to an C block and either or both can be used in an outer block; they also both have a "statement modifier" form. But there is a difference in how following code in the same, outer block is handled: When the C block is executed, control is passed to the enclosing block and following statements are ignored; but when the C block is executed, following statements are executed. N The following examples should illustrate the C or C block's default behavior assuming no special exit or other side effect statements are included in the C or C blocks: =begin code { if X {...} # if X is true in Boolean context, block is executed # following statements are executed regardless } { when X {...} # if X is true in Boolean context, block is executed # and control passes to the outer block # following statements are NOT executed } =end code Should the C and C blocks above appear at file scope, following statements would be executed in each case. There is one other feature C has that C doesn't: the C's Boolean context test defaults to C<$_ ~~> while the C's does not. That has an effect on how one uses the X in the C block without a value for C<$_> (it's L|/type/Any> in that case and L|/type/Any> smartmatches on C: C yields C). Consider the following: =begin code { my $a = 1; my $b = True; when $a { say 'a' }; # no output when so $a { say 'a' } # a ("so $a" 'so' coerces $a to Boolean context True # which matches with Any) when $b { say 'b' }; # no output (this statement won't be run) } =end code Finally, C's statement modifier form does not affect execution of following statements either inside or outside of another block: =begin code say "foo" when X; # if X is true statement is executed # following statements are not affected =end code Since a successful match will exit the block, the behavior of this piece of code: =begin code $_ = True; my $a; { $a = do when .so { "foo" } }; say $a; # OUTPUT: «(Any)␤» =end code is explained since the C block is abandoned before any value is stored or processed. However, in this case: =begin code $_ = False; my $a; { $a = do when .so { "foo" } }; say $a; # OUTPUT: «False␤» =end code the block is not abandoned since the comparison is false, so C<$a> will actually get a value. =head1 X The C loop iterates over a list, running the statements inside a L|/type/Block> once on each iteration. If the block takes parameters, the elements of the list are provided as arguments. By default, the block takes one parameter, C<$_>: my @foo = 1..3; for @foo { $_.print } # prints each value contained in @foo for @foo { .print } # same thing, because .print implies a $_ argument for @foo { 42.print } # prints 42 as many times as @foo has elements Pointy block syntax or a L may be used to name the parameter: my @foo = 1..3; for @foo -> $item { print $item } for @foo { print $^item } # same thing Multiple parameters can be declared, in which case the iterator takes as many elements from the list as needed before running the block. my @foo = 1..3; for @foo.kv -> $idx, $val { say "$idx: $val" } my %hash = Z=> 1,2,3; for %hash.kv -> $key, $val { say "$key => $val" } for 1, 1.1, 2, 2.1 { say "$^x < $^y" } # OUTPUT: «1 < 1.1␤2 < 2.1␤» Parameters of a pointy block can have default values, allowing the code to handle lists with missing elements. my @list = 1,2,3,4; for @list -> $a, $b = 'N/A', $c = 'N/A' { say "$a $b $c" } # OUTPUT: «1 2 3␤4 N/A N/A␤» When no parameters are specified for a C loop's block, C can be used within it similarly to how it's used in a C block: # A solution for FizzBuzz: for 1..100 { when * %% 15 { say 'FizzBuzz' } when * %% 3 { say 'Fizz' } when * %% 5 { say 'Buzz' } default { say $_ } } If the postfix form of C is used, a block is not required and the topic is set for the statement list. say „I $_ butterflies!“ for <♥ ♥ ♥>; # OUTPUT: «I ♥ butterflies!␤I ♥ butterflies!␤I ♥ butterflies!␤» A C may be used on lazy lists – it will only take elements from the list when they are needed, so to read a file line by line, you could use: =for code for $*IN.lines -> $ln { $ln.say } Iteration variables are always lexical, so you don't need to use C to give them the appropriate scope. Also, they are read-only aliases. If you need them to be writable, use C«<->» instead of C«->». Alternatively, you can add the L«C«is rw»|/language/signatures#Parameter_traits_and_modifiers» trait; this performs a binding operation so assigning to the parameter changes the value of the variable at the caller side. If instead you want to modify copies of the arguments within the block, add L«C«is copy»|/language/signatures#Parameter_traits_and_modifiers». =begin code my @foo = 1..3; for @foo <-> $value { $value = $value %% 2 ?? "Even" !! "Odd" } say @foo; # OUTPUT: «[Odd Even Odd]␤» @foo = 1..3; for @foo -> $value is rw { $value = $value %% 2 ?? "Even" !! "Odd" } say @foo; # OUTPUT: «[Odd Even Odd]␤» @foo = 1..3; my @bar; for @foo -> $value is copy { $value = $value %% 2 ?? "Even" !! "Odd"; @bar.push: $value } say @foo; # OUTPUT: «[1 2 3]␤» say @bar; # OUTPUT: «[Odd Even Odd]␤» =end code This rule also applies to the topic variable C«$_», which by default is a read-write alias; it will become read-only if it's used in a C«->» loop. my @foo = 1..3; for @foo -> $_ { $_.say } # Error: ...require mutable arguments for @foo -> $_ { $_++ } A C loop can produce a L|/type/List> of the values produced by each run of the attached block. To capture these values, put the for loop in parenthesis or assign them to an array: (for 1, 2, 3 { $_ * 2 }).say; # OUTPUT: «(2 4 6)␤» my @a = do for 1, 2, 3 { $_ * 2 }; @a.say; # OUTPUT: «[2 4 6]␤» my @b = (for 1, 2, 3 { $_ * 2 }); @b.say; # OUTPUT: «[2 4 6]␤» This implies that, if the results of the loop are not assigned, they will be in a L: =for code class Sunk { has $.titanic; method sink { say "Sinking $!titanic"; } } Sunk.new( :titanic($_) ) for ^3; for 1 { say "About to sink"; Sunk.new( :titanic($_) ); } # OUTPUT: # Sinking 0 # Sinking 1 # Sinking 2 # About to sink # Sinking 1 The first loop creates three elements but they are in a sink context, so its C method is called. In the second loop, its last statement will be in a sink context, so it will be also sunk (from version 6.d). The C constant will act as a no-op for a loop: =for code say "Not here" for Empty; Will not do anything. This constant is L. Undefined values will behave in the same way: =for code my @array := Empty; .say for @array; say @array; # OUTPUT: «()␤» Assigning C will effectively undefine an L|/type/Array>, using C over an undefined array will not even enter the loop, as shown, effectively behaving in the same way as above when C was used directly. With C and C, the C loop is potentially iterated in parallel. See also the documentation for C and C in class L|/type/Map>. =for code my $primes_h = hyper for ^10_000 -> $number { $number if $number.is-prime }; say $primes_h.elems; # OUTPUT: «1229␤» say $primes_h.tail: 5; # OUTPUT: «(9931 9941 9949 9967 9973)␤» with C the order of elements is preserved. =for code my $primes_r = race for ^10_000 -> $number { $number if $number.is-prime }; say $primes_r.elems; # OUTPUT: «1229␤» Unlike C, C does not preserve the order of elements. =head1 X C is a statement or block prefix that returns a L of values. The values come from calls to L in the dynamic scope of the C code. In the following example, we implement a subroutine to compute the factors of an integer with C (note that the factors are not generated in order): sub factors( Int:D \n ) { my $k = 1; gather { while $k**2 < n { if n %% $k { take $k; take n div $k; } $k++; } take $k if $k**2 == n; } } say factors(36); # OUTPUT: «1, 36, 2, 18, 3, 12, 4, 9, 6␤» The C combination can generate values lazily, depending on context. Binding to a scalar or sigilless container will force laziness. If you want to force lazy evaluation use the L subroutine or method. For example: my @vals = lazy gather { take 1; say "Produced a value"; take 2; } say @vals[0]; say 'between consumption of two values'; say @vals[1]; # OUTPUT: # 1 # between consumption of two values # Produced a value # 2 C is scoped dynamically, so you can call C from subs or methods that are called from within C: sub weird(@elems, :$direction = 'forward') { my %direction = ( forward => sub { take $_ for @elems }, backward => sub { take $_ for @elems.reverse }, random => sub { take $_ for @elems.pick(*) }, ); return gather %direction{$direction}(); } say weird(, :direction ); # OUTPUT: «(c b a)␤» If values need to be mutable on the caller side, use L. Note that the L|/type/Seq> created by C may be coerced to another type. An example with assignment to a hash: my %h = gather { take "foo" => 1; take "bar" => 2}; say %h; # OUTPUT: «{bar => 2, foo => 1}␤» B: C must not be used to collect results from C. The C block is not run from the thread that runs the C, but the thread that runs the C. On this thread, there is no handler for the control exception thrown by C, causing it to error out. =head1 X The keyword C creates a L which is an L that you can tap. It pairs with C, which can be used anywhere from within C prefixed code. Using the L|/type/Mu#method_emit> or the L|/type/independent-routines#sub_emit> passes the invocant to the enclosing L: my $supply = supply { .emit for "foo", 42, .5; } $supply.tap: { say "received {.^name} ($_)"; } # OUTPUT: # received Str (foo) # received Int (42) # received Rat (0.5) See also: L|/routine/tap> and L|/type/Supplier>. X<|Other languages,switch (given)> X<|Other languages,case statements (given)> =head1 X The C statement is Raku's topicalizing keyword in a similar way that C topicalizes in languages such as C. In other words, C sets C<$_> inside the following block. The keywords for individual cases are C and C. The usual idiom looks like this: my $var = (Any, 21, any ).pick; given $var { when 21 { say $_ * 2 } when 'lie' { .say } default { say 'default' } } The C statement is often used alone: given 42 { .say; .Numeric; } This is a lot more understandable than: { .say; .Numeric; }(42) =head2 X A block containing a C statement will be left immediately when the sub-block after the C statement is left. It is as though the rest of the statements in the block were skipped. given 42 { "This says".say; $_ == 42 and ( default { "This says, too".say; 43; } ); "This never says".say; } # The above block evaluates to 43 A C statement will also do this (but a C statement modifier will I.) In addition, C statements C the topic (C<$_>) against a supplied expression such that it is possible to check against values, regular expressions, and types when specifying a match. for 42, 43, "foo", 44, "bar" { when Int { .say } when /:i ^Bar/ { .say } default { say "Not an Int or a Bar" } } # OUTPUT: «42␤43␤Not an Int or a Bar␤44␤Bar␤» In this form, the C/C construct acts much like a set of C/C/C statements. Be careful with the order of the C statements. The following code says C<"Int"> not C<42>. given 42 { when Int { say "Int" } when 42 { say 42 } default { say "huh?" } } # OUTPUT: «Int␤» When a C statement or C statement causes the outer block to return, nesting C or C blocks do not count as the outer block, so you can nest these statements and still be in the same "switch" just so long as you do not open a new block: given 42 { when Int { when 42 { say 42 } say "Int" } default { say "huh?" } } # OUTPUT: «42␤» C statements can smartmatch against L. =head2 X and X Both C and C are meant to be used only from inside C or C blocks. The C statement will immediately leave the C or C block, skipping the rest of the statements, and resuming after the block. This prevents the C or C from exiting the outer block. =for code given * { default { proceed; "This never says".say } } "This says".say; This is most often used to enter multiple C blocks. C will resume matching after a successful match, like so: given 42 { when Int { say "Int"; proceed } when 42 { say 42 } when 40..* { say "greater than 40" } default { say "huh?" } } # OUTPUT: «Int␤» # OUTPUT: «42␤» Note that the C match didn't occur. For this to match such cases as well, one would need a C in the C block. This is not like a C C statement, because the C does not merely enter the directly following block, it attempts to match the C value once more, consider this code: given 42 { when Int { "Int".say; proceed } when 43 { 43.say } when 42 { 42.say } default { "got change for an existential answer?".say } } # OUTPUT: «Int␤» # OUTPUT: «42␤» ...which matches the L|/type/Int>, skips C<43> since the value doesn't match, matches C<42> since this is the next positive match, but doesn't enter the C block since the C block doesn't contain a C. By contrast, the C keyword short-circuits execution and exits the entire C block at that point. It may also take an argument to specify a final value for the block. say do given 42 { when Int { succeed "Found"; say "never this!"; } when 42 { say 42 } default { say "dunno?" } } # OUTPUT: «Found␤» If you are not inside a when or default block, it is an error to try to use C or C.Also remember, the C statement modifier form does not cause any blocks to be left, and any C or C in such a statement applies to the surrounding clause, if there is one: given 42 { { say "This says" } when Int; "This says too".say; when * > 41 { { "And this says".say; proceed } when * > 41; "This never says".say; } "This also says".say; } # OUTPUT: «This says␤This says too␤And this says␤This also says␤» =head2 X C can follow a statement to set the topic in the statement it follows. .say given "foo"; # OUTPUT: «foo␤» printf "%s %02i.%02i.%i", [.day-of-week - 1], .day, .month, .year given DateTime.now; # OUTPUT: «Sa 03.06.2016» =head1 X The C statement takes three statements in parentheses separated by C<;> that take the roles of initializer, conditional and incrementer, respectively. The initializer is executed once before the conditional is first tested. In case the initializer involves a variable declaration, the variable is declared as a lexical variable in the loop's I scope so that it can be used in code following the loop statement. The conditional is executed before each iteration and coerced to L|/type/Bool>; if C the loop is stopped. The incrementer is executed after each iteration, and before the conditional is tested again. loop (my $i = 0; $i < 10; $i++) { # A typical loop say $i; } my @str = "However Long".comb; # Our very own .chars routine: loop (my $l = 0;;) { # Declare $l in outer scope last if !@str[$l++] # and count chars until we hit } # an undefined element (Any) say "The string is {--$l} chars long."; The infinite loop does not require parentheses. =for code loop { say 'forever' } The C statement may be used to produce values from the result of each run of the attached block if it appears in lists: (loop ( my $i = 0; $i++ < 3;) { $i * 2 }).say; # OUTPUT: «(2 4 6)␤» my @a = (loop ( my $j = 0; $j++ < 3;) { $j * 2 }); @a.say; # OUTPUT: «[2 4 6]␤» my @b = do loop ( my $k = 0; $k++ < 3;) { $k * 2 }; @b.say; # same thing Unlike a C loop, one should not rely on whether returned values are produced lazily. It would probably be best to use C to guarantee that a loop whose return value may be used actually runs: sub heads-in-a-row { (eager loop (; 2.rand < 1;) { "heads".say }) } =head1 X The C statement executes the block as long as its condition is true. So my $x = 1; while $x < 4 { print $x++; } print "\n"; # OUTPUT: «123␤» Similarly, the C statement executes the block as long as the expression is false. my $x = 1; until $x > 3 { print $x++; } print "\n"; # OUTPUT: «123␤» The condition for C or C can be parenthesized, but there must be a space between the keyword and the opening parenthesis of the condition. Both C and C can be used as statement modifiers. E. g. my $x = 42; $x-- while $x > 12 See L|#next>, L|#last>, and related below for ways to fine-tune loop control. Also see C and C for other loop syntax. All these forms may produce a return value the same way C does. =head1 X Executes the block I and, if the condition allows, repeats that execution. This differs from C/C in that the condition is evaluated at the end of the loop, even if it appears at the front. my $x = -42; repeat { $x++; } while $x < 5; $x.say; # OUTPUT: «5␤» repeat { $x++; } while $x < 5; $x.say; # OUTPUT: «6␤» repeat while $x < 10 { $x++; } $x.say; # OUTPUT: «10␤» repeat while $x < 10 { $x++; } $x.say; # OUTPUT: «11␤» repeat { $x++; } until $x >= 15; $x.say; # OUTPUT: «15␤» repeat { $x++; } until $x >= 15; $x.say; # OUTPUT: «16␤» repeat until $x >= 20 { $x++; } $x.say; # OUTPUT: «20␤» repeat until $x >= 20 { $x++; } $x.say; # OUTPUT: «21␤» All these forms may produce a return value the same way C does. =head1 X A block or statement prefixed with C will be executed exactly once, even if placed inside a loop or a recursive routine. my $guard; loop { once $guard = 3; last if $guard-- <= 0; once { put 'once' }; print 'many' } # OUTPUT: «once␤manymanymany» This works per "clone" of the containing code object, so: ({ once 42.say } xx 3).map: {$_(), $_()}; # says 42 thrice Note that this is B a thread-safe construct when the same clone of the same block is run by multiple threads. Also remember that methods only have one clone per class, not per object. =head1 LABELs C, C, C and C loops can all take a label, which can be used to identify them for C, C, and C. Nested loops are supported, for instance: OUTAHERE: while True { for 1,2,3 -> $n { last OUTAHERE if $n == 2; } } Labels can be used also within nested loops to name each loop, for instance: =begin code OUTAHERE: loop ( my $i = 1; True; $i++ ) { OUTFOR: for 1,2,3 -> $n { # exits the for loop before its natural end last OUTFOR if $n == 2; } # exits the infinite loop last OUTAHERE if $i >= 2; } =end code =head1 X The C command starts the next iteration of the loop. So the code =begin code my @x = 1, 2, 3, 4, 5; for @x -> $x { next if $x == 3; print $x; } =end code prints "1245". You can also use C in a C: the above example then looks like: =begin code my @x = 1, 2, 3, 4, 5; print @x.map: -> $x { next if $x == 3; $x } =end code prints "1 2 4 5" because a space is added between entries of a L|/type/Seq> when it is stringified. Note that that C was not put inside the block of the C, as it generally considered bad practice to run a C for its side-effects (in this case, the C. If the L phaser|/language/phasers#NEXT> is present, it runs before the next iteration: =begin code my Int $i = 0; while ($i < 10) { if ($i % 2 == 0) { next; } say "$i is odd."; NEXT { $i++; } } # OUTPUT: «1 is odd.␤3 is odd.␤5 is odd.␤7 is odd.␤9 is odd.␤» =end code In version 6.e.PREVIEW (available as of the 2021.07 Rakudo compiler release), it is also possible to return a value with the C statement. This is particularly useful when using it in a C: =begin code my @x = 1, 2, 3, 4, 5; print @x.map: -> $x { next 42 if $x == 3; $x } =end code prints "1 2 42 4 5". In a L block, C immediately exits the block for the current value: react { whenever Supply.interval(1) { next if .is-prime; say $_; done if $_ == 4; } } prints "0", "1" and "4" - integers from 0 to 4 with primes skipped. *Since version 6.d, the C command in a loop that collects its last statement values returns C for the iterations they run on.* =head1 X The C command immediately exits the loop in question. =begin code my @x = 1, 2, 3, 4, 5; for @x -> $x { last if $x == 3; print $x; } =end code prints "12". You can also use C in a C: the above example then looks like: =begin code my @x = 1, 2, 3, 4, 5; print @x.map: -> $x { last if $x == 3; $x } =end code prints "1 2" because a space is added between entries of a L|/type/Seq> when it is stringified. Note that that C was not put inside the block of the C, as it generally considered bad practice to run a C for its side-effects (in this case, the C. If the L phaser|/language/phasers#LAST> is present, it runs before exiting the loop: =begin code my Int $i = 1; while ($i < 10) { if ($i % 5 == 0) { last; } LAST { say "The last number was $i."; } NEXT { $i++; } } # OUTPUT: «The last number was 5.␤» =end code Since version 6.d, the C command in a loop that collects its last statement values returns C for the iterations they run on. In version 6.e.PREVIEW (available as of the 2021.07 Rakudo compiler release), it is also possible to return a value with the C statement. This is particularly useful when using it in a C: =begin code my @x = 1, 2, 3, 4, 5; print @x.map: -> $x { last 42 if $x == 3; $x } =end code print "1 2 42". =head1 X The C command restarts the loop block without evaluating the conditional again. =for code for 1..5 -> $current-level { state $total-attempts = 0; $total-attempts++; print("Entering #$current-level. "); if $total-attempts %% 3 { redo; } } # OUTPUT: «Entering #1... Entering #2... Entering #3... Entering #3... Entering #4... Entering #5... Entering #5... » =head1 X The sub C will stop execution of a subroutine or method, run all relevant L and provide the given return value to the caller. The default return value is L|/type/Nil>. If a return L is provided it will be checked unless the return value is L|/type/Nil>. If the type check fails the exception L|/type/X::TypeCheck::Return> is thrown. If it passes a control exception is raised and can be caught with L. Any C in a block is tied to the first L|/type/Routine> in the outer lexical scope of that block, no matter how deeply nested. Please note that a C in the root of a package will fail at runtime. A C in a block that is evaluated lazily (e.g. inside C) may find the outer lexical routine gone by the time the block is executed. In almost any case C is the better alternative. Please check L for more information on how return values are handled and produced. =head1 X The sub C will return values, not containers. Those are immutable and will lead to runtime errors when attempted to be mutated. sub s(){ my $a = 41; return $a }; say ++s(); CATCH { default { say .^name, ': ', .Str } }; # OUTPUT: «X::Multi::NoMatch.new(dispatcher … To return a mutable container, use C. sub s(){ my $a = 41; return-rw $a }; say ++s(); # OUTPUT: «42␤» The same rules as for C regarding phasers and control exceptions apply. =head1 X Leaves the current routine and returns the provided L|/type/Exception> or L|/type/Str> wrapped inside a L|/type/Failure>, after all relevant L are executed. If the caller activated fatal exceptions via the pragma C, the exception is thrown instead of being returned as a L|/type/Failure>. sub f { fail "WELP!" }; say f; CATCH { default { say .^name, ': ', .Str } } # OUTPUT: «X::AdHoc: WELP!␤» =end pod ================================================ FILE: doc/Language/create-cli.rakudoc ================================================ =begin pod :kind("Language") :subkind("Language") :category("tutorial") =TITLE Command line interface =SUBTITLE Creating your own CLI in Raku X<|Programs,command line arguments> =head1 Command line interface - an overview The default command line interface of Raku scripts consists of three parts: =head2 Parsing the command line parameters into a L|/type/Capture> This looks at the values in L<@*ARGS|/language/variables#index-entry-@*ARGS>, interprets these according to some policy, and creates a L|/type/Capture> object out of that. An alternative way of parsing may be provided by the developer or installed using a module. =head2 Calling a provided C
subroutine using that capture Standard L is used to call the C
subroutine with the generated L|/type/Capture> object. This means that your C
subroutine may be a C, each candidate of which is responsible for some part of processing the given command line arguments. =head2 Creating / showing usage information if calling C
failed If multi dispatch failed, then the user of the script should be informed as well as possible as to why it failed. By default, this is done by inspecting the signature of each C
candidate sub, and any associated Pod information. The result is then shown to the user on STDERR (or on STDOUT if C<--help> was specified). An alternative way of generating the usage information may be provided by the developer or installed using a module. X<|Programs,MAIN> =head1 sub MAIN The sub with the special name C
will be executed after all relevant entry phasers (C, C, C, C
, C) have been run and
the L of the script has been
executed. No error will occur if there is no C
sub: your script will then just have to do the work, such as argument parsing, in the mainline of the script. Any normal exit from the C
sub will result in an exit code of C<0>, indicating success. Any return value of the C
sub will be ignored. If an exception is thrown that is not handled inside the C
sub, then the exit code will be C<1>. If the dispatch to C
failed, a usage message will be displayed on STDERR and the exit code will be C<2>. The command line parameters are present in the C<@*ARGS> dynamic variable and may be altered in the mainline of the script before the C
unit is called. The signature of (the candidates of the multi) sub C
determines which candidate will actually be called using the standard L semantics. A simple example: # inside file 'hello.raku' sub MAIN($name) { say "Hello $name, how are you?" } If you call that script without any parameters, you get the following usage message: =begin code :lang $ raku hello.raku Usage: hello.raku =end code However, if you give a default value for the parameter, running the script either with or without specifying a name will always work: # inside file 'hello.raku' sub MAIN($name = 'bashful') { say "Hello $name, how are you?" } =begin code :lang $ raku hello.raku Hello bashful, how are you? =end code =begin code :lang $ raku hello.raku Liz Hello Liz, how are you? =end code Another way to do this is to make C a C: # inside file 'hello.raku' multi MAIN() { say "Hello bashful, how are you?" } multi MAIN($name) { say "Hello $name, how are you?" } Which would give the same output as the examples above. Whether you should use either method to achieve the desired goal is entirely up to you. If you want to pass an indeterminate number of parameters to be dealt with in C, you can use L: # inside file 'hello-all.raku' sub MAIN(*@all) { for @all -> $name { say "Hello, " ~ $name } } =begin code :lang $ raku hello-all.raku peter paul mary Hello, peter Hello, paul Hello, mary =end code =head2 Multiple named parameters, and C clauses A more complicated example using a single positional and multiple named parameters, and also showing that C clauses can also be applied to C
arguments: =for code :method # inside "frobnicate.raku" sub MAIN( Str $file where *.IO.f = 'file.dat', Int :$length = 24, Bool :$verbose ) { say $length if $length.defined; say $file if $file.defined; say 'Verbosity ', ($verbose ?? 'on' !! 'off'); } The clause C checks that the string C<$file> corresponds to the name of a file that actually exists. The part C<= 'file.dat'> specifies a default value for C<$file> in case no argument for it is given. If a file C is present, a call with no arguments will work this way: =begin code :lang $ raku frobnicate.raku 24 file.dat Verbosity off =end code Or this way with C<--verbose>: =begin code :lang $ raku frobnicate.raku --verbose 24 file.dat Verbosity on =end code If the file C is not present, or you've specified another filename that doesn't exist, you would get the standard usage message created from introspection of the C
sub: =begin code :lang $ raku frobnicate.raku doesnotexist.dat Usage: frobnicate.raku [--length=] [--verbose] [] =end code Such usage messages are generated completely automatically for you. If they seem too terse, you can easily add more information to them. =head2 Improve usage messages with rakudoc comments There's an easy way to make the autogenerated usage message better by providing hints using pod features: =for code :method # inside "frobnicate.raku" sub MAIN( Str $file where *.IO.f = 'file.dat', #= an existing file to frobnicate Int :$length = 24, #= length needed for frobnication Bool :$verbose, #= required verbosity ) { say $length if $length.defined; say $file if $file.defined; say 'Verbosity ', ($verbose ?? 'on' !! 'off'); } Which would improve the usage message like this: =begin code :lang $ raku frobnicate.raku doesnotexist.dat Usage: frobnicate.raku [--length=] [--verbose] [] [] an existing file to frobnicate --length= length needed for frobnication --verbose required verbosity =end code =head2 Command lines and usage messages: more examples From release 2021.03, values to single named arguments can be separated by spaces too. Consider a C program with the following source: subset name of Any where Str|True; subset port of Str; multi MAIN( $file, name :$profile, #= Write profile information to a file port :$debug-port, #= Listen for debugger connections on the specified port Bool :v($verbose), #= Display verbose output ) {} multi MAIN("--process-files", *@images) {} This program generates the following usage message: =begin code :lang Usage: demo [--profile[=name]] [--debug-port=] [-v] demo --process-files [ ...] --profile[=name] Write profile information to a file --debug-port= Listen for debugger connections on the specified port -v Display verbose output =end code The following are valid ways to call C: =for code :lang demo --profile ~/foo demo --profile=/tmp/bar ~/foo demo --debug-port 4242 ~/foo demo --debug-port=4242 ~/foo demo -v ~/foo demo --process-files *.jpg These, however, are not valid =for code :lang demo --profile /tmp/bar ~/foo demo --debug-port ~/foo The first is invalid because C and C<~/foo> are both parsed as positional arguments, which means C was called with too many positional arguments. The second is invalid because C<~/foo> is parsed as an argument to C<--debug-port>, and thus C lacks the required positional argument. Here's how it works; with Raku distinguishing between three types of options: =item Boolean options (like C<-v>), which I take an argument; they are ether present or absent. =item Options with a mandatory argument (like C<--debug-port>), which always take an argument. If you give them an argument with C<=>, they will use that; if not, they'll take the following argument. =item Options with an optional argument (like C<--profile>), which are valid both with and without an argument. You can I give these arguments an option with the C<=> syntax; if there is a space after the option, that means it was called without an argument. And here's the signature that produces each type of argument: =item Boolean options: A L|/type/Bool> type constraint. =item Options with a mandatory argument: A type that does not L|/routine/ACCEPTS> a L|/type/Bool>. =item Options with an optional argument: A type that C<.ACCEPTS> a C (because passing an option without an argument is equivalent to passing C) =head2 Aliases for named parameters As any other subroutine, C
can define L for its named parameters. In particular, this can be used to define single-letter alternative names. =for code :method sub MAIN( Str $file where *.IO.f = 'file.dat', #= an existing file to frobnicate Int :l(:$length) = 24, #= length needed for frobnication Bool :v(:$verbose), #= required verbosity ) { say $length if $length.defined; say $file if $file.defined; say 'Verbosity ', ($verbose ?? 'on' !! 'off'); } In which case, these aliases will also be listed as alternatives with C<--help>: =begin code :lang Usage: frobnicate.raku [--size|--length=] [--verbose] [] [] an existing file to frobnicate -l|--length= length needed for frobnication -v|--verbose required verbosity =end code =head2 Named arrays The MAIN subroutine can also use a different kind of named parameter: the named array. This enables, for instance, providing two different short arrays as arguments on a command line. Declare a named-array parameter with C<:@> in sub MAIN's signature: # inside file 'named-array.raku' sub MAIN(:@n) { .raku.say for @n } You can use this on the command line by repeating the named-array parameter with different values each time. =begin code :lang $ raku named-array.raku --n=foo --n=23 --n=6.3 --n=3e8 --n=2+2i --n=bar "foo" IntStr.new(23, "23") RatStr.new(6.3, "6.3") NumStr.new(300000000e0, "3e8") ComplexStr.new(<2+2i>, "2+2i") "bar" =end code =head2 Enumerations L|/type/Enumeration>s can be used in signatures with arguments converted automatically to its corresponding C symbol: =begin code enum Flag ( FLAG_FOO => 0b001, FLAG_BAR => 0b010, FLAG_BAZ => 0b100, ); sub MAIN(Flag $flag = FLAG_FOO) { say "Flagging $flag with value $flag.value()"; } =end code This will work correctly with =for code :lang raku MAIN-enum.raku FLAG_BAZ # OUTPUT: «Flagging FLAG_BAZ with value 4␤» but will die if called with something that is not a C. =head2 X|Variables,%*SUB-MAIN-OPTS> It's possible to alter how arguments are processed before they're passed to C by setting options in the C<%*SUB-MAIN-OPTS> hash. Due to the nature of dynamic variables, it is required to set up the C<%*SUB-MAIN-OPTS> hash and fill it with the appropriate settings. For instance: my %*SUB-MAIN-OPTS = :named-anywhere, # allow named variables at any location :bundling, # allow bundling of named arguments :coerce-allomorphs-to(Int), # coerce allomorphic arguments to given type :allow-no, # allow --no-foo as alternative to --/foo :numeric-suffix-as-value, # allow -j2 as alternative to --j=2 ; sub MAIN ($a, $b, :$c, :$d) { say "Accepted!" } Available options are: =head3 X|Reference,named-anywhere> By default, named arguments passed to the program (i.e., C
) cannot appear after any positional argument. However, if C«%*SUB-MAIN-OPTS» is set to a true value, named arguments can be specified anywhere, even after positional parameter. For example, the above program can be called with: =begin code :lang $ raku example.raku 1 --c=2 3 --d=4 =end code =head3 X|Programs,command-line argument bundling> When C«%*SUB-MAIN-OPTS» is set to a true value, single letter named arguments can be bundled together with a single dash. The following two commands are then equivalent: =begin code :lang $ raku example.raku -a -b -c $ raku example.raku -abc =end code Bundled arguments can be understood as flags, that can neither be negated, nor assigned a value though: =begin code :lang $ raku example.raku -/a # OK $ raku example.raku -a=asdf # OK $ raku example.raku -abc=asdf # Error $ raku example.raku -/abc # Error =end code This option is only available starting in the 2020.10 release of the Rakudo compiler. =head3 X|Programs,command-line argument coercion> When C«%*SUB-MAIN-OPTS» is set to a specific type, then any L values will be coerced to that type. This can be helpful in any dispatch issues to C
. This option is only available starting in the 2020.12 release of the Rakudo compiler. =head3 X|Programs,allow no- to negate> When C«%*SUB-MAIN-OPTS» is set to a true value, then negation of arguments on the command line can also be indicated by using the C instead of C. =begin code :lang $ raku example.raku --/foo # named argument "foo" is False $ raku example.raku --no-foo # same =end code This option is only available starting in the 2022.12 release of the Rakudo compiler. =head3 X|Programs,simpler way for numeric values> When C«%*SUB-MAIN-OPTS» is set to a true value, then single letter arguments can have a numeric value specified as a suffix. =begin code :lang $ raku example.raku --j=2 # named argument "j" is 2 $ raku example.raku -j2 # same =end code This option is only available starting in the 2022.12 release of the Rakudo compiler. =head2 X|Reference,hidden-from-USAGE> Sometimes you want to exclude a C
candidate from being shown in any automatically generated usage message. This can be achieved by adding a C trait to the specification of the C
candidate you do not want to show. Expanding on an earlier example: # inside file 'hello.raku' multi MAIN() is hidden-from-USAGE { say "Hello bashful, how are you?" } multi MAIN($name) { #= the name by which you would like to be called say "Hello $name, how are you?" } So, if you would call this script with just a named variable, you would get the following usage: =begin code :lang $ raku hello.raku --verbose Usage: hello.raku -- the name by which you would like to be called =end code Without the C trait on the first candidate, it would have looked like this: =begin code :lang $ raku hello.raku --verbose Usage: hello.raku hello.raku -- the name by which you would like to be called =end code Which, although technically correct, doesn't read as well. =head1 X|Reference,unit (MAIN)> If the entire program body resides within C
, you can use the C declarator as follows (adapting an earlier example): =begin code :solo unit sub MAIN( Str $file where *.IO.f = 'file.dat', Int :$length = 24, Bool :$verbose, ); # <- note semicolon here say $length if $length.defined; say $file if $file.defined; say 'Verbosity ', ($verbose ?? 'on' !! 'off'); # rest of script is part of MAIN =end code Note that this is only appropriate if you can get by with just a single (only) C. =head2 X and X If no multi candidate of C
is found for the given command line parameters, the sub C is called. If no such method is found, the compiler will output a default usage message. In the following example, we print a custom usage message via a L (with the C<:c|/language/quoting#Interpolating_closures> flag enabling interpolation of curly braces, and the C<:to|/language/quoting#Heredocs:_:to> flag for stating it all as a heredoc): #|(is it the answer) multi MAIN(Int $i) { say $i == 42 ?? 'answer' !! 'dunno' } #|(divide two numbers) multi MAIN($a, $b){ say $a/$b } sub USAGE() { print Q:c:to/EOH/; Usage: {$*PROGRAM-NAME} [number] Prints the answer or 'dunno'. EOH } The default usage message is available inside C via the read-only C<$*USAGE> variable. It will be generated based on available C candidates and their parameters. As shown before, you can specify an additional extended description for each candidate using a C<#|(...)> Pod block to set L«C|/routine/WHY». =head1 Intercepting usage message generation (2018.10, v6.d and later) You can replace or augment the default way of usage message generation (after a failed dispatch to MAIN) by supplying a C subroutine yourself, or by importing one from any of the L modules available in the ecosystem. =head2 X The C subroutine should accept a L|/type/Callable> representing the C
subroutine that didn't get executed because the dispatch failed. This can be used for introspection. All the other parameters are the parameters that were set up to be sent to C
. It should return the string of the usage information you want to be shown to the user. An example that will just recreate the L|/type/Capture> that was created from processing the arguments: sub GENERATE-USAGE(&main, |capture) { capture:exists ?? "You're not allowed to specify a --foo" !! &*GENERATE-USAGE(&main, |capture) } You can also use multi subroutines to create the same effect: multi GENERATE-USAGE(&main, :$foo!) { "You're not allowed to specify a --foo" } multi GENERATE-USAGE(&main, |capture) { &*GENERATE-USAGE(&main, |capture) } Note that the dynamic variable L|/language/variables#&*GENERATE-USAGE> is available to perform the default usage message generation so you don't have to reinvent the whole wheel if you don't want to. =head1 Intercepting CLI argument parsing (2018.10, v6.d and later) You can replace or augment the default way of argument parsing by supplying an C subroutine yourself, or by importing one from any of the L modules available in the ecosystem. =head2 X The C subroutine should accept two parameters: a L|/type/Callable> representing the C
unit to be executed (so it can be introspected if necessary) and an array with the arguments from the command line. It should return a L|/type/Capture> object that will be used to dispatch the C
unit. The following is a B contrived example that will create a L|/type/Capture> depending on some keyword that was entered (which can be handy during testing of a command line interface of a script): sub ARGS-TO-CAPTURE(&main, @args --> Capture) { # if we only specified "frobnicate" as an argument @args == 1 && @args[0] eq 'frobnicate' # then dispatch as MAIN("foo","bar",verbose => 2) ?? Capture.new( list => , hash => { verbose => 2 } ) # otherwise, use default processing of args !! &*ARGS-TO-CAPTURE(&main, @args) } Note that the dynamic variable L|/language/variables#&*ARGS-TO-CAPTURE> is available to perform the default command line arguments to L|/type/Capture> processing so you don't have to reinvent the whole wheel if you don't want to. =head2 X sub RUN-MAIN(&main, $mainline, :$in-as-argsfiles) This routine allows complete control over the handling of C
. It gets a L|/type/Callable> that is the C
that should be executed, the return value of the mainline execution and an additional named variable: C<:in-as-argsfiles> which will be C if STDIN should be treated as C<$*ARGFILES>. If C is not provided, a default one will be run that looks for subroutines of the old interface, such as C and C. If found, it will execute following the "old" semantics. =begin code class Hero { has @!inventory; has Str $.name; submethod BUILD( :$name, :@inventory ) { $!name = $name; @!inventory = @inventory } } sub new-main($name, *@stuff ) { Hero.new(:name($name), :inventory(@stuff) ).raku.say } RUN-MAIN( &new-main, Nil ); =end code This will print the name (first argument) of the generated object. =head1 Intercepting MAIN calling (before 2018.10, v6.e) An older interface enabled one to intercept the calling to C
completely. This depended on the existence of a C subroutine that would be called if a C
subroutine was found in the mainline of a program. This interface was never documented. However, any programs using this undocumented interface will continue to function until C. From v6.d onward, the use of the undocumented API will cause a C message. Ecosystem modules can provide both the new and the old interface for compatibility with older versions of Perl 6 and Raku: if a newer Raku recognizes the new (documented) interface, it will use that. If there is no new interface subroutine available, but the old C interface is, then it will use the old interface. If a module developer decides to only offer a module for C or higher, then the support for the old interface can be removed from the module. =end pod ================================================ FILE: doc/Language/distributions/configuration-structure.rakudoc ================================================ =begin pod :kind("Language") :subkind("Modules") :category("tutorial") =TITLE Distributing modules: the configuration and structure =SUBTITLE How to structure and configure Raku modules for distribution =head1 Preparing the module For a module to work in any of the ecosystems, it needs to follow a certain structure. We strongly suggest that you use some of the L that are available. =head1 Quick Overview using C To create a skeleton, run the commands: =begin code :lang fez init MyNew::Module # Will create the following: # MyNew--Module/ # ├── lib # │   └── MyNew # │   └── Module.rakumod # ├── META6.json # └── t # └── 00-use.rakutest =end code If you need to add new modules, classes, resources, build-depends, or depends you may use the following (respectively, these resources will automatically be added to META6.json): =begin code :lang fez module My::New::Module fez module --class My::New::Module fez resource xyz fez depends --build Build::Dependency fez depends Runtime::Dependency =end code =head1 Full Explanation Even if you're intending to use fez or an equivalent (and you should), the following can be useful reading before releasing a module, so that, as you develop your module, you will be aware of the requirements and customs regarding how a module is structured. The META6.json file specifies the various metadata of your project and their uses; this has various sections that align with the filesystem of your module, so the following sections will step through the filesystem and the META6.json file in parallel; some sections belong only to one or the other, but many belong to both. The filesystem items will be referred to as C or C, and the META6.json sections will be referred to as a C or a C
. =head2 The module root directory and META6.json file The attributes in this file are analyzed by the L|https://github.com/jonathanstowe/META6> class. They are divided into optional, mandatory and I. Mandatory are the ones you need to insert into your file, and customary are those used by the current Raku ecosystem and possibly displayed on the module page if it's published, but you have no obligation to use it. Create a project directory named after your module. For example, if your module is C, then create a project directory named C. Make your project directory look like this: =begin code :lang Vortex-TotalPerspective/ ├── META6.json ├── LICENSE ├── README.md ├── lib │ └── Vortex │ └── TotalPerspective.rakumod └── bin │ └── vortex └── t └── basic.rakutest =end code Make your X|Reference,META6.json> file look something like this: =begin code :allow :lang { "name" : "Vortex::TotalPerspective", "description" : "Wonderful simulation to get some perspective.", "source-url" : "git://github.com/R/Vortex-TotalPerspective.git" "auth" : "github:SomeAuthor", "authors" : [ "R" ], "tags": [ "Vortex", "Total", "Perspective" ], "depends" : [ ], "build-depends" : [ ], "test-depends" : [ ], "license" : "Artistic-2.0", "version" : "0.0.1", "api" : "1", "raku" : "6.c", "provides" : { "Vortex::TotalPerspective" : "lib/Vortex/TotalPerspective.rakumod" }, "resources" : [ ], } =end code There are more fields described in the L design documents|https://github.com/Raku/old-design-docs/blob/master/S22-package-format.pod#META6.json>, but not all of these are implemented by existing package managers. Hence you should stick to the fields described in the above example block to ensure compatibility with existing package managers such as C. You can also check L, but bear in mind that some of them might use fields, such as C above, which are currently ignored. =head3 The C key The C key is compulsory, and C will fail if you do not include it. Even if you have created a META6.json file just to express the dependencies for a series of scripts, this section must be included. =head3 The C key The C field is also mandatory, and includes a short description of the module. =head3 The C key C indicates the URL of the repository where the module is developed; this is one of the customary modules if you are going to publish it in the module ecosystem. The current module ecosystem will link this URL from the project description. N field, which was used to indicate the kind of source control system, generally C, which can be used to download the module. However, this field is nowadays ignored by C and the rest of the tools.> See also the C section, below. =head3 The C and C sections The C section includes a list of all the module authors. In the case there is only one author, a single element list must be supplied. This field is optional. The C section identifies the author in GitHub or other repository hosting site, such as Bitbucket or GitLab. This field is I, since it's used to identify the author in the ecosystem, and opens the possibility of having modules with the same name and different authors. =head3 The C section The C section is also optional. It is used to describe the module in the Raku ecosystem. =head3 The C, C, and C sections The C, C, and C sections include different modules that are used in those phases of the of installation. All are optional, but if present must contain the required modules for those phases. These dependencies might optionally use L|/type/Version> specification strings; C will check for the presence and versions of these modules and install or upgrade them if needed. =for code :lang //... "depends": [ "URI", "File::Temp", "JSON::Fast", "Pod::To::BigPage:ver<0.5.0+>", "Pod::To::HTML:ver<0.6.1+>", "OO::Monitors", "File::Find", "Test::META" ], //... Additionally, C can be either an array as above or a hash that uses two keys, C and C, whose function should be self-descriptive, and which are used, for instance, L|https://github.com/niner/Inline-Python/blob/master/META6.json>: =for code :lang //... "depends" : { "build": { "requires": [ "Distribution::Builder::MakeFromJSON", { "from" : "bin", "name" : { "by-distro.name" : { "macosx" : "python2.7-config", "debian" : "python2.7-config", "" : "python2-config" } } } ] }, "runtime": { "requires": [ "python2.7:from" ] } }, // ... In general, the array form will be more than enough for most cases. =head3 The C file The C file is a L text file, which will later be automatically rendered as HTML by GitHub/GitLab for modules kept in those places, or by L website for modules accessible with L. =head3 The C file and key =item Regarding the C file, if you have no other preference, you might just use the same one that Rakudo Raku uses. Just copy/paste the raw form of L into your own C file. =item The license field in META6.json should be one of the standardized names listed here: L. In the case of the B license, which is what many of our ecosystem modules use, its identifier is C. Having standardized identifiers make it easy for humans and computers alike to know which license was actually used by looking at the metadata! =item If you can't find your license on C or you use your own license, you should put the license's name in the license field. For more details see L. =head2 The versioning keys =head3 The C key For choosing a version numbering scheme, try and use "major.minor.patch" (see L for further details). This will go into the C key of C. This field is optional, but used by installation to match against installed version, if one exists. =head3 The C key Optionally, you can set an C field. Incrementing this indicates that the interface provided by your module is not backwards compatible with a previous version. You can use it if you want to adhere to L. A best practice is to simply keep the C field to the same value as your major version number. A dependency can then depend on your module by including an C<:api> part, which will ensure backwards incompatible releases will not be pulled in. =head3 The C key Set C version to the minimum Raku version your module works with. This field is mandatory. Use C<6.c> if your module is valid for Christmas release and newer ones, use C<6.d> if it requires, at least the Diwali version. =head2 The C section and the C directory If your project contains other modules that help the main module do its job, they should go in your lib directory like so: =begin code :lang lib └── Vortex ├── TotalPerspective.rakumod └── TotalPerspective ├── FairyCake.rakumod └── Gargravarr.rakumod =end code In the C section, include all the namespaces provided by your distribution and that you wish to be installed; only module files that are explicitly included here will be installed and available with C or C in other programs. This field is mandatory. In the C object (object in the JSON sense), the key is the module name, the value is the path from the module root to the file in the lib/ directory. =head2 The C directory Programs and scripts that you need in the C<$PATH> for execution need to be included in the C directory; these will be copied to whatever directory your installed Rakudo distribution has allotted for executables; typically this will be C, a folder that should be available in C<$PATH>. I =head2 The C directory and section The C section is optional, but if present, should contain a list of the files in your C directory that you wish to be installed. These will be installed with hashed names alongside your library files. If you have any additional files (such as templates or a dynamic library) that you wish to have installed so you can access them at runtime, they should be placed in a C subdirectory of your project, e.g.: =begin code :lang resources └── templates └── default-template.mustache =end code The file must then be referenced in C (see below for more on C) so that the distribution path can be provided to the program. =begin code :lang { "name" : "Vortex::TotalPerspective", "provides" : { "Vortex::TotalPerspective" : "lib/Vortex/TotalPerspective.rakumod" }, "resources": [ "templates/default-template.mustache"] } =end code The additional file can then be accessed inside module code; see the section on the %?RESOURCES variable, below. =head3 X variable|Modules,%?DISTRIBUTION> The L|/syntax/$?DISTRIBUTION> variable is only populated within files listed in the C section (usually those in the C directory). If you want to use it outside that (i.e. in your tests), you'll need to provide a L|/type/Routine> that returns it. =head3 X variable|Modules,%?RESOURCES> Note the example here is returning a L|/type/Distribution::Resource> object. It should B be considered as a path to an object in the filesystem. =begin code my $template-text = %?RESOURCES.slurp; =end code B: Accessing these files via C<%?RESOURCES> is B getting their installed locations or an L|/type/IO> class: You are accessing a L|/type/Distribution::Resource>. object indexed on the name provided. It's important to be careful in how you use these to avoid embedding the filename at compile-time which might be different than the location the file is in at runtime. The L|/syntax/$?RESOURCES> variable is only populated within files listed in the C section (usually those in the C directory). If you want to use it outside that (i.e. in your tests), you'll need to provide a L|/type/Routine> that returns it. An example of how to use this might be: =begin code sub MyModule-resources(*@resources) is export(:tests) { for @resources -> $resource-filename { my $resource = %?RESOURCES{$resource-filename}; # Just some error-checking code if $resource !~~ Distribution::Resource { note "Could not find resource '$resource-filename' in distribution"; say qx{ls -laF ; ls -laF resources ; cat META6.json}; say "Resource is: " ~ $resource.raku; say "Resource keys are: " ~ %?RESOURCES.keys.raku; } } return %?RESOURCES; } =end code ...and then to use it in your code: =begin code :skip-test use TOP :tests :DEFAULT; # Note that the :tests here matches the "is export" above my $resource-name = 'templates/default-template.mustache'; my $resources = MyModule-resources($resource-name); my $resource = $resources{$resource-name}; my $file_handle = $resource.open(); =end code The above will produce quite a bit of debugging output if the resource isn't found (but will continue regardless). This can be handy when running in a remote location, such as a GitHub action. =head2 The C directory, and testing your module If you don't yet have any tests, you can leave out the C directory and C file for now. For more information on how to write tests (for now), you might have a look at how other modules use L|/type/Test>. The L module| https://github.com/jonathanstowe/Test-META/> can help you check the correctness of the META6.json file; this module will check for all the mandatory fields and that the type used for all of them is correct. If you want to test your module you can use the following command to install the module directly from the module folder you just created. =begin code :lang zef install ./your-module-folder =end code Note that doing so precompiles and installs your module. If you make changes to the source, you'll need to re-install the module. (See C L, C<-I> command line switch, or C environment variable, to include a path to your module source while developing it, so you don't have to install it at all). See also the C section, above. =head2 Documenting your modules To document your modules, use L markup inside them. Module documentation is most appreciated and will be especially important once the Raku module directory (or some other site) begins rendering Pod docs as HTML for easy browsing. If you have extra docs (in addition to the Pod docs in your module(s)), create a C directory for them. Follow the same folder structure as the C directory like so: =begin code :lang doc └── Vortex └── TotalPerspective.rakudoc =end code N directory. If you'd like a graphical logo to appear next to your module at the module directory, create a C directory and put into it a C file. At some point, you might also consider adding C, C, C, or other files.> =head2 Build hooks If your module requires extra processing during installation to fully integrate with and use non-Raku operating system resources, you may need to add a X|Reference,Build.rakumod> file (a "build hook") to the top-level directory. It will be used by the C installer as the first step in the installation process. See the README for C for a brief example. Also see various usage scenarios in existing ecosystem modules such as C itself. =head1 Documentation about Modules =item1 L =item2 L =item2 L =item1 L =item2 L Want to distribute your modules? =item1 L =item2 L (this page) =item2 L =item2 L =item2 L =end pod ================================================ FILE: doc/Language/distributions/introduction.rakudoc ================================================ =begin pod :kind("Language") :subkind("Modules") :category("tutorial") =TITLE Distributions: an introduction =SUBTITLE Distributions and how they work =head2 Terminology This is a point in the Raku journey where we need to get specific with some of the terminology, so here are some of the terms which will be used: =item1 B: A compilation unit, or compunit for short, is a piece of Raku code that is analyzed and compiled as a single unit. Typically, this comes from a source file on disk, but what's inside an EVAL also counts as such. =item1 B