## dist_zef-antononcube-JavaScript-Google-Charts.md
# JavaScript::Google::Charts

This repository has the Raku package for generation of
the [JavaScript Google Charts](https://developers.google.com/chart)
code for making plots and charts.

This package is intended to be used in Jupyter notebooks with the
[Raku kernel implemented by Brian Duggan](https://github.com/bduggan/raku-jupyter-kernel), [BD1], or
["Jupyter::Chatbook"](https://github.com/antononcube/Raku-Jupyter-Chatbook), [AAp4].
The commands of the package generate JavaScript code that produces (nice)
[Google Charts plots or charts](https://developers.google.com/chart/interactive/docs/gallery).

The package JavaScript graphs can be also included in HTML and Markdown documents.

One nice feature of Google Charts is that it allows the download of the plots and charts made with it.

---

## Mission statement

Make first class -- beautiful, tunable, and useful -- plots and charts with Raku using
concise specifications.

---

## Design and philosophy

Here is a list of guiding design principles:

* Google Charts gives a simple user interface, hence, we preserve and follow it as much as we can
* Make Google Charts' documentation completely applicable for the implemented functions
  * That documentation is very detailed and high quality.
  * *(Raku is just "conduit" to Google Charts.)*
* Facilitate the use of data simpler than that required by Google Charts
  * For example, just giving a list of numbers to a scatter plot should work.
* Facilitate the generation of both HTML code and (just) JavaScript code
* Keep the implementation simple
  * Do not to try to make an extensive interface to Google Charts or have complicated code snippets system.
    * *(Like the efforts in ["JavaScript::D3"](https://raku.land/zef:antononcube/JavaScript::D3).)*

---

## The chart types currently implemented

| Chart Type | Chart Type | Chart Type |
| --- | --- | --- |
| Annotated Timeline ▢ | Area Chart ✓ | Bar Chart ✓ |
| Bubble Chart ✓ | Calendar Chart ▢ | Candlestick Chart ▢ |
| Column Chart ✓ | Combo Chart ✓ | Gauge ✓ |
| Geo Chart ✓ | Histogram ✓ | Line Chart ✓ |
| Org Chart ▢ | Pie Chart ✓ | Sankey Diagram ✓ |
| Scatter Chart ✓ | Stepped Area Chart ✓ | Timeline ✓ |
| TreeMap ✓ | Waterfall Chart ▢ | Word Tree ✓ |

---

## How does it work?

Here is a diagram that summarizes the evaluation path from a Raku plot spec to a browser diagram:

```
graph TD
   Raku{{Raku}}
   IRaku{{"Raku<br>Jupyter kernel"}}
   Jupyter{{Jupyter}}
   JS{{JavaScript}}
   RakuInput[/Raku code input/]
   JSOutput[/JavaScript code output/]
   CellEval[Cell evaluation]
   JSResDisplay[JavaScript code result display]
   Jupyter -.-> |1|IRaku -.-> |2|Raku -.-> |3|JSOutput -.-> |4|Jupyter
   Jupyter -.-> |5|JS -.-> |6|JSResDisplay
   RakuInput ---> CellEval ---> Jupyter  ---> JSResDisplay

```

Here is the corresponding narration:

1. Enter Raku plot command in cell that starts with
   [the magic spec `%% js`](https://github.com/bduggan/raku-jupyter-kernel/issues/100#issuecomment-1349494169).

   * Like `js-google-charts-plot('Scatter', (^12)>>.rand)`.
2. Jupyter via the Raku kernel evaluates the Raku plot command.
3. The Raku plot command produces JavaScript code.
4. The Jupyter "lets" the web browser to evaluate the obtained JavaScript code.

   * Instead of web browser, say, Visual Studio Code can be used.

The evaluation loop spelled out above is possible because of the magics implementation in the Raku package
[Jupyter::Kernel](https://github.com/bduggan/raku-jupyter-kernel#features),
[BD1].

---

## Alternatives

### Raku packages

The Raku package
["JavaScript::D3"](https://raku.land/zef:antononcube/JavaScript::D3), [AAp1, AAv1],
provides a similar set of JavaScript computed plots and charts using the library [D3.js](https://d3js.org).

D3.js is (much more) of lower level library than Google Charts.

**Remark:** Google Charts is customizable, but its set of plots and charts is a streamlined
and relatively rigid compared to D3.js.

The Raku packages "Text::Plot", [AAp2] and "SVG::Plot", [MLp1],
provide similar functionalities and both can be used in Jupyter notebooks.
(Well, "Text::Plot" can be used anywhere.)

---

## Examples

### [Scatter plot](https://developers-dot-devsite-v2-prod.appspot.com/chart/interactive/docs/gallery/scatterchart)

```
use JavaScript::Google::Charts;

my @res = 120.rand xx 12;

js-google-charts('Scatter', @res, format => 'html', :png-button);

```

![](https://raw.githubusercontent.com/antononcube/Raku-JavaScript-Google-Charts/main/docs/Raku-JavaScript-Google-Charts-scatter-plot-demo.png)

### [Bubble chart](https://developers-dot-devsite-v2-prod.appspot.com/chart/interactive/docs/gallery/bubblechart)

```
my @res2 = [('A'..'Z').pick, 120.rand, 130.rand, <a b>.pick, 10.rand] xx 12;

@res2 = @res2.map({ <label x y group z>.Array Z=> $_.Array })».Hash;

js-google-charts('Bubble', @res2, column-names => <label x y group z>, format => 'html', :png-button, div-id => 'bubble');

```

![](https://raw.githubusercontent.com/antononcube/Raku-JavaScript-Google-Charts/main/docs/Raku-JavaScript-Google-Charts-bubble-chart-demo.png)

---

## References

### Articles

[OV1] Olivia Vane,
["D3 JavaScript visualisation in a Python Jupyter notebook"](https://livingwithmachines.ac.uk/d3-javascript-visualisation-in-a-python-jupyter-notebook),
(2020),
[livingwithmachines.ac.uk](https://livingwithmachines.ac.uk).

[SF1] Stefaan Lippens,
[Custom D3.js Visualization in a Jupyter Notebook](https://www.stefaanlippens.net/jupyter-custom-d3-visualization.html),
(2018),
[stefaanlippens.net](https://www.stefaanlippens.net).

### Packages

[AAp1] Anton Antonov,
[JavaScript::D3 Raku package](https://raku.land/zef:antononcube/Text::Plot),
(2022-2024),
[GitHub/antononcube](https://github.com/antononcube/Raku-JavaScript-D3).

[AAp1] Anton Antonov,
[Text::Plot Raku package](https://raku.land/zef:antononcube/Text::Plot),
(2022),
[GitHub/antononcube](https://github.com/antononcube/Raku-Text-Plot).

[AAp3] Anton Antonov,
[JavaScriptD3 Python package](https://github.com/antononcube/Python-packages/tree/main/JavaScriptD3),
(2022),
[Python-packages at GitHub/antononcube](https://github.com/antononcube/Python-packages).

[AAp4] Anton Antonov,
[Jupyter::Chatbook Raku package](https://github.com/antononcube/Raku-Jupyter-Chatbook),
(2023-2024),
[GitHub/antononcube](https://github.com/antononcube).

[BD1] Brian Duggan,
[Jupyter::Kernel Raku package](https://raku.land/cpan:BDUGGAN/Jupyter::Kernel),
(2017-2022),
[GitHub/bduggan](https://github.com/bduggan/raku-jupyter-kernel).

[MLp1] Moritz Lenz,
[SVG::Plot Raku package](https://github.com/moritz/svg-plot)
(2009-2018),
[GitHub/moritz](https://github.com/moritz/svg-plot).

### Videos

[AAv1] Anton Antonov,
["The Raku-ju hijack hack for D3.js"](https://www.youtube.com/watch?v=YIhx3FBWayo),
(2022),
[YouTube/@AAA4Prediction](https://www.youtube.com/@AAA4prediction).


## dist_zef-knarkhov-Node-Ethereum-Keccak256-Native.md
# Raku binding to original Keccak256-2011

Fast original Keccak256-2011 computation using NativeCall to C.

## License

Module `Node::Ethereum::Keccak256::Native` is free and opensource software, so you can redistribute it and/or modify it under the terms of the [The Artistic License 2.0](https://opensource.org/licenses/Artistic-2.0).

## Credits

1. <https://medium.com/@ConsenSys/are-you-really-using-sha-3-or-old-code-c5df31ad2b0>
2. <https://github.com/epicblockchain/whitepapers/blob/master/ETC/SHA3/SHA-3_Transition_Whitepaper_Impact_on_Ethereum_Classic_Mining_Hardware_and_Network_Security.md>
3. [keccak256.c](https://github.com/firefly/wallet/blob/master/source/libs/ethers/src/keccak256.c), [keccak256.h](https://github.com/firefly/wallet/blob/master/source/libs/ethers/src/keccak256.h)

## Author

Please contact me via [LinkedIn](https://www.linkedin.com/in/knarkhov/) or [Twitter](https://twitter.com/CondemnedCell). Your feedback is welcome at [narkhov.pro](https://narkhov.pro/contact-information.html).


## dist_zef-librasteve-PDF-Extract.md
[![](https://img.shields.io/badge/License-Artistic%202.0-0298c3.svg)](https://opensource.org/licenses/Artistic-2.0)

# raku PDF::Extract

Simple binding of the pdftotext command line utility

### Installation

1. `brew install poppler` (MacOS) or `sudo apt-get install poppler-utils` (ubuntu)
2. `zef install PDF::Extract`

To install poppler on other popular (geddit?) systems such as Nix or Windows, please see the installation instructions [here](https://poppler.freedesktop.org) and use your Nix package manager (e.g. `sudo aptitude` on Debian) or go [here](https://github.com/oschwartz10612/poppler-windows) for Windoze binaries (this module not yet tested on Windows).

### Synopsis

```
use PDF::Extract;

my $extract = Extract.new: file => '../resources/sample.pdf';

say $extract.text;
say $extract.html;
say $extract.xml;

say $extract.so;   #test for PDF headers
say $extract.info;
say $extract.info<CreationDate>;
...

### Copyright
copyright(c) 2023 Henley Cloud Consulting Ltd.

```


## dist_zef-raku-community-modules-SOAP-Client.md
[![Actions Status](https://github.com/raku-community-modules/SOAP-Client/actions/workflows/linux.yml/badge.svg)](https://github.com/raku-community-modules/SOAP-Client/actions) [![Actions Status](https://github.com/raku-community-modules/SOAP-Client/actions/workflows/macos.yml/badge.svg)](https://github.com/raku-community-modules/SOAP-Client/actions)

# NAME

SOAP::Client - Quick and dirty SOAP client

# SYNOPSIS

```
use SOAP::Client;

my $temp = SOAP::Client.new('https://www.w3schools.com/xml/tempconvert.asmx?WSDL');
say $temp.call('CelsiusToFahrenheit', Celsius => 100);

```

# DESCRIPTION

Warning: This library currently only supports the simplest of SOAP calls.

# AUTHOR

Andrew Egeler

# COPYRIGHT AND LICENSE

Copyright 2015- 2017 Andrew Egeler

Copyright 2018 - 2024 Raku Community

Licensed under the MIT license.


## dist_zef-raku-community-modules-MIME-Types.md
[![Actions Status](https://github.com/raku-community-modules/MIME-Types/actions/workflows/test.yml/badge.svg)](https://github.com/raku-community-modules/MIME-Types/actions)

# NAME

MIME::Types - determine mime type by file extension

# SYNOPSIS

```
use MIME::Types;

# Specify the mime file you wisg to use
# Or don't pass anything and get the default from the 'resources' directory
my $mime = MIME::Types.new("/etc/mime.types");

my $type = $mime.type('txt'); ## Returns: 'text/plain';
my @known_extensions = $mime.extensions('application/vnd.ms-excel');
# Returns: [ 'xls', 'xlb', 'xlt' ]

```

# DESCRIPTION

A Raku library that reads the `mime.types` file as used by many Linux distributions, and web servers, and returns an object that can be queried by either type or extension.

# EXAMPLE

An example mime.types is included in the resources/ directory, and is used by the tests in t/.

# AUTHOR

Timothy Totten

# COPYRIGHT AND LICENSE

Copyright 2011 - 2015 Timothy Totten

Copyright 2016 - 2022 Raku Community

This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.


## dist_zef-yguillemot-Qt-QtWidgets.md
# Qt::QtWidgets

A Raku module and native wrapper providing an interface to the Qt5 GUI.

## CONTENT

* 1. DESCRIPTION
* 2. LIMITATIONS
* 3. IMPLEMENTED FUNCTIONALITIES
* 4. DOCUMENTATION
  * 4.1 Classes and methods
  * 4.2 Instantiation
  * 4.3 Calling a method
  * 4.4 Enums
  * 4.5 Signals and slots
  * 4.6 Connect
  * 4.7 Disconnect
  * 4.8 Emit a QtSignal\_\_
  * 4.9 Subclassing a Qt object\_\_
* 5. EXAMPLES
  * 5.1 clock\_fixedSize.raku
  * 5.2 clock\_resizable.raku
  * 5.3 2deg\_eqn\_solver.raku\_\_
  * 5.4 sketch\_board.raku
  * 5.5 editor.raku
  * 5.6 sliders.raku
  * 5.7 sudoku\_grid.raku
  * 5.8 QMainWindow examples\_\_
  * 5.9 show\_mouse\_events.raku\_\_
  * 5.10 moving\_objects.raku\_\_
* 6. TOOL
* 7. PREREQUISITES
* 8. INSTALLATION
* 9. SOURCE CODE
* 10. AUTHOR
* 11. COPYRIGHT AND LICENSE

## 1. DESCRIPTION

This module defines Raku classes trying to mimic the Qt GUI C++ classes.
Qt objects are created and used through the Raku classes with native calls.

This is a work in progress and, currently, only a few classes and methods are
defined. Nevertheless, this module is already usable (see paragraph 5 *EXAMPLES*
below).

## 2. LIMITATIONS

Currently, this module is only working with Linux.

Although already usable, this interface is still limited to a few of the
most basic objects of the Qt GUI.

## 3. IMPLEMENTED FUNCTIONALITIES

The list of Qt classes and methods already ported is given in the
file doc/Qt/QtWidgets/Classes.html included in the distribution.

## 4. DOCUMENTATION

### 4.1 Classes and methods

The Raku API aims to be as close as possible to the C++ one.

Classes defined by the Raku API implement the Qt C++ classes and the Raku
methods have the same arguments as their related C++ methods.

Therefore the Qt C++ documentation should apply to its Raku interface.

This documentation is available here: <https://doc.qt.io/qt-5>.

The Raku API hides the C++ passing mode of the parameters.

Each class resides in its own compunit. So, before using a class, an **use**
instruction have to be provided for the related module.

For example, the following line:

```
use Qt::QtWidgets::QPushButton;

```

has to be issued before using any instruction related to a QPushButton.

The script **guessuse** is provided to help writing the needed **use**
instructions.
See the paragraph 6 *TOOL* below.

### 4.2 Instantiation

To instantiate a Qt class object from Raku, just use new with the same arguments
than the C++ constructor.

For example the C++ call of a QPushButton constructor is :

`QPushButton * button = new QPushButton("some text");`

the raku equivalent is:

`my $button = QPushButton.new("some text");`

### 4.3 Calling a method

Raku methods are called exactly as the original C++ method.

The C++ code :

`button->setDisable(true);`

is translated to Raku as :

`$button.setDisable(True);`

### 4.4 Enums

Similarly the C++ enums have their Raku equivalent :

the C++ code :

`QPen * pen = new QPen(Qt::DashLine);`

is translated to Raku as :

`my $pen = QPen.new(Qt::DashLine);`

### 4.5 Signals and slots

The signals and slots mechanism used by Qt allows unrelated objects to
communicate.

A C++ Qt object can have **slots** and/or **signals** if it inherits from the
C++ class **QObject**.

Similarly, a Raku object can have **QtSlots** and/or **QtSignals** if it
inherits from the Raku class **QtObject**.

The class **QtObject** and the related subroutines **connect** and
**disconnect** are exported from the compunit **Qt::QtWidgets** and have to
be imported with:

`use Qt::QtWidgets;`

A Raku Qt::QtWidgets **Qtslot** is an ordinary method defined with the trait
**is QtSlot**.

```
class MyClass is Qt::QtWidgetsObject {
   ... # Some code
   method mySlot(...) is QtSlot {
        ... # Some code
   }
   ... # Some code
}

```

As well, a Raku Qt::QtWidgets **Qtsignal** is a method defined with the trait
**is QtSignal**.
Its associated code will never be executed. So a stub should be used when
defining the method.

```
class MyClass2 is Qt::QtWidgetsObject {
   ... # Some code
   method mySignal(...) is QtSignal { ... }
   ... # Some code
}

```

### 4.6 Connect

The subroutine **connect** connects a QtSignal to a QtSlot (or to another
QtSignal).

`sub connect(QtObject $src, Str $signal, QtObject $dst, Str $slot)`

The names of signal and slot are passed to connect in strings.

The signal and slot must have compatible signatures.

> TODO: explanations needed

Example:

```
my $src = MyClass2.new;
my $dst = MyClass.new;
connect $src, "mySignal", $dst, "mySlot";

```

### 4.7 Disconnect

The subroutine **disconnect** does the opposite of **connect**.

`sub disconnect(QtObject $src, Str $signal, QtObject $dst, Str $slot)`

Example:

`disconnect $src, "mySignal", $dst, "mySlot";`

### 4.8 Emit a QtSignal

In C++ Qt, the keyword **emit** is used to emit a signal.

`emit mySignal(some_arg);`

In Raku Qt::QtWidgets, you only have to execute the method to emit the
associated **QtSignal**.

`self.mySignal(some_arg);`

### 4.9 Subclassing a Qt object

When programming with Qt and C++, some features can only be accessed
by overriding a Qt C++ virtual method.

A parallel mechanism is implemented in the Qt::QtWidgets module.

Subclassing a Qt object needs three steps:

* Define a Raku class inheriting the Qt class
* Call the **subClass** method of the parent class from the BUILD or TWEAK
  submethod of the new class.
* Override the virtual methods. The overriding method must have
  the same name and signature that the overrided method and doesn't need
  any specific syntax.

The first and third steps are obvious.

The second one is used to instantiate the C++
counterpart of the Raku class and to pass it the parameters its constructor
needs. In this second step, the parent class whose the subClass method is
called must be explicitely specified:
`self.ParentClass::subClass($param, ...);`

The following example shows how to subclass a QLabel and override its
QMousePressEvent method.

**Pure C++ version:**

```
#include <QtWidgets>

class MyLabel : public QLabel
{
public :
    MyLabel(const QString txt) : QLabel(txt) { }

    void mousePressEvent(QMouseEvent* event)
    {
        // Do something when the mouse is pressed on the label
    }
};

...

// Instantiation of the label in the main function :
MyLabel * label = new MyLabel("text on the label");

```

**Raku version:**

```
use Qt::QtWidgets;
use Qt::QtWidgets::QLabel;
use Qt::QtWidgets::QMouseEvent;

class MyLabel is QLabel
{
    has Str $.txt;

    submethod TWEAK { self.QLabel::subClass($!txt); }

    method mousePressEvent(QMouseEvent $event)
    {
        # Do something when the mouse is pressed on the label
    }
}

...

# Instantiation of the label in the main program :
my $label = MyLabel.new(txt => "text on the label");

```

## 5. EXAMPLES

They are available in the **examples** directory of the distribution.

### 5.1 clock\_fixedSize.raku

A very simple clock displaying the current time.

`raku examples/clock_fixedSize.raku`

### 5.2 clock\_resizable.raku

The same clock with a resizable window.

`raku examples/clock_resizable.raku`

### 5.3 2deg\_eqn\_solver.raku

A graphical interface to solve quadratic equations.

`raku examples/2deg_eqn_solver.raku`

### 5.4 sketch\_board.raku

A small example showing how to draw with the mouse and how to get file names
using QFileDialog methods.

`raku examples/sketch_board.raku`

### 5.5 editor.raku

A tiny text editor build with QTextEdit

`raku examples/editor.raku`

### 5.6 sliders.raku

A demonstration of QSlider, QDial, QCheckBox and QRadioButton widgets.

`raku examples/sliders.raku`

### 5.7 sudoku\_grids.raku

A QGrid layout usage example.

`raku examples/sudoku_grid.raku`

### 5.8 QMainWindow examples

editor\_mv.raku and sketch\_board\_mw.raku are modifications of the previous
editor and sketch\_board examples which show how to use main window menus
and status bar.

`raku examples/editor_mw.raku`

`raku examples/sketch_board_mw.raku`

### 5.9 show\_mouse\_events.raku

A small example which shows how to read mouse events.

`raku examples/show_mouse_events.raku`

### 5.10 moving\_objects.raku

An example showing how to create QGraphics objects and move them on
a QGraphicsScene.

`raku examples/moving_objects.raku`

### 5.11 show\_dialog.raku

An example of a popup dialog to enter some data

`raku examples/show_dialog.raku`

## 6. TOOL

Ideally, inserting "use Qt::QtWidgets;" at the beginning of a script should be
sufficient to import all the elements of the Qt::QtWidgets module.
Unfortunately it's not the case and seems not to be possible with the current
version of Raku (except by gathering all the classes of this API inside a single
huge source file).
Currently a specific **use** instruction is needed for each Qt class used in
a script.

That's why a tool named **guessuse** is provided to help the user to find what
**use** instructions a given script needs.

When called with the name of a raku file as argument, it writes out the
list of **use** instructions related to **Qt::QtWidgets** needed by this script.

For example, the command:

```
guessUse examples/sketch_board.raku

```

prints out the following lines:

```
use Qt::QtWidgets;
use Qt::QtWidgets::QAction;
use Qt::QtWidgets::QApplication;
use Qt::QtWidgets::QBrush;
use Qt::QtWidgets::QColor;
use Qt::QtWidgets::QFileDialog;
use Qt::QtWidgets::QHBoxLayout;
use Qt::QtWidgets::QMenu;
use Qt::QtWidgets::QMouseEvent;
use Qt::QtWidgets::QPaintEvent;
use Qt::QtWidgets::QPainter;
use Qt::QtWidgets::QPen;
use Qt::QtWidgets::QPushButton;
use Qt::QtWidgets::QVBoxLayout;
use Qt::QtWidgets::QWidget;
use Qt::QtWidgets::Qt;

```

Beware that this tool, when scanning a source file, doesn't make any difference
between code, comments and character strings and may very well print out "use"
instruction for some unneeded compunit.

**guessuse** resides in the the bin directory of the distribution and is
installed by **zef** along with the **Qt::QtWidgets** module.

## 7. PREREQUISITES

* Linux OS
* Qt5 development package
* C++ compiler

This module has been tested with **Qt 5.15.7** and **gcc 12.3.0**.
Many other versions should be usable as well.

## 8. INSTALLATION

`zef install Qt::QtWidgets`

Warning: Given the many classes and methods provided, the
installation may need several minutes.

Please, be patient.

## 9. SOURCE CODE

The source code is available here:
<https://github.com/yguillemot/Raku-Qt-QtWidgets.git>

Given the large number of Qt Classes and methods, manually writing such a
code is very tedious and error prone.
That's why this source and its associated documentation have been
automatically generated from the Qt C++ headers files coming with the Qt
development package.

The building tools are available here:
<https://github.com/yguillemot/RaQt_maker.git>

## 10. AUTHOR

Yves Guillemot
<[yc.guillemot@wanadoo.fr](mailto:yc.guillemot@wanadoo.fr)>

## 11. COPYRIGHT AND LICENSE

Copyright (C) 2021-2025 Yves Guillemot

This software is free: you can redistribute and/or modify it under
the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any
later version.

This software is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.


## dist_github-moznion-Text-LTSV.md
[![Build Status](https://travis-ci.org/moznion/p6-Text-LTSV.svg?branch=master)](https://travis-ci.org/moznion/p6-Text-LTSV)

# NAME

Text::LTSV - LTSV (Labeled Tab Separated Value) toolkit

# SYNOPSIS

```
use Text::LTSV;

my $ltsv = Text::LTSV.new;

## one line
$ltsv.stringify(Array[Pair].new(
    'foo'  => 'bar',
    'buz'  => 'qux',
    'john' => 'paul',
)); # => "foo:bar\tbuz:qux\tjohn:paul"

## multiple lines
$ltsv.stringify(Array[Array[Pair]].new(
    Array[Pair].new('foo' => 'bar'),
    Array[Pair].new('buz' => 'qux'),
)); # => "foo:bar\nbuz:qux"

## With parser
use Text::LTSV::Parser;
my $parser = Text::LTSV::Parser.new;
$ltsv.stringify($parser.parse-line("foo:bar\tbuz:qux\tjohn:paul\n")); # => "foo:bar\tbuz:qux\tjohn:paul"
$ltsv.stringify($parser.parse-text("foo:bar\tbuz:qux\njohn:paul\tgeorge:ringo\n")); # => "foo:bar\tbuz:qux\njohn:paul\tgeorge:ringo"

```

# DESCRIPTION

Text::LTSV is a builder for [LTSV (Labeled Tab Separated Values)](http://ltsv.org/).

# METHODS

## `multi method stringify(Pair @key-values) returns Str`

Stringify LTSV as one line.

## `multi method stringify(Array[Pair] @multi-key-values) returns Str`

Stringify LTSV as multiple lines. You can specify new line character by `$.nl`. Default `$.nl` is `"\n"`;

# SEE ALSO

* Text::LTSV::Parser

# AUTHOR

moznion [moznion@gmail.com](mailto:moznion@gmail.com)

# COPYRIGHT AND LICENSE

Copyright 2015 moznion

This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.


## uniname.md
uniname

Combined from primary sources listed below.

# [In Cool](#___top "go to top of document")[§](#(Cool)_routine_uniname "direct link")

See primary documentation
[in context](/type/Cool#routine_uniname)
for **routine uniname**.

```raku
sub uniname(Str(Cool) --> Str)
method uniname(--> Str)
```

Interprets the invocant or first argument as a [`Str`](/type/Str), and returns the Unicode codepoint name of the first codepoint of the first character. See [uninames](/routine/uninames) for a routine that works with multiple codepoints, and [uniparse](/routine/uniparse) for the opposite direction.

```raku
# Camelia in Unicode
say ‘»ö«’.uniname;
# OUTPUT: «RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK␤»
say "Ḍ̇".uniname; # Note, doesn't show "COMBINING DOT ABOVE"
# OUTPUT: «LATIN CAPITAL LETTER D WITH DOT BELOW␤»

# Find the char with the longest Unicode name.
say (0..0x1FFFF).sort(*.uniname.chars)[*-1].chr.uniname;
# OUTPUT: «BOX DRAWINGS LIGHT DIAGONAL UPPER CENTRE TO MIDDLE RIGHT AND MIDDLE LEFT TO LOWER CENTRE␤»
```

Available as of the 2021.04 Rakudo compiler release.


## dist_zef-jjmerelo-Array-Shaped-Console.md
# NAME [Test-install distro](https://github.com/JJ/raku-array-shaped-console/actions/workflows/test.yaml)

Array::Shaped::Console - Renders 2d arrays to a console using block symbols

# SYNOPSIS

```
use Array::Shaped::Console;

my @array[2;2] = (-1,1;1,-1);
# Prints "□▧\n▧□\n"  using default "grayscale" console symbols array
printed(@array).say;

# Prints "□■\n■□\n" with infinity having a special default symbol.
@array = (-1,Inf;Inf,-1);
say printed( @array );

```

# DESCRIPTION

Array::Shaped::Console includes functions and ranges to easily render
numeric 2d arrays to the console, using the same shape of the array,
and adapting the array range to the number of symbols that are also
handled in the function.

These arrays, as well as the "infinity" symbol, are predefined;

```
@grayscale = chr(0x25A1)..chr(0x25A9);
@dashes = '–'..'―';
@lines = '⎽'...'⎺';
@shades = '░'..'▓';
@lower = '▁'..'█';
@left = '▏'...'█';
@squares = <▪◾◼>;
@chars = ".:-=+*#%@".comb;
$inf-char = chr(0x25A0);

```

@grayscale is used by default.

## method printed( @array, @shapes = @grayscale, $non-symbol = $inf-char)

Returns a string that collates, using the array shape, in a single string that separates rows by a carriage return.

# AUTHOR

JJ Merelo [jjmerelo@gmail.com](mailto:jjmerelo@gmail.com)

# COPYRIGHT AND LICENSE

Copyright 2020-2022 JJ Merelo

This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.


## dist_zef-zero-overhead-App-Workflows-Github.md
| last push | [Linux Status](https://github.com/zero-overhead/App-Workflows-Github/actions) | [MacOS Status](https://github.com/zero-overhead/App-Workflows-Github/actions) | [Windows Status](https://github.com/zero-overhead/App-Workflows-Github/actions) |
| --- | --- | --- | --- |
| scheduled check | [Linux Status](https://github.com/zero-overhead/App-Workflows-Github/actions) | [MacOS Status](https://github.com/zero-overhead/App-Workflows-Github/actions) | [Windows Status](https://github.com/zero-overhead/App-Workflows-Github/actions) |

# NAME

App::Workflows::Github - a CI/CD workflow collection for Raku Module developers.

# SYNOPSIS

```
zef install App::Workflows::Github
cd your-module-directory
create-workflows-4-github

```

# DESCRIPTION

[![last version](https://raku.land/zef:zero-overhead/App::Workflows::Github/badges/version)](https://raku.land/zef:zero-overhead/App::Workflows::Github/badges) [![downloads](https://raku.land/zef:zero-overhead/App::Workflows::Github/badges/downloads)](https://raku.land/zef:zero-overhead/App::Workflows::Github/badges)

App::Workflows::Github is collecting Github workflows for testing your [Module](https://raku.land) on Linux, MacOS and Windows.

Scheduled workflows only run automatically on github if the .yml files are pushed to the default branch - usually 'main'.

## Microsoft Windows

If you are on [Windows](https://learn.microsoft.com/en-us/linux/install) and can not use [WSL](https://learn.microsoft.com/en-us/windows/wsl/): consider switching off the [maximum-path-length-limitation](https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=powershell) in case of failed tests during installation.

```
New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" -Name "LongPathsEnabled" -Value 1 -PropertyType DWORD -Force

```

You might get away with temporarily setting TEMP to a short path.

```
set TEMP=D:\T

mkdir -Force %TEMP%
set TMP=%TEMP%
set ZEF_CONFIG_TEMPDIR=%TEMP%

```

## Installation

Linux/MacOS/Windows install module command:

```
zef install App::Workflows::Github

```

Finally execute the following commands:

```
cd your-module-directory
create-workflows-4-github

```

This will create or overwrite the following files:

```
your-module-directory/.github/workflows/runner.yml
your-module-directory/.github/workflows/dispatch.yml
your-module-directory/.github/workflows/Linux.yml
your-module-directory/.github/workflows/MacOS.yml
your-module-directory/.github/workflows/Windows.yml
your-module-directory/run-tests.raku

```

Then do the usual three git steps to push the changes to github.

```
git add .github/workflows/
git add run-tests.raku

git commit -m"adding github workflows"

git push

```

## Workflow Dispatch

To [dispatch a workflow run](https://cli.github.com/manual/gh_workflow_run) using [gh](https://cli.github.com/manual/) CLI use e.g.

```
cd your-module-directory

echo '{"verbosity":"debug", "os":"windows", "ad_hoc_pre_command":"pwd", "ad_hoc_post_command":"ls -alsh", "os_version":"2019", "raku_version":"2023.02", "run_prove6":"true", "install_module":"true", "run_tests_script":"true", "skip_deps_tests":"false"}' > run_parameters.json
cat run_parameters.json | gh workflow run 'dispatch' --ref branch-to-run-on --json

```

For 'os' you can choose any of 'ubuntu|macos|windows'. For 'os\_version' check [supported-runners-and-hardware-resources](https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources). For available 'raku\_version' check [here](https://www.rakudo.org/downloads/rakudo).

![screenshot of dispatch menu](https://github.com/zero-overhead/App-Workflows-Github/blob/main/resources/dispatch-screenshot.png?raw=true)

Open <https://github.com/your-name/your-module/actions> to check the workflow results or dispatch a run via browser.

# AUTHOR

rcmlz [rcmlz@github.com](mailto:rcmlz@github.com)

# COPYRIGHT AND LICENSE

Copyright 2023 rcmlz

This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.


## dist_cpan-ANTONOV-Data-Summarizers.md
# Raku Data::Summarizers

[![Build Status](https://app.travis-ci.com/antononcube/Raku-Data-Summarizers.svg?branch=main)](https://app.travis-ci.com/github/antononcube/Raku-Data-Summarizers)
[![](https://img.shields.io/badge/License-Artistic%202.0-0298c3.svg)](https://opensource.org/licenses/Artistic-2.0)

This Raku package has data summarizing functions for different data structures that are
coercible to full arrays.

The supported data structures (so far) are:

* 1D Arrays
* 1D Lists
* Positional-of-hashes
* Positional-of-arrays

---

## Usage examples

### Setup

Here we load the Raku modules
[`Data::Generators`](https://modules.raku.org/dist/Data::Generators:cpan:ANTONOV),
[`Data::Reshapers`](https://modules.raku.org/dist/Data::Reshapers:cpan:ANTONOV)
and this module,
[`Data::Summarizers`](https://github.com/antononcube/Raku-Data-Summarizers):

```
use Data::Generators;
use Data::Reshapers;
use Data::Summarizers;

```

```
# (Any)

```

### Summarize vectors

Here we generate a numerical vector, place some NaN's or Whatever's in it:

```
my @vec = [^1001].roll(12);
@vec = @vec.append( [NaN, Whatever, Nil]);
@vec .= pick(@vec.elems);
@vec

```

```
# [740 311 434 300 (Whatever) 192 705 202 576 561 544 NaN (Any) 744 133]

```

Here we summarize the vector generated above:

```
records-summary(@vec)

```

```
# O────────────────────────────────────O
# │ numerical                          │
# O────────────────────────────────────O
# │ 1st-Qu                    => 251   │
# │ Max                       => 744   │
# │ Median                    => 489   │
# │ (Any-Nan-Nil-or-Whatever) => 3     │
# │ Mean                      => 453.5 │
# │ Min                       => 133   │
# │ 3rd-Qu                    => 640.5 │
# O────────────────────────────────────O

```

### Summarize tabular datasets

Here we generate a random tabular dataset with 16 rows and 3 columns and display it:

```
srand(32);
my $tbl = random-tabular-dataset(16,
                                 <Pet Ref Code>,
                                 generators=>[random-pet-name(4), -> $n { ((^20).rand xx $n).List }, random-string(6)]);
to-pretty-table($tbl)

```

```
# O────────────────O───────────O──────────O
# │      Code      │    Ref    │   Pet    │
# O────────────────O───────────O──────────O
# │ A2Ue69EWAMtJCi │  0.050176 │ Guinness │
# │ KNwmt0QmoqABwR │  0.731900 │ Truffle  │
# │ A2Ue69EWAMtJCi │  0.739763 │  Jumba   │
# │       aY       │  7.342107 │ Guinness │
# │ xgZjtSP6VrKbH  │ 19.868591 │  Jumba   │
# │    20CO9FGD    │ 12.956172 │  Jumba   │
# │    20CO9FGD    │ 15.854088 │ Guinness │
# │ A2Ue69EWAMtJCi │  4.774780 │ Guinness │
# │ A2Ue69EWAMtJCi │ 18.729798 │ Guinness │
# │ xgZjtSP6VrKbH  │ 13.383997 │ Guinness │
# │       aY       │  9.837488 │  Jumba   │
# │    20CO9FGD    │  2.912506 │ Truffle  │
# │ xgZjtSP6VrKbH  │ 11.782221 │ Truffle  │
# │ KNwmt0QmoqABwR │  9.825102 │ Truffle  │
# │ xgZjtSP6VrKbH  │ 16.277717 │  Jumba   │
# │ CQmrQcQ4YkXvaD │  1.740695 │ Guinness │
# O────────────────O───────────O──────────O

```

**Remark:** The values of the column "Pet" is sampled from a set of four pet names, and the values of the column
and "Code" is sampled from a set of 6 strings.

Here we summarize the tabular dataset generated above:

```
records-summary($tbl)

```

```
# O───────────────O──────────────────────────────O─────────────────────O
# │ Pet           │ Ref                          │ Code                │
# O───────────────O──────────────────────────────O─────────────────────O
# │ Guinness => 7 │ Min    => 0.0501758995572299 │ xgZjtSP6VrKbH  => 4 │
# │ Jumba    => 5 │ 1st-Qu => 2.3266005718178704 │ A2Ue69EWAMtJCi => 4 │
# │ Truffle  => 4 │ Mean   => 9.175443804770861  │ 20CO9FGD       => 3 │
# │               │ Median => 9.831294839627123  │ KNwmt0QmoqABwR => 2 │
# │               │ 3rd-Qu => 14.619042446877677 │ aY             => 2 │
# │               │ Max    => 19.868590809216744 │ CQmrQcQ4YkXvaD => 1 │
# O───────────────O──────────────────────────────O─────────────────────O

```

### Summarize collections of tabular datasets

Here is a hash of tabular datasets:

```
my %group = group-by($tbl, 'Pet');

%group.pairs.map({ say("{$_.key} =>"); say to-pretty-table($_.value) });

```

```
# Guinness =>
# O────────────────O───────────O──────────O
# │      Code      │    Ref    │   Pet    │
# O────────────────O───────────O──────────O
# │ A2Ue69EWAMtJCi │  0.050176 │ Guinness │
# │       aY       │  7.342107 │ Guinness │
# │    20CO9FGD    │ 15.854088 │ Guinness │
# │ A2Ue69EWAMtJCi │  4.774780 │ Guinness │
# │ A2Ue69EWAMtJCi │ 18.729798 │ Guinness │
# │ xgZjtSP6VrKbH  │ 13.383997 │ Guinness │
# │ CQmrQcQ4YkXvaD │  1.740695 │ Guinness │
# O────────────────O───────────O──────────O
# Truffle =>
# O─────────O───────────O────────────────O
# │   Pet   │    Ref    │      Code      │
# O─────────O───────────O────────────────O
# │ Truffle │  0.731900 │ KNwmt0QmoqABwR │
# │ Truffle │  2.912506 │    20CO9FGD    │
# │ Truffle │ 11.782221 │ xgZjtSP6VrKbH  │
# │ Truffle │  9.825102 │ KNwmt0QmoqABwR │
# O─────────O───────────O────────────────O
# Jumba =>
# O───────────O────────────────O───────O
# │    Ref    │      Code      │  Pet  │
# O───────────O────────────────O───────O
# │  0.739763 │ A2Ue69EWAMtJCi │ Jumba │
# │ 19.868591 │ xgZjtSP6VrKbH  │ Jumba │
# │ 12.956172 │    20CO9FGD    │ Jumba │
# │  9.837488 │       aY       │ Jumba │
# │ 16.277717 │ xgZjtSP6VrKbH  │ Jumba │
# O───────────O────────────────O───────O

```

Here is the summary of that collection of datasets:

```
records-summary(%group)

```

```
# summary of Guinness =>
# O──────────────────────────────O─────────────────────O───────────────O
# │ Ref                          │ Code                │ Pet           │
# O──────────────────────────────O─────────────────────O───────────────O
# │ Min    => 0.0501758995572299 │ A2Ue69EWAMtJCi => 3 │ Guinness => 7 │
# │ 1st-Qu => 1.7406953436440742 │ CQmrQcQ4YkXvaD => 1 │               │
# │ Mean   => 8.839377375678543  │ 20CO9FGD       => 1 │               │
# │ Median => 7.34210706081909   │ xgZjtSP6VrKbH  => 1 │               │
# │ 3rd-Qu => 15.854088005472917 │ aY             => 1 │               │
# │ Max    => 18.72979803423013  │                     │               │
# O──────────────────────────────O─────────────────────O───────────────O
# summary of Truffle =>
# O──────────────O──────────────────────────────O─────────────────────O
# │ Pet          │ Ref                          │ Code                │
# O──────────────O──────────────────────────────O─────────────────────O
# │ Truffle => 4 │ Min    => 0.7318998724597869 │ KNwmt0QmoqABwR => 2 │
# │              │ 1st-Qu => 1.822202836225727  │ 20CO9FGD       => 1 │
# │              │ Mean   => 6.312932174017679  │ xgZjtSP6VrKbH  => 1 │
# │              │ Median => 6.368803873269801  │                     │
# │              │ 3rd-Qu => 10.803661511809633 │                     │
# │              │ Max    => 11.782221077071329 │                     │
# O──────────────O──────────────────────────────O─────────────────────O
# summary of Jumba =>
# O──────────────────────────────O────────────O─────────────────────O
# │ Ref                          │ Pet        │ Code                │
# O──────────────────────────────O────────────O─────────────────────O
# │ Min    => 0.7397628145038704 │ Jumba => 5 │ xgZjtSP6VrKbH  => 2 │
# │ 1st-Qu => 5.28862527360509   │            │ 20CO9FGD       => 1 │
# │ Mean   => 11.935946110102654 │            │ A2Ue69EWAMtJCi => 1 │
# │ Median => 12.956171789492936 │            │ aY             => 1 │
# │ 3rd-Qu => 18.073154106905072 │            │                     │
# │ Max    => 19.868590809216744 │            │                     │
# O──────────────────────────────O────────────O─────────────────────O

```

### Skim

*TBD...*

---

## TODO

* User specified `NA` marker
* Tabular dataset summarization tests
* Skimmer
* Peek-er

---

## References

### Functions, repositories

[AAf1] Anton Antonov,
[RecordsSummary](https://resources.wolframcloud.com/FunctionRepository/resources/RecordsSummary),
(2019),
[Wolfram Function Repository](https://resources.wolframcloud.com/FunctionRepository).


## dist_cpan-MANWAR-Games-Maze.md
[![Actions Status](https://github.com/manwar/Games-Maze/workflows/test/badge.svg)](https://github.com/manwar/Games-Maze/actions)

# NAME

Games::Maze - Maze generator.

# SYNOPSIS

```
use Games::Maze;

my $maze = Games::Maze.new( :height(10), :width(10) );
$maze.make.render.say;

```

# DESCRIPTION

Games::Maze is the implementation of the work that I contributed to the [Raku Advent Calendar 2019](https://raku-advent.blog/2019/12/17/maze-maker-for-fun/).

It was my first ever participation to the Advent Calendar for Raku. I used the opportunity to explore the language.

I was meant to package it as library and release it long time ago but for some reason it didn't work out.

I have finally managed to find the time to bundle the package.

# AUTHOR

Mohammad S Anwar [mohammad.anwar@yahoo.com](mailto:mohammad.anwar@yahoo.com)

# COPYRIGHT AND LICENSE

Copyright 2020 Mohammad S Anwar

This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.


## dist_cpan-TYIL-Hash-Merge.md
### sub merge-hashes

```
sub merge-hashes(
    *@hashes
) returns Hash

```

Merge any number of Hashes together.

## class \*@hashes

Any number of Hashes to merge together.

### sub merge-hash

```
sub merge-hash(
    %first,
    %second,
    Bool:D :$deep = Bool::True,
    Bool:D :$positional-append = Bool::True
) returns Hash

```

Merge two hashes together.

## class %first

The original Hash to merge the second Hash into.

## class %second

The second hash, which will be merged into the first Hash.

## class Bool:D :$deep = Bool::True

Boolean to set whether Associative objects should be merged on their own. When set to False, Associative objects in %second will overwrite those from %first.

## class Bool:D :$positional-append = Bool::True

Boolean to set whether Positional objects should be appended. When set to False, Positional objects in %second will overwrite those from %first.


## dist_zef-raku-community-modules-Text-Caesar.md
[![Actions Status](https://github.com/raku-community-modules/Text-Caesar/actions/workflows/linux.yml/badge.svg)](https://github.com/raku-community-modules/Text-Caesar/actions) [![Actions Status](https://github.com/raku-community-modules/Text-Caesar/actions/workflows/macos.yml/badge.svg)](https://github.com/raku-community-modules/Text-Caesar/actions) [![Actions Status](https://github.com/raku-community-modules/Text-Caesar/actions/workflows/windows.yml/badge.svg)](https://github.com/raku-community-modules/Text-Caesar/actions)

# NAME

Text::Caesar - Encrypt / Decrypt using a Caesar cipher

# SYNOPSIS

```
use Text::Caesar;

my $message = Message.new(
  key  => 3,
  text => "I am a secret message"
);
my $secret = Secret.new(
  key  => 3,
  text => $message.encrypt();
);
say $message.encrypt;
say $secret.decrypt;

```

# DESCRIPTION

This module allows you to use 4 functions.

You can encrypt a message:

```
use Text::Caesar;

my Str $secret = "I'm a secret message.";
my Str $message = encrypt(3, $secret);
say $message;

```

You can decrypt a message :

```
my Str $secret = 'LPDVHFUHWPHVVDJH'
my Str $message = decrypt(3, $secret);
say $message;

```

You can encrypt (or decrypt) a file:

```
encrypt-from-file($key, $origin, $destination)

```

This code will encrypt `$origin`'s text into the `$destination` file.

You can also use objects:

```
my $message = Message.new(
  key  => 3,
  text => "I am a secret message"
);
say $message.encrypt;

```

```
my $secret = Secret.new(
  key  => 3,
  text => $message.encrypt;
);
say $secret.decrypt;

```

# AUTHOR

Emeric Fischer

# COPYRIGHT AND LICENSE

Copyright 2016 - 2017 Emeric Fischer

Copyright 2024 Raku Community

This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.


## initialization.md
class X::Role::Initialization

Error due to passing an initialization value to an ineligible role

```raku
class X::Role::Initialization is Exception { }
```

Thrown when the `SomeRole($init)` syntax is used, but SomeRole does not have exactly one public attribute.

For example:

```raku
role R { }; "D2" but R(2)
CATCH { default { put .^name, ': ', .Str } }
# OUTPUT: «X::Role::Initialization: Can only supply an initialization value for a role if it has a single public attribute, but this is not the case for 'R'␤»

```

# [Methods](#class_X::Role::Initialization "go to top of document")[§](#Methods "direct link")

## [method role](#class_X::Role::Initialization "go to top of document")[§](#method_role "direct link")

```raku
method role()
```

Returns the role that caused the error.


## dist_zef-jonathanstowe-Monitor-Monit.md
# Monitor::Monit

Provide an interface to the monit monitoring daemon

![Build Status](https://github.com/jonathanstowe/Monitor-Monit/workflows/CI/badge.svg)

## Synopsis

```

use Monitor::Monit;

# use default settings
my $mon = Monitor::Monit.new;

for $mon.service -> $service {
	say $service.name, " is ", $service.status-name;
}

```

## Description

Monit is a lightweight, relatively simple and widely used system
and application monitoring service.

This provides a mechanism to interact with its http api.

## Installation

In order for this to be useful you will need to have 'monit' installed,
most Linux distributions provide it as a package.

If you set the enviromment variable `MONIT_TEST_LIVE` the tests will
attempt to connect to a monit daemon on the local host with the default
port and credentials, if there is no connection then the online tests
will be skipped.

By default the monit daemon will be configured to only listen for local
connections on the loopback interface, if you wish to work with a remote
monit daemon you may need to alter the monit configuration accordingly.

You can provide the details for the running monit daemon you want to test
with by setting some environment variables before running the tests:

* `MONIT_TEST_HOST` - the hostname on which the daemon is running
* `MONIT_TEST_PORT` - the port the daemon is using (default 2812)
* `MONIT_TEST_USER` - the username to authenticate (default `admin`)
* `MONIT_TEST_PASS` - the password to authenticate (default `monit`)

Additionally, if the environment variable `MONIT_TEST_CONTROL` is set to
a true value, the tests will attempt to control the services, you probably don't
want to do this on a production system.

Assuming you have a working Rakudo installation then you should be able to install with `zef` :

zef install Monitor::Monit

## Support

I've only tested this against my particular configuration of monit so it is
entirely possible that I have missed something that is important to you,
please feel to make suggestions at <https://github.com/jonathanstowe/Monitor-Monit/issues>

It is possible that it may not work properly with certain older versions of
monit though I can't pinpoint which versions and it's difficult to test so
any help with that would be appreciated.

## Copyright and Licence

This is free software.

Please see the <LICENCE> file in this directory.

© Jonathan Stowe 2016 - 2021


## dist_zef-antononcube-FunctionalParsers.md
# FunctionalParsers Raku package

## Introduction

This Raku package provides a (monadic) system of Functional Parsers (FPs).

The package design and implementation follow closely the article "Functional parsers" by Jeroen Fokker, [JF1].
That article can be used as *both* a theoretical- and a practical guide to FPs.

### Two in one

The package provides both FPs and
[Extended Backus-Naur Form (EBNF)](https://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_form)
parsers and interpreters.
The reasons for including the EBNF functionalities are:

* EBNF parsing is discussed in [JF1]
* EBNF parsers and interpreters are very good examples of FPs application

### Previous work

#### Anton Antonov

* FPs packages implementations in Lua, Mathematica, and R.
  See [these blog posts](https://mathematicaforprediction.wordpress.com/?s=functional+parsers) and [AAp1, AAp2].

**Remark:** In this document Mathematica and Wolfram Language (WL) are used as synonyms.

#### Jeroen Fokker

* "Functional parsers" article using Haskell, [JF1].

#### Wim Vanderbauwhede

* Interesting and insightful blog post ["List-based parser combinators in Haskell and Raku"](https://limited.systems/articles/list-based-parser-combinators/).

  * The corresponding Raku code repository [WVp1] is not (fully) productized.
* Perl package ["Parser::Combinators"](https://github.com/wimvanderbauwhede/Perl-Parser-Combinators), [WVp2].

---

## Installation

From [Zef ecosystem](https://raku.land):

```
zef install FunctionalParsers;

```

From GitHub:

```
zef install https://github.com/antononcube/Raku-FunctionalParsers.git

```

---

## Motivation

Here is a list of motivations for implementing this package:

1. Word-based backtracking
2. Elevate the "tyranny" of Raku grammars
3. Easier transfer of Raku grammars into other languages
4. Monadic parser construction
5. Quick, elegant implementation

### Word-based backtracking

I had certain assumptions about certain slow parsing with Raku using regexes.
For example, is not that easy to specify backtracking over sequences of words (instead of characters) in grammars.
To check my assumptions I wrote the basic eight FPs (which is quick to do.) After my experiments,
I could not help myself making a complete package.

### Elevate the "tyranny" of Raku grammars and transferring to other languages

The "first class citizen" treatment of grammars is one of the most important and unique features of Raku.
It is one of the reasons why I treat Raku as a "secret weapon."

But that uniqueness does not necessarily facilitate easy utilization or transfer in large software systems.
FPs, on the other hand, are implemented in almost every programming language.
Hence, making or translating grammars with- or to FPs would provide greater knowledge transfer and integration
of Raku-derived solutions.

### Monadic parser construction

Having a monadic way of building parsers or grammars is very appealing. (To some people.)
Raku's operator making abilities can be nicely utilized.

**Remark:** The monad of FPs produces Abstract Syntax Trees (ASTs) that are simple lists.
I prefer that instead of using specially defined types (as, say, in [WV1, WVp1].) That probably,
comes from too much usage of LISP-family programming languages. (Like Mathematica and R.)

### Quick, elegant implementation

The Raku code implementing FPs was quick to write and looks concise and elegant.

(To me at least. I would not be surprised if that code can be simplified further.)

---

## Naming considerations

### Package name

I considered names like "Parser::Combinator", "Parser::Functional", etc. Of course, I looked up
names of similar packages.

Ultimately, I decided to use "FunctionalParsers" because:

* Descriptive name that corresponds to the title of the article by Jeroen Fokker, [JF1].
* The package has not only parser combinators, but also parser transformers and modifiers.
* The connections with corresponding packages in other languages are going to be more obvious.
  * For example, I have used the name "FunctionalParsers" for similar packages in other programming languages (Lua, R, WL.)

### Actions vs Contexts

I considered to name the directory with EBNF interpreters "Context" or "Contexts", but
since "Actions" is used a lot I chose that name.

**Remark:** In [JF1] the term "contexts" is used.

---

## Examples

Make a parser for a family of (two) simple sentences:

```
use FunctionalParsers :ALL;

my &p1 = (symbol('numerical') «|» symbol('symbolic')) «&» symbol('integration');

```

```
# -> @x { #`(Block|6352212853176) ... }

```

Here we parse sentences adhering to the grammar of the defined parser:

```
.say for ("numerical integration", "symbolic integration")>>.words.map({ $_ => &p1($_)});

```

```
# (numerical integration) => ((() (numerical integration)))
# (symbolic integration) => ((() (symbolic integration)))

```

These sentences are not parsed:

```
("numeric integration", "symbolic summation")>>.words.map({ $_ => &p1($_)});

```

```
# ((numeric integration) => () (symbolic summation) => ())

```

---

## Infix operators

Several notation alternatives are considered for the infix operations corresponding to
the different combinators and transformers. Here is a table with different notation styles:

| Description | set | double | n-ary |
| --- | --- | --- | --- |
| sequential combination | (&) | «&» | ⨂ |
| left sequential pick | (<&) | «& | ◁ |
| right sequential pick | (&>) | &» | ▷ |
| alternatives combination | (⎸) | «⎸» | ⨁ |
| function application | (^) | «o | ⨀ |

Consider the parsers:

```
my &p1 = apply( {1}, symbol('one'));
my &p2 = apply( {2}, symbol('two'));
my &p3 = apply( {3}, symbol('three'));
my &p4 = apply( {4}, symbol('four'));
my &pM = symbol('million');
my &pTh = symbol('things');

```

```
# -> @x { #`(Block|6352245759584) ... }

```

Here are spec examples for each style of infix operators:

```
# set
my &p = (&p1 (|) &p2 (|) &p3 (|) &p4) (&) (&pM (^) {10**6}) (&) &pTh;
&p('three million things'.words.List).head.tail;

```

```
# (3 (1000000 things))

```

```
# double
(&p1 «|» &p2 «|» &p3 «|» &p4) «&» &pM «o {10**6} «&» &pTh;

```

```
# n-ary
(&p1 ⨁ &p2 ⨁ &p3 ⨁ &p4) ⨂ {10**6} ⨀ &pM ⨂ &pTh

```

**Remark:** The arguments of the apply operator `⨀` are "reversed" when compared to the arguments of the operators `(^)` and `«o`.
For `⨀` the function to be applied is the first argument.

---

## Parser generation

Here is an EBNF grammar:

```
my $ebnfCode = q:to/END/;
<digit> = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' ;
<integer> = <digit> , { <digit> } ;
<top> = <integer> ;
END

```

```
# <digit> = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' ;
# <integer> = <digit> , { <digit> } ;
# <top> = <integer> ;

```

Here generation is the corresponding functional parsers code:

```
use FunctionalParsers::EBNF;
.say for fp-ebnf-parse($ebnfCode, actions => 'Raku::Code').head.tail;

```

```
# my &pDIGIT = alternatives(symbol('0'), symbol('1'), symbol('2'), symbol('3'), symbol('4'), symbol('5'), symbol('6'), symbol('7'), symbol('8'), symbol('9'));
# my &pINTEGER = sequence(&pDIGIT, many(&pDIGIT));
# my &pTOP = &pINTEGER;

```

For more detailed examples see ["Parser-code-generation.md"](./doc/Parser-code-generation.md).

---

## Random sentence generation

Here is an EBNF grammar:

```
my $ebnfCode2 = q:to/END/;
<top> = <who> , <verb> , <lang> ;
<who> = 'I' | 'We' ;
<verb> = 'love' | 'hate' | { '♥' } | '🤮';
<lang> = 'Julia' | 'Perl' | 'Python' | 'R' | 'WL' ;
END

```

```
# <top> = <who> , <verb> , <lang> ;
# <who> = 'I' | 'We' ;
# <verb> = 'love' | 'hate' | { '♥' } | '🤮';
# <lang> = 'Julia' | 'Perl' | 'Python' | 'R' | 'WL' ;

```

Here is generation of random sentences with the grammar above:

```
.say for fp-random-sentence($ebnfCode2, 12);

```

```
# We love R
# We hate WL
# I love Perl
# I hate Julia
# We 🤮 R
# We  R
# We  Julia
# I hate R
# We ♥ WL
# I ♥ ♥ WL
# We 🤮 WL
# We love Julia

```

---

## Generating Mermaid diagrams for EBNFs

The function `fp-ebnf-parse` can produce
[Mermaid-JS diagrams](https://mermaid.js.org)
corresponding to grammars with the target "MermaidJS::Graph".
Here is an example:

```
my $ebnfCode3 = q:to/END/;
<top> = <a> | <b> ;
<a> = 'a' , { 'A' } , [ '1' ];
<b> = 'b' , ( 'B' | '2' );
END

fp-ebnf-parse($ebnfCode3, target=>"MermaidJS::Graph", dir-spec => 'LR').head.tail

```

```
graph LR
	alt1((or))
	NT:top["top"]
	seq12((and))
	T:A("A")
	NT:b["b"]
	T:B("B")
	T:2("2")
	T:a("a")
	NT:a["a"]
	T:b("b")
	rep7((*))
	alt14((or))
	opt9((?))
	T:1("1")
	seq5((and))
	alt1 --> NT:a
	alt1 --> NT:b
	NT:top --> alt1
	rep7 --> T:A
	opt9 --> T:1
	seq5 --> |1|T:a
	seq5 --> |2|rep7
	seq5 --> |3|opt9
	NT:a --> seq5
	alt14 --> T:B
	alt14 --> T:2
	seq12 --> |1|T:b
	seq12 --> |2|alt14
	NT:b --> seq12

```

Here is a legend:

* The non-terminals are shown with rectangles
* The terminals are shown with round rectangles
* The "conjunctions" are shown in disks

**Remark:** The Markdown cell above has the parameters `result=asis, output-lang=mermaid, output-prompt=NONE`
which allow for direct diagram rendering of the obtained Mermaid code in various Markdown viewers (GitHub, IntelliJ, etc.)

Compare the following EBNF grammar and corresponding diagram with the ones above:

```
my $ebnfCode4 = q:to/END/;
<top> = <a> | <b> ;
<a> = 'a' , { 'A' } , [ '1' ] ;
<b> = 'b' , 'B' | '2' ;
END

fp-grammar-graph($ebnfCode4, dir-spec => 'LR')

```

```
graph LR
	T:A("A")
	rep7((*))
	NT:a["a"]
	T:B("B")
	T:2("2")
	seq5((and))
	alt12((or))
	NT:top["top"]
	NT:b["b"]
	T:a("a")
	seq13((and))
	alt1((or))
	opt9((?))
	T:b("b")
	T:1("1")
	alt1 --> NT:a
	alt1 --> NT:b
	NT:top --> alt1
	rep7 --> T:A
	opt9 --> T:1
	seq5 --> |1|T:a
	seq5 --> |2|rep7
	seq5 --> |3|opt9
	NT:a --> seq5
	seq13 --> |1|T:b
	seq13 --> |2|T:B
	alt12 --> seq13
	alt12 --> T:2
	NT:b --> alt12

```

---

## CLI

The package provides a Command Line Interface (CLI) script for parsing EBNF. Here is its usage message:

```
fp-ebnf-parse --help

```

```
# Usage:
#   fp-ebnf-parse <ebnf> [-t|--actions=<Str>] [-n|--parser-name=<Str>] [-p|--rule-name-prefix=<Str>] [-m|--rule-name-modifier=<Str>] [-s|--style=<Str>] -- Generates parser code for a given EBNF grammar.
#   fp-ebnf-parse <file> [-t|--actions=<Str>] [-n|--parser-name=<Str>] [-p|--rule-name-prefix=<Str>] [-m|--rule-name-modifier=<Str>] [-s|--style=<Str>] -- Generates parser code for a given EBNF grammar file.
#
#     <ebnf>                           EBNF text.
#     -t|--actions=<Str>               Actions ('t' for 'target'.) [default: 'Raku::Class']
#     -n|--parser-name=<Str>           Parser name. [default: 'MyParser']
#     -p|--rule-name-prefix=<Str>      Rule names prefix. [default: 'p']
#     -m|--rule-name-modifier=<Str>    Rule names modifier. [default: 'WhateverCode']
#     -s|--style=<Str>                 EBNF style, one of 'G4', 'Inverted', 'Standard', 'Relaxed', or 'Whatever'. [default: 'Whatever']
#     <file>                           EBNF file name.

```

If [mermaid-cli](https://github.com/mermaid-js/mermaid-cli)
is installed here is an example UNIX shell pipeline with it:

```
fp-ebnf-parse ./resources/Arithmetic.ebnf -s=relaxed -t=mermaid > diag.md && mmdc -i diag.md -o diag.png -w 1200 && open diag.png

```

---

## Implementation considerations

### Infix operators

The infix operators have to be reviewed and probably better sets of symbols would be chosen.
The challenge is to select operators that are "respected" by the typical Raku IDEs.
(I only experimented with Emacs and Comma IDE.)

### EBNF parser

All EBNF parser functions in `FunctionalParsers::EBNF` have apply-transformers that use the attributes of
a dedicated object:

```
unit module FunctionalParsers::EBNF;
...
our $ebnfActions = FunctionalParsers::EBNF::Actions::Raku::AST.new;
....

```

By assigning instances of different classes to `$ebnfActions` we get different parsing interpretations.

### Not having abstract class

Looking at the Raku EBNF interpreter classes it can be easily seen that each can inherit from a common abstract class.
But since the EBNF parsing methods (or attributes that callables) are approximately a dozen one-liners,
it seems more convenient to have all class method- and attribute definitions on “one screen.”

### Flowchart

```
graph TD
    FPs[[EBNF<br/>Functional Parsers]]
    RakuAST[Raku::AST]
    RakuClass[Raku::Class]
    RakuCode[Raku::Code]
    RakuGrammar[Raku::Grammar]
    WLCode[WL::Code]
    WLGrammar[WL::Grammar]
    JavaFuncJ[Java::FuncJ]
    JavaANTLR[Java::ANTLR]
    Input[/- EBNF code<br/>- Properties/]
    PickTarget[Assign context]
    Parse[Parse]
    QEVAL{Evaluate?}
    EVAL[[EVAL]]
    Code>Code]
    Context[Context object]
    Result{{Result}}
    Input --> PickTarget
    PickTarget -.- WL
    PickTarget -.- Java
    PickTarget -..- Raku
    PickTarget -.-> Context
    PickTarget --> Parse
    Parse -.- FPs
    Context -.-> FPs
    Parse --> QEVAL
    Parse -.-> Code
    QEVAL --> |yes|EVAL
    Code -.-> EVAL
    EVAL ---> Result
    QEVAL ---> |no|Result
    subgraph Raku
        RakuAST
        RakuClass
        RakuCode
        RakuGrammar
    end
    subgraph WL
        WLCode
        WLGrammar
    end
    subgraph Java
        JavaFuncJ
        JavaANTLR
    end

```

---

## TODO

* TODO Parsing EBNF refactoring & additional features
  * DONE Parse any combination of sequence operators
    * Initially, only these were parsed:
      * `'a' <& 'b' <& 'c' | 'a' &> 'd';`
      * `'a' , 'b' , 'c' | 'a' &> 'd';`
    * These are also parsed:
      * `'a' , 'b' &> 'c'`
      * `'a' <& 'b' &> 'c'`
  * DONE Class-based parsers
    * DONE From characters
    * DONE From tokens
  * DONE Themed parsers
    * DONE Inheritance based implementation
    * DONE "Simpler"
    * DONE ANTLR / G4
    * DONE Whatever
  * TODO "Named" tokens
    * `'_?StringQ'` or `'_String'`
    * `'_WordString'`, `'_LetterString'`, and `'_IdentifierString'`
    * `'_?NumberQ'` and `'_?NumericQ'`
    * `'_Integer'`
    * `'Range[*from*, *to*]'`
* TODO Interpreters of EBNF
  * DONE Java
    * DONE ["funcj.parser"](https://github.com/typemeta/funcj/tree/master/parser)
  * TODO [GraphViz](https://graphviz.org)
    * TODO [DOT](https://graphviz.org/doc/info/lang.html)
  * DONE MermaidJS
  * TODO Scala
    * TODO built-in
    * TODO [parsley](https://github.com/j-mie6/parsley)
  * MAYBE Python
  * TODO Raku
    * DONE AST
    * DONE Class
    * DONE Code
    * DONE Grammar
    * TODO Tokenizer (of character sequences)
    * Other EBNF styles
  * TODO WL
    * DONE FunctionalParsers, [AAp1, AAp2]
    * [P] TODO GrammarRules
      * Implemented to a point, not tested in WL.
    * Graph
      * Via MermaidJS classes.
* TODO Translators
  * TODO FPs code into EBNF
    * Very cool to have, but seems to be a lot of work.
  * DONE Raku grammars to FPs
    * See the class "Grammar::TokenProcessing::Actions::EBNF" of the package "Grammar::TokenProcessing".
  * DONE Stand-alone grammar-graph translation function.
    * `fp-grammar-graph`
* TODO Extensions
  * DONE First-matched alternation
    * The standard `alterations` parser is ["longest alternation"](https://docs.raku.org/language/regexes#Longest_alternation:_%7C) (in Raku's terms.)
  * TODO Extra parsers
    * DONE `pInteger`
    * DONE `pNumber`
    * DONE `pWord`
    * DONE `pLetterWord`
    * DONE `pIdentifier`
    * TODO `pNumberRange`
    * Other?
  * TODO Zero-width assertions implementation
    * TODO Lookahead
    * TODO Lookbehind
* DONE Random sentence generation
  * DONE Basic class code
  * DONE Preventing infinite recursion
  * DONE "Named" tokens interpretation
    * `'_?StringQ'` or `'_String'`
    * `'_WordString'`, `'_LetterString'`, and `'_IdentifierString'`
    * `'_?NumberQ'` and `'_?NumericQ'`
    * `'_Integer'`
    * `'Range[*from*, *to*]'`
* TODO Documentation
  * DONE README
  * DONE Parser code generation
    * TODO Raku
      * DONE Class
      * TODO Code
      * DONE Grammar
    * DONE WL
      * DONE FunctionalParsers
      * DONE GrammarRules
    * TODO Java
  * TODO Random sentences generation
  * TODO Mermaid flowchart
  * TODO Mermaid class diagram?
* TODO Videos
  * TODO Introduction
  * TODO TRC-2023 presentation

---

## References

### Articles

[JF1] Jeroen Fokker,
["Function Parsers"](https://www.researchgate.net/publication/2426266_Functional_Parsers),
(1997),
Conference: Advanced Functional Programming,
First International Spring School on Advanced Functional Programming Techniques-Tutorial Text.
10.1007/3-540-59451-5\_1.

[WV1] Wim Vanderbauwhede,
["List-based parser combinators in Haskell and Raku"](https://limited.systems/articles/list-based-parser-combinators/),
(2020),
[Musings of an Accidental Computing Scientist at codeberg.page](https://wimvanderbauwhede.codeberg.page).

### Packages, paclets, repositories

[AAp1] Anton Antonov,
["FunctionalParsers.m"](https://github.com/antononcube/MathematicaForPrediction/blob/master/FunctionalParsers.m),
(2014),
[MathematicaForPrediction at GitHub](https://github.com/antononcube/MathematicaForPrediction).

[AAp2] Anton Antonov,
["FunctionalParsers" WL paclet](https://resources.wolframcloud.com/PacletRepository/resources/AntonAntonov/FunctionalParsers/),
(2023),
[Wolfram Language Paclet Repository](https://resources.wolframcloud.com/PacletRepository/).

[WVp1] Wim Vanderbauwhede,
[List-based parser combinator library in Raku](https://github.com/wimvanderbauwhede/list-based-combinators-raku),
(2020),
[GitHub/wimvanderbauwhede](https://github.com/wimvanderbauwhede).

[WVp2] Wim Vanderbauwhede,
[Parser::Combinators Perl package](https://github.com/wimvanderbauwhede/Perl-Parser-Combinators),
(2013-2015),
[GitHub/wimvanderbauwhede](https://github.com/wimvanderbauwhede).


## dist_zef-lizmat-List-UtilsBy.md
[![Actions Status](https://github.com/lizmat/List-UtilsBy/workflows/test/badge.svg)](https://github.com/lizmat/List-UtilsBy/actions)

# NAME

Raku port of Perl's List::UtilsBy module 0.11

# SYNOPSIS

```
use List::UtilsBy <nsort_by min_by>;

my @files_by_age = nsort_by { .IO.modified }, @files;

my $shortest_name = min_by { .chars }, @names;

```

# DESCRIPTION

This module tries to mimic the behaviour of Perl's `List::UtilsBy` module as closely as possible in the Raku Programming Language.

List::UtilsBy provides some trivial but commonly needed functionality on lists which is not going to go into `List::Util`.

# Porting Caveats

Raku does not have the concept of `scalar` and `list` context. Usually, the effect of a scalar context can be achieved by prefixing `+` to the result, which would effectively return the number of elements in the result, which usually is the same as the scalar context of Perl of these functions.

Many functions take a `&code` parameter of a `Block` to be called by the function. Many of these assume **$\_** will be set. In Raku, this happens automagically if you create a block without a definite or implicit signature:

```
say { $_ == 4 }.signature;   # (;; $_? is raw)

```

which indicates the Block takes an optional parameter that will be aliased as `$_` inside the Block. If you want to be able to change `$_` inside the block **without** changing the source array, you can use the `is copy` trait thus:

```
-> $_ is copy { ... code changing $_ ... }

```

Raku also doesn't have a single `undef` value, but instead has `Type Objects`, which could be considered undef values, but with a type annotation. In this module, `Nil` (a special value denoting the absence of a value where there should have been one) is used instead of `undef`.

Also note there are no special parsing rules with regards to blocks in Raku. So a comma is **always** required after having specified a block.

Some functions return something different in scalar context than in list context. Raku doesn't have those concepts. Functions that are supposed to return something different in scalar context also the `Scalar` type as the first positional parameter to indicate the result like the result of a scalar context, is required. It will be noted with the function in question if that feature is available.

# FUNCTIONS

## sort\_by BLOCK, LIST

Returns the list of values sorted according to the string values returned by the BLOCK. A typical use of this may be to sort objects according to the string value of some accessor, such as:

```
my @sorted = sort_by { .name }, @people;

```

The key function is being passed each value in turn, The values are then sorted according to string comparisons on the values returned. This is equivalent to:

```
my @sorted = sort -> $a, $b { $a.name cmp $b.name }, @people;

```

except that it guarantees the `name` accessor will be executed only once per value. One interesting use-case is to sort strings which may have numbers embedded in them "naturally", rather than lexically:

```
my @sorted = sort_by { S:g/ (\d+) / { sprintf "%09d", $0 } / }, @strings;

```

This sorts strings by generating sort keys which zero-pad the embedded numbers to some level (9 digits in this case), helping to ensure the lexical sort puts them in the correct order.

### Idiomatic Raku ways

```
my @sorted = @people.sort: *.name;

```

## nsort\_by BLOCK, LIST

Similar to `/sort_by` but compares its key values numerically.

### Idiomatic Raku ways

```
my @sorted = <10 1 20 42>.sort: +*;

```

## rev\_sort\_by BLOCK, LIST

## rev\_nsort\_by BLOCK, LIST

```
my @sorted = rev_sort_by { KEYFUNC }, @values;

my @sorted = rev_nsort_by { KEYFUNC }, @values;

Similar to L<sort_by> and L<nsort_by> but returns the list in the reversei
order.

```

## max\_by BLOCK, LIST

```
my @optimal = max_by { KEYFUNC }, @values;

my $optimal = max_by Scalar, { KEYFUNC }, @values;

```

Returns the (first) value(s) from `@vals` that give the numerically largest result from the key function.

```
my $tallest = max_by Scalar, { $_->height }, @people;

my $newest = max_by Scalar, { .IO.modified }, @files;

```

If the `Scalar` positional parameter is specified, then only the first maximal value is returned. Otherwise a list of all the maximal values is returned. This may be used to obtain positions other than the first, if order is significant.

If called on an empty list, an empty list is returned.

For symmetry with the </nsort_by> function, this is also provided under the name `nmax_by` since it behaves numerically.

### Idiomatic Raku ways

```
my @tallest = @people.max( *.height );       # all tallest people

my $tallest = @people.max( *.height ).head;  # only the first

```

## min\_by BLOCK, LIST

```
my @optimal = min_by { KEYFUNC }, @values;

my $optimal = min_by Scalar, { KEYFUNC }, @values;

```

Similar to </max_by> but returns values which give the numerically smallest result from the key function. Also provided as `nmin_by`

### Idiomatic Raku ways

```
my @smallest = @people.min: *.height;       # all smallest people

my $smallest = @people.min( *.height ).head;  # only the first

```

## minmax\_by

```
my ($minimal, $maximal) = minmax_by { KEYFUNC }, @values;

```

Similar to calling both </min_by> and </max_by> with the same key function on the same list. This version is more efficient than calling the two other functions individually, as it has less work to perform overall. Also provided as `nminmax_by`.

### Idiomatic Raku ways

```
my ($smallest,$tallest) = @people.minmax: *.height;

```

## uniq\_by BLOCK, LIST

```
my @unique = uniq_by { KEYFUNC }, @values;

```

Returns a list of the subset of values for which the key function block returns unique values. The first value yielding a particular key is chosen, subsequent values are rejected.

```
my @some_fruit = uniq_by { $_->colour }, @fruit;

```

To select instead the last value per key, reverse the input list. If the order of the results is significant, don't forget to reverse the result as well:

```
my @some_fruit = reverse uniq_by { $_->colour }, reverse @fruit;

```

Because the values returned by the key function are used as hash keys, they ought to either be strings, or at least stringify in an identifying manner.

### Idiomatic Raku ways

```
my @some_fruit = @fruit.uniq: *.colour;

```

## partition\_by BLOCK, LIST

```
my %parts = partition_by { KEYFUNC }, @values;

```

Returns a Hash of Arrays containing all the original values distributed according to the result of the key function block. Each value will be an Array containing all the values which returned the string from the key function, in their original order.

```
my %balls_by_colour = partition_by { $_->colour }, @balls;

```

Because the values returned by the key function are used as hash keys, they ought to either be strings, or at least stringify in an identifying manner.

### Idiomatic Raku ways

```
my %balls_by_colour = @balls.classify: *.colour;

```

## count\_by BLOCK, LIST

```
my %counts = count_by { KEYFUNC }, @values;

```

Returns a Hash giving the number of times the key function block returned the key, for each value in the list.

```
my %count_of_balls = count_by { $_->colour }, @balls;

```

Because the values returned by the key function are used as hash keys, they ought to either be strings, or at least stringify in an identifying manner.

### Idiomatic Raku ways

```
my %count_of_balls = @balls.map( *.colour ).Bag;

```

## zip\_by BLOCK, ARRAYS

```
my @vals = zip_by { ITEMFUNC }, @arr0, @arr1, @arr2, ... ;

```

Returns a list of each of the values returned by the function block, when invoked with values from across each each of the given Arrays. Each value in the returned list will be the result of the function having been invoked with arguments at that position, from across each of the arrays given.

```
my @transposition = zip_by { [ @_ ] }, @matrix;

my @names = zip_by { "$_[1], $_[0]" }, @firstnames, @surnames;

print zip_by { "$_[0] => $_[1]\n" }, %hash.keys, %hash.values;

```

If some of the arrays are shorter than others, the function will behave as if they had `Any` in the trailing positions. The following two lines are equivalent:

```
zip_by { f(@_) }, [ 1, 2, 3 ], [ "a", "b" ];
f( 1, "a" ), f( 2, "b" ), f( 3, Any );

```

If the item function returns a list, and you want to have the separate entries of that list to be included in the result, you need to return that slip that list. This can be useful for example, for generating a hash from two separate lists of keys and values:

```
my %nums = zip_by { |@_ }, <one two three>, (1, 2, 3);
# %nums = ( one => 1, two => 2, three => 3 )

```

(A function having this behaviour is sometimes called `zipWith`, e.g. in Haskell, but that name would not fit the naming scheme used by this module).

### Idiomatic Raku ways

```
my @names = zip @firstnames, @surnames, :with({ "$^b, $^a" });

zip [1,2,3], [<a b>], :with(&f);

my %nums = zip <one two three>, (1, 2, 3);

```

## unzip\_by BLOCK, LIST

```
my (@arr0, @arr1, @arr2, ...) = unzip_by { ITEMFUNC }, @vals

```

Returns a list of Arrays containing the values returned by the function block, when invoked for each of the values given in the input list. Each of the returned Arrays will contain the values returned at that corresponding position by the function block. That is, the first returned Array will contain all the values returned in the first position by the function block, the second will contain all the values from the second position, and so on.

```
my (@firstnames, @lastnames) = unzip_by { .split(" ",2) }, @names;

```

If the function returns lists of differing lengths, the result will be padded with `Any` in the missing elements.

This function is an inverse of </zip_by>, if given a corresponding inverse function.

## extract\_by BLOCK, ARRAY

```
my @vals = extract_by { SELECTFUNC }, @array;

```

Removes elements from the referenced array on which the selection function returns true, and returns a list containing those elements. This function is similar to `grep`, except that it modifies the referenced array to remove the selected values from it, leaving only the unselected ones.

```
my @red_balls = extract_by { .color eq "red" }, @balls;
# Now there are no red balls in the @balls array

```

This function modifies a real array, unlike most of the other functions in this module. Because of this, it requires a real array, not just a list.

This function is implemented by invoking `splice` on the array, not by constructing a new list and assigning it.

## extract\_first\_by BLOCK, ARRAY

```
my $value = extract_first_by { SELECTFUNC }, @array;

```

A hybrid between </extract_by> and `List::Util::first`. Removes the first element from the referenced array on which the selection function returns true, returning it.

As with </extract_by>, this function requires a real array and not just a list, and is also implemented using `splice`.

If this function fails to find a matching element, it will return an empty list unless called with the `Scalar` positional parameter: in that case it will return `Nil`.

## weighted\_shuffle\_by BLOCK, LIST

```
my @shuffled = weighted_shuffle_by { WEIGHTFUNC }, @values;

```

Returns the list of values shuffled into a random order. The randomisation is not uniform, but weighted by the value returned by the `WEIGHTFUNC`. The probability of each item being returned first will be distributed with the distribution of the weights, and so on recursively for the remaining items.

## bundle\_by BLOCK, NUMBER, LIST

```
my @bundled = bundle_by { BLOCKFUNC }, $number, @values;

```

Similar to a regular `map` functional, returns a list of the values returned by `BLOCKFUNC`. Values from the input list are given to the block function in bundles of `$number`.

If given a list of values whose length does not evenly divide by `$number`, the final call will be passed fewer elements than the others.

### Idiomatic Raku ways

```
my @bundled = @values.batch(3).map: -> @_ { ... };

```

# AUTHOR

Elizabeth Mattijsen [liz@raku.rocks](mailto:liz@raku.rocks)

If you like this module, or what I’m doing more generally, committing to a [small sponsorship](https://github.com/sponsors/lizmat/) would mean a great deal to me!

Source can be located at: <https://github.com/lizmat/List-UtilsBy> . Comments and Pull Requests are welcome.

# COPYRIGHT AND LICENSE

Copyright 2018, 2019, 2020, 2021, 2023 Elizabeth Mattijsen

This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.

Re-imagined from the Perl version as part of the CPAN Butterfly Plan. Perl version developed by Paul Evans.


## dist_zef-raku-community-modules-LN.md
[![Actions Status](https://github.com/raku-community-modules/LN/actions/workflows/test.yml/badge.svg)](https://github.com/raku-community-modules/LN/actions)

# NAME

LN - Get $\*ARGFILES with line numbers via $\*LN

# SYNOPSIS

```
perl  -wlnE   'say "$.:$_"; close ARGV if eof' foo bar # Perl
raku -MLN -ne 'say "$*LN:$_"'                  foo bar # Raku

```

```
$ echo -e "a\nb\nc" > foo
$ echo -e "d\ne"    > bar

$ raku -MLN -ne 'say "$*LN:$_"' foo bar
1:a
2:b
3:c
1:d
2:e

$ raku -ne 'use LN "no-reset"; say "$*LN:$_"' foo bar
1:a
2:b
3:c
4:d
5:e

```

# DESCRIPTION

Mixes in [`IO::CatHandle::AutoLines`](https://raku.land/zef:raku-community-modules/IO::CatHandle::AutoLines)) into [`$*ARGFILES`](https://docs.perl6.org/language/variables#index-entry-%24%2AARGFILES) which provides an `.ln` method containing current line number of the current handle (or total line number if `'no-reset'` option was passed to `use`). For ease of access to that method `$*LN` dynamic variable containing its value is available.

# EXPORTED TERMS

## $\*LN

Contains same value as `$*ARGFILES.ln`https://raku.land/zef:raku-community-modules/IO::CatHandle::AutoLines#synopsis| which is a method exported by [`IO::CatHandle::AutoLines`](https://raku.land/zef:raku-community-modules/IO::CatHandle::AutoLines) that gives the current line number of the handle.

By default, the line number will get reset on each new file in `$*ARGFILES`. If you wish it to *not* reset, pass `"no-reset"` positional argument to the `use` line:

```
use LN 'no-reset';

=head1 EXPORTED TYPES

=head2 role IO::CatHandle::AutoLines

Exports L<C<IO::CatHandle::AutoLines>|https://raku.land/zef:raku-community-modules/IO::CatHandle::AutoLines>
role, for you to use, if needed.

```

# AUTHOR

Zoffix Znet

# COPYRIGHT AND LICENSE

Copyright 2017 Zoffix Znet

Copyright 2018 - 2022 Raku Community

This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.


## dist_cpan-CTILMES-DB-MySQL.md
# DB::MySQL - MySQL access for Perl 6

[![Build Status](https://travis-ci.org/CurtTilmes/perl6-dbmysql.svg)](https://travis-ci.org/CurtTilmes/perl6-dbmysql)

This is a reimplementation of Perl 6 bindings for MySQL.

## Basic usage

```
use DB::MySQL;
my $mysql = DB::MySQL.new();  # You can pass in various options

```

Execute a query, and get a single value:

```
say $mysql.execute('select 42').value;
# 42

```

Create a table:

```
$mysql.execute('create table foo (x int, y varchar(80))');

```

Insert some values using placeholders:

```
$mysql.query('insert into foo (x,y) values (?,?)', 1, 'this');

```

Execute a query returning a row as an array or hash;

```
say $mysql.query('select * from foo where x = ?', 1).array;
say $mysql.query('select * from foo where x = ?', 1).hash;

```

Execute a query returning a bunch of rows as arrays or hashes:

```
.say for $mysql.query('select * from foo').arrays;
.say for $mysql.query('select * from foo').hashes;

```

`.query()` caches a prepared statement, and can have placeholders and
arguments - `.execute()` does not prepare/cache and can't have
placeholders. Both can return results.

## Installation

This module relies on `libmysqlclient.so`. For Ubuntu, I install this
with:

```
sudo apt install libmysqlclient-dev

```

I worked with version 5.7 of the API. It may or may not work with
other versions. You can see the client version with:

```
perl6 -MDB::MySQL::Native -e 'say mysql_get_client_info'

```

There are likely 64-bit Linux dependencies in the code. Patches
welcome if someone wants to make it on other OSes.

## Connection Information

There are many options that can be specified to `DB::MySQL.new()`:

* `:host` - defaults to `localhost`
* `:port` - defaults to `3306`
* `:user`
* `:password`
* `:socket`
* `:database` - optional, sets current database
* `:connect-timeout` - timeout in seconds for a connect attempt.
* `:read-timeout` - timeout in seconds for each attempt to read
  from the servers.
* `:write-timeout` - timeout in seconds for each attempt to write to
  the server.
* `:default-file` - Read options from the named file instead of
  `my.cnf`.
* `:group` - defaults to 'client'. Reads options from the specified
  group in the `.my.cnf` file. Undefine this to ignore defaults file.

The easiest way to connect is to put your options in `.my.cnf`.

## DB::MySQL::Connection

The main **DB::MySQL** object acts as a factory for connections,
maintaining a cache of connections already created. A new connection
can be requested with the `.db` method, but often this isn't needed.
When you are finished with a connection, you can explicitly return it
to the cache with `.finish`.

You can call `.query()` or `.execute()` on the main **DB::SQLite**
object, but all they really do is allocate a
**DB::SQLite::Connection** (either from the cache, or create a new
one) and call those methods on it, then return the connection to the
cache.

These are equivalent:

```
.say for $mysql.query('select * from foo').arrays;

```

```
my $db = $mysql.db;
.say for $mysql.query('select * from foo').arrays;
$db.finish;

```

The connection object also has some extra methods for separately
preparing and executing the query:

```
my $db = $mysql.db;
my $sth = $db.prepare('insert into foo (x,y) values (?,?)');
$sth.execute(1, 'this');
$sth.execute(2, 'that');
$db.finish;

```

You can also call `.finish()` on the statement:

```
my $sth = $mysql.db.prepare('insert into foo (x,y) values (?,?)');
$sth.execute(1, 'this');
$sth.execute(2, 'that');
$sth.finish;

```

The statement will finish the associated connection, returning it to
the cache. Yet another way to do it is to pass `:finish` in to the
execute.

```
my $sth = $mysql.db.prepare('insert into foo (x,y) values (?,?)');
$sth.execute(1, 'this');
$sth.execute(2, 'that', :finish);

```

And finally, a cool Perl 6ish way is the `will` trait to install a
Phaser directly on the variable:

```
{
    my $sth will leave { .finish } = $mysql.db.prepare('insert into foo (x,y) values (?,?)');
    $sth.execute(1, 'this');
    $sth.execute(2, 'that');
}

```

Calling `.prepare()` on the **DB::MySQL::Connection** prepares and
returns a **DB::MySQL::Statement** that can then be `.execute()`ed.
The prepared statement is also retained in a cache with the
connection. If the same statement is prepared again on the same
connection, the cached object will be returned instead of
re-preparing. If you don't want it to be cached, you can pass in the
`:nocache` option.

```
my $sth = $mysql.db.prepare('insert into foo (x,y) values (?,?)', :nocache);
$sth.execute(1, 'this');
$sth.execute(2, 'that', :finish);

```

You must still take care to call `.finish()` to return the connection
to the connection cache so it will get reused. (Or take care NOT to
call `.finish()` if you don't want the connection to be reused,
possibly in another thread.)

For the main object, or the connection object, `.execute()` is used
instead of `.query()` if you don't need placeholders/arguments.

## Transactions

The database connection object can also manage transactions with the
`.begin`, `.commit`, and `.rollback` methods:

```
my $db = $mysql.db;
my $sth = $db.prepare('insert into foo (x,y) values (?,?)');
$db.begin;
$sth.execute(1, 'this');
$sth.execute(2, 'that');
$db.commit;
$db.finish;

```

The `begin`/`commit` ensure that the statements between them happen
atomically, either all or none.

Transactions can also dramatically improve performance for some
actions, such as performing thousands of inserts/deletes/updates since
the indexes for the affected table can be updated in bulk once for the
entire transaction.

If you `.finish` the database prior to a `.commit`, an uncommitted
transaction will automatically be rolled back.

As a convenience, `.commit` also returns the database object, so you
can just `$db.commit.finish`.

## Results

Calling `.query()` on a **DB::MySQL** or **DB::MySQL::Connection**,
or calling `.execute()` on a **DB::SQLite::Statement** with an SQL
SELECT or something that returns data, a `DB::SQLite::Result` object
will be returned.

The query results can be consumed from that object with the following
methods:

* `.value` - a single scalar result
* `.array` - a single array of results from one row
* `.hash` - a single hash of results from one row
* `.arrays` - a sequence of arrays of results from all rows
* `.hashes` - a sequence of hashes of results from all rows

If the query isn't a select or otherwise doesn't return data, such as
an INSERT, UPDATE, or DELETE, it will return the number of rows
affected.

By default, the entire result of the query is retrieved immediately
from the server to the client. You can pass in the `:nostore` option
to `.query` or `.execute` to avoid this behavior. It will then
retrieve the results from the server as you consume them on the
client. This will hold up server resources while you retrieve the
results, so exercise care with this.

## Exceptions

All database errors, including broken SQL queries, are thrown as exceptions.

## Acknowledgements

Inspiration taken from the existing Perl6
[DBIish](https://github.com/perl6/DBIish) module as well as the Perl 5
[Mojo::Pg](http://mojolicious.org/perldoc/Mojo/Pg) from the
Mojolicious project.

## License

Portions thanks to DBIish:

Copyright © 2009-2016, the DBIish contributors All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

* Redistributions of source code must retain the above copyright
  notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
  notice, this list of conditions and the following disclaimer in the
  documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


## dist_cpan-ATROXAPER-Propius.md
[![Build Status](https://travis-ci.org/atroxaper/p6-Propius.svg?branch=master)](https://travis-ci.org/atroxaper/p6-Propius)

# Propius

Memory cache with loader and eviction by time.
Inspired by [Guava's CacheLoader](https://github.com/google/guava/wiki/CachesExplained).

## Examples

```
    use Propius;
    my $cache = eviction-based-cache(
      loader => { $:key ** 2 }, # calculation of the new value for key
      removal-listener => { say 'removed ', $:key, ':', $:value, ' cause ', $:cause },
        # optional listener for removed values
      expire-after-write => 60); # freshness time of cached values;

    $cache.get(5); # returns prodused the new value - 25;
    $cache.get(5): # returns cached value - 25;
    $cache.get-if-exists(6); # returns Any
    $cache.put(:9key, loader => { $:key ** 3 }); # cache value for specified loader
    $cache.get(9); # returns cached value - 729
    # ... 60 seconds later in output (in case you use the cache)
    removed 5:25 cause Expired
    removed 9:729 cause Expired

```

## Create

You can use sub `eviction-based-cache` for creation the new cache.
Arguments are:

`:&loader! where .signature ~~ :(:$key)` - sub with signature like `(:$key)`.
The sub will be used for producing the new values. Obligatory argument.

`:&removal-listener where .signature ~~ :(:$key, :$value, :$cause)` -
sub with signature like `(:$key, :$value, :$cause)`.
The sub will be called in case when value removed from the cache.
Cause is element of enum `RemoveCause`.

`:$expire-after-write` - how long the cache have to store value after its last re/write

`:$expire-after-access` - how long the cache have to store value after its last access (read or write)

`:$time-unit` - object of `TimeUnit`, indicate time unit of expire-after-write/access value.
Seconds by default.

`:$ticker` - object of `Ticker`, witch is used for retrieve 'current' time.
Can be specified for overriding standard behaviour (current system time), for example for testing.

`:$size` - max capacity of the cache.

## Notes

The cache can use object keys. If you want that you have to control .WHICH method of keys.

Of course the cache is thread-save. It simply uses OO::Monitors for synchronisation.

## Available methods

### get(Any:D $key)

Retrieve value by key.

```
    my $is-primitive = $cache.get(655360001);

```

If there is no value for specified key then loader with be
used to produce the new value.

### get-if-exists(Any:D $key)

Retrieve value by key only if it exists.

```
    my $is-primitive = $cache.get-if-exists(900900900900990990990991);

```

If there is no value for specified key then Any will be returned.

### put(Any:D :$key, Any:D :$value)

### put(Any:D :$key, :&loader! where .signature ~~ :(:$key))

Store a value in cache with/without specified loader.

```
    $cache.put(:900900900900990990990991key, :value);
    $cache.put(:2key, loader => { True });

```

It will rewrite any cached value for specified key. In that case
removal-listener will be called with old value cause Replaced.

In case of cache already reached max capacity value which has not
been used for a longest time will be removed. In that case
removal-listener will be called with old value cause Size.

### invalidate

### invalidateAll(List:D @keys)

### invalidateAll

Mark value/values for specified/all key/keys as invalidate.

```
    $cache.invalidate(655360001);
    $cache.invalidateAll(<1 2 3>);
    $cahce.invalidateAll();

```

The value will be removed and removal-listener will be called for each
old values cause Explicit.

### elems

Return keys and values stored in cache as Hash.

```
    $cache.elems();

```

### hash

Return keys and values stored in cache as Hash.

```
    $cache.hash();

```

This is a copy of values. Any modification of returned cache will no have
an effect on values in the store.

### clean-up

Clean evicted values from cache.

```
    $cache.clean-up();

```

This method may be invoked directly by user.

The method invoked on each write operation and ones for several read operation
if there was no write operation recently.

It means that evicted values will not be removed on just in time of its eviction.
This is done for the purpose of optimisation - is it not requires special thread
for checking an eviction. If it is issue for you then you can call it method yourself
by some scheduled Promise for example.

## Sources

[GitHub](https://github.com/atroxaper/p6-Propius)

## Author

Mikhail Khorkov [atroxaper@cpan.org](mailto:atroxaper@cpan.org)

## License

See <LICENSE> file for the details of the license of the code in this repository.


## dist_cpan-RIBNOTTER-Text-Names.md
Text::Names generates American English names.

I wrote this project as a way of learning perl6 so the code may not be fully idiomatic perl6.

# Usage

```
get-full() # generates a random name with a first name and last name
get-full("male") # generates a random male full name
get-full("female") # generates a random female full name
get-male() # generates just a male first name
get-female() # generates just a female first name
get-last() # generates just a last name

```

You can significantly increase performance for large numbers of generated names by setting `$*buffer-size` to the number of names you plan on generating. By default, the file is reread every time a name is generated. `$*buffer-size` tells the library to fetch that many names at once from each file used. `$*buffer-size` will likely not significantly improve performance for small numbers of generated names.

If you prefer enums to magic strings, you can use `male`, `female`, and `both` from the enum `Gender`.

# Known Issues

Performance is a bit rubbish. The current algorithm is slower than it needs to be. Some speed increases can be implemented likely by indexing the source file instead of reading though almost the entire name database every time a rare name is generated. Alternatively a heuristic could likely be used to allow greater leaps down the text file to find the target name quicker.

In theory, the automatic tests could rarely fail just from drawing the same random name several times in a row. I have never seen this happen and is extremely unlikely.

# Credit

This module was written using the python ["names"](https://github.com/treyhunner/names) module heavily as reference. Ribbon-otter (me) copied the public domain source files as well as the basic algorithm from it. The names python project, at time of writing, lists their authors as

* Trey Hunner <http://treyhunner.com>
* Simeon Visser <http://simeonvisser.com>


## charsorbytes.md
class X::Proc::Async::CharsOrBytes

Error due to tapping the same Proc::Async stream for both text and binary reading

```raku
class X::Proc::Async::CharsOrBytes is Exception {}
```

A [`Proc::Async`](/type/Proc/Async) object allows subscription to the output or error stream either for bytes ([`Blob`](/type/Blob)) or for text data ([`Str`](/type/Str)), but not for both. If you do try both, it throws an exception of type `X::Proc::Async::CharsOrBytes`.

```raku
my $proc = Proc::Async.new('echo');
$proc.stdout.tap(&print);
$proc.stdout(:bin).tap(&print);
CATCH { default { put .^name, ': ', .Str } };
# OUTPUT: «X::Proc::Async::CharsOrBytes: Can only tap one of chars or bytes supply for stdout␤»
```

# [Methods](#class_X::Proc::Async::CharsOrBytes "go to top of document")[§](#Methods "direct link")

## [method handle](#class_X::Proc::Async::CharsOrBytes "go to top of document")[§](#method_handle "direct link")

```raku
method handle(X::Proc::Async::CharsOrBytes:D: --> Str:D)
```

Returns the name of the handle that was accessed both for text and for binary data, `stdout` or `stderr`.


## dist_cpan-ARNE-Time-Repeat.md
# NAME

Time::Repeat - Modules for working with time intervals.

# SYNOPSIS

use Time::Repeat::String; # Work with text strings

use Time::Repeat::HHMM; # Work with HHMM objects (hour and minutes), defined in the module

use Time::Repeat::HHMM::Interval; # Work with intervals, based on HHMM objects

use Time::Repeat::MM; # Work with MM objects (minutes), defined in the module

use Time::Repeat::DateTime; # Work with DateTime objects

# DESCRIPTION

See the indvividual module documentation for a list of procedures and methods they provide.

# AUTHOR

Arne Sommer; arne at perl6.eu

# COPYRIGHT AND LICENSE

Copyright 2018-2019 Arne Sommer. This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.


## variable.md
class Variable

Object representation of a variable for use in traits

```raku
class Variable {}
```

Variables have a wealth of compile-time information, but at runtime, accesses to a variable usually act on the value stored inside it, not the variable itself. The runtime class of a variable is [`Scalar`](/type/Scalar).

Class `Variable` holds the compile-time information that traits can use to introspect and manipulate variables.

# [Traits](#class_Variable "go to top of document")[§](#Traits "direct link")

## [trait is default](#class_Variable "go to top of document")[§](#trait_is_default "direct link")

Sets the default value with which a variable is initialized, and to which it is reset when [`Nil`](/type/Nil) is assigned to it. Trait arguments are evaluated at compile time. Closures won't do what you expect: they are stored as is and need to be called by hand.

```raku
my Int $x is default(42);
say $x;     # OUTPUT: «42␤»
$x = 5;
say $x;     # OUTPUT: «5␤»
# explicit reset:
$x = Nil;
say $x;     # OUTPUT: «42␤»
```

The trait `is default` can be used also with subscripting things like arrays and hashes:

```raku
my @array is default( 'N/A' );
@array[22].say;  # OUTPUT: N/A
@array = Nil;
@array.say;      # OUTPUT: [N/A]
@array[4].say;   # OUTPUT: N/A

my %hash is default( 'no-value-here' );
%hash<non-existent-key>.say; # OUTPUT: no-value-here
%hash<foo> = 'bar';
%hash<>.say;                 # OUTPUT: {foo => bar}
%hash<wrong-key>.say;        # OUTPUT: no-value-here

```

## [trait is dynamic](#class_Variable "go to top of document")[§](#trait_is_dynamic "direct link")

```raku
multi trait_mod:<is>(Variable:D, :$dynamic)
```

Marks a variable as dynamic, that is, accessible from inner dynamic scopes without being in an inner lexical scope.

```raku
sub introspect() {
    say $CALLER::x;
}
my $x is dynamic = 23;
introspect;         # OUTPUT: «23␤»
{
    # not dynamic
    my $x;
    introspect()    # dies with an exception of X::Caller::NotDynamic
}

```

The `is dynamic` trait is a rather cumbersome way of creating and accessing dynamic variables. A much easier way is to use the `* twigil`:

```raku
sub introspect() {
    say $*x;
}
my $*x = 23;
introspect;         # OUTPUT: «23␤»
{
    # not dynamic
    my $x;
    introspect()    # dies with an exception of X::Dynamic::NotFound
}

```

## [trait of](#class_Variable "go to top of document")[§](#trait_of "direct link")

```raku
multi trait_mod:<of>(Mu:U $target, Mu:U $type)
```

Sets the type constraint of a container bound to a variable.

```raku
my $i of Int = 42;
$i = "forty plus two";
CATCH { default { say .^name, ' ', .Str } }
# OUTPUT: «X::TypeCheck::Assignment Type check failed in assignment to $i; expected Int but got Str ("forty plus two")␤»
```

You can use any value defined in compile time as a type constraint, including constants:

```raku
constant \T = Int;
my $i of T = 42;
```

which would be equivalent to the previous definition.

# [Methods](#class_Variable "go to top of document")[§](#Methods "direct link")

## [method name](#class_Variable "go to top of document")[§](#method_name "direct link")

```raku
method name(Variable:D: str)
```

Returns the name of the variable, including the sigil.

# [Typegraph](# "go to top of document")[§](#typegraphrelations "direct link")

Type relations for `Variable`

raku-type-graph

Variable
Variable

Any
Any

Variable->Any

Mu
Mu

Any->Mu

[Expand chart above](/assets/typegraphs/Variable.svg)