Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

PPC Elevator Pitch for Perl::Types

26 views
Skip to first unread message

Oodler 577 via perl5-porters

unread,
Aug 16, 2023, 12:45:05 AM8/16/23
to perl5-...@perl.org
# Proposed Perl Changes Elevator Pitch for Perl::Types

This document is the first step in the Proposed Perl Changes process:

https://github.com/Perl/PPCs/blob/main/README.md

Respectfully submitted by the _Perl::Types Committee_:
* Will Braswell (WBRASWELL), Co-Founder & Chairman
* Brett Estrade (OODLER), Co-Founder & 1st Vice Chairman
* Zakariyya Mughal (ZMUGHAL), Co-Founder & 2nd Vice Chairman
* John Napiorkowski (JJNAPIORK)
* Darren Duncan (DUNCAND)
* Nedzad Hrnjica (NHRNJICA)
* Rohit Manjrekar (MANJREKAR)
* Paul Millard (MAGUDAS)
* Joshua Day (HAX)
* Tyler Bird (BIRDTY)
* Robbie Hatley (HATLEYSFT)
* David Warner (WESTBASE)
* Daniel Mera (DMERA)
* Duong Vu (DVU)
* Rajan Shah (RSHAH)

## Here is a problem

Perl lacks sufficient exposure of the already-existing real natural
Perl data types for use by the programmer. This has lead to false
claims that the Perl interpreter "has no data types". This has
also lead to countless programmer-hours spent devising synthetic
or unnatural type systems that rely entirely on fuzzy data guessing
via regular expressions, etc.

Fortunately, the Perl compiler already provides the capability to
expose the underlying real native C data types which can be used
by Perl programmers to incrementally improve performance, eventually
achieving the full native speed of compiled C code. Among other
features, the Perl compiler also enables real natural data type
checking with identical behavior in both dynamic (intrepreted) mode
and static (compiled) mode.

https://metacpan.org/dist/RPerl

The data type subsystem of the Perl compiler is currently in the
process of being extracted and refactored as an independant CPAN
distribution called `Perl::Types`. This distribution provides new,
core capabilities and thus should be included in the Perl core
distribution as a "Dual-Life" module.

https://github.com/Dual-Life

## Here is the syntax that we're proposing

The Perl interpreter already has an unused slot in the grammar for
this very purpose:

`my TYPE $var;`

The Perl interpreter and the Perl compiler already provide the
basic data types to be used in the grammar slot above:

* `boolean` (`SV` when `SvIsBOOL(sv)` is true, new in 5.36)
* `integer` (`IV`)
* `number` (`NV`)
* `string` (`PV`)
* `array` (`AV`) & `arrayref` (`RV(AV)`)
* `hash` (`HV`) & `hashref` (`RV(HV)`)
* user-defined classes

Custom data structures are declared with compound or nested data
types composed from the basic types above, for example:

* `integer::arrayref`
* `integer::arrayref::arrayref`
* `integer::arrayref::hashref`
* `integer::arrayref::arrayref::hashref`
* `string::arrayref`
* `MyClass::arrayref`
* etc.

Attempting to utilize incompatible data types gives the same behavior
and same errors in both interpreted mode and compiled mode, for
example:

```
#!/usr/bin/perl
use Perl::Types;

sub squared {
{ my number $RETURN_TYPE };
( my number $base ) = @ARG;
return $base ** 2;
}

squared(2); # FINE
squared(2.3); # FINE
squared(to_number('2')); # FINE
my number $foo = 23;
squared($foo); # FINE

squared(); # ERROR ENVxx, TYPE-CHECKING MISMATCH: number value expected but ...
squared('2'); # ERROR ENVxx, TYPE-CHECKING MISMATCH: number value expected but ...
my string $bar = 'howdy';
squared($bar); # ERROR ENVxx, TYPE-CHECKING MISMATCH: number value expected but ...
squared([2]); # ERROR ENVxx, TYPE-CHECKING MISMATCH: number value expected but ...
```

The syntax for arrays and hashes is similarly straightforward:
```
sub multiply_array {
{ my number::arrayref $RETURN_TYPE };
( my integer $input_integer, my number::arrayref $input_array ) = @ARG;
my number::arrayref $output_array = [
$input_integer * $input_array->[0],
$input_integer * $input_array->[1],
$input_integer * $input_array->[2]
];
return $output_array;
}

sub multiply_hash {
{ my number::hashref $RETURN_TYPE };
( my integer $input_integer, my number::hashref $input_hash ) = @ARG;
my number::hashref $output_hash = {
a => $input_integer * $input_hash->{a},
b => $input_integer * $input_hash->{b},
c => $input_integer * $input_hash->{c}
};
return $output_hash;
}
```

## Here are the benefits of this

The primary benefit of including `Perl::Types` in the Perl core
distribution is that it will provide a greatly-needed capability
of exposing the underlying C-level data types and data structures
to every Perl programmer, so they may utilize Perl data types to
achieve a number of benefits including but not limited to:

* increased performance
* code correctness
* type safety (type checking)
* memory safety (bounds checking)
* documentation of code intent
* potential for polymorphism
* potential for derived or synthetic types

Additionally, this foundational support for enabling Perl data
types at the interpreter level will allow for the creation of
synthetic or unnatural data types and data structures to be built
on top of `Perl::Types` itself. For example, the capabilities
provided in `Perl::Types` are necessary for any effort to introduce
real natural type checking constraints related to Perl's new `class`
keyword.

## Here are potential problems

Because the Perl interpreter has already implemented both the real
natural Perl data types, as well as the required `my TYPE $var`
syntax construct, we therefore do not foresee the introduction of
any significant issues by including `Perl::Types` in the Perl core
distribution.

The largest barrier to adoption for the Perl compiler is the need
for numerous non-Perl dependencies, such as the C++ compiler and
other libraries. This barrier will be completely removed for the
`Perl::Types` distribution, due to being refactored out of the
compiler distribution and removal of all non-core dependencies.

On Behalf of the _Perl::Types Committee_,
Brett Estrade

--
ood...@cpan.org
oodl...@sdf-eu.org
SDF-EU Public Access UNIX System - http://sdfeu.org
irc.perl.org #openmp #pdl #native

G.W. Haywood via perl5-porters

unread,
Aug 16, 2023, 3:15:05 AM8/16/23
to perl5-...@perl.org
Hi there,

On Wed, 16 Aug 2023, Oodler 577 via perl5-porters wrote:

> # Proposed Perl Changes Elevator Pitch for Perl::Types
>
> This document is the first step in the Proposed Perl Changes process:
>
> https://github.com/Perl/PPCs/blob/main/README.md
> ...

I've just spent an hour trying and to all intents and purposes failing
to read this document.

Am I excluded because <browser>?

--

73,
Ged.

Darren Duncan

unread,
Aug 16, 2023, 3:30:05 AM8/16/23
to perl5-...@perl.org
On 2023-08-16 12:06 a.m., G.W. Haywood via perl5-porters wrote:
> On Wed, 16 Aug 2023, Oodler 577 via perl5-porters wrote:
>> https://github.com/Perl/PPCs/blob/main/README.md
>
> I've just spent an hour trying and to all intents and purposes failing
> to read this document.
>
> Am I excluded because <browser>?

This is a simple documentation file on Github, which is a very widely used and
presumably thoroughly tested site.

I can read the page fine on 3 different web browsers, Safari, Firefox, Chrome,
all fairly new versions.

What browser are you using, and can you try a different one? My top
recommendation is Firefox.

-- Darren Duncan

Diab Jerius

unread,
Aug 16, 2023, 3:30:06 AM8/16/23
to G.W. Haywood, perl5-...@perl.org

Arne Johannessen via perl5-porters

unread,
Aug 16, 2023, 4:30:06 AM8/16/23
to Darren Duncan, G.W. Haywood via perl5-porters
Darren Duncan <dar...@darrenduncan.net> wrote:
> On 2023-08-16 12:06 a.m., G.W. Haywood via perl5-porters wrote:
>>
>> Am I excluded because <browser>?
>
> This is a simple documentation file on Github, which is a very widely used and presumably thoroughly tested site.

Hot take: Can't be that well tested if it fails to work without JavaScript.


> What browser are you using, and can you try a different one?

`git clone https://github.com/Perl/PPCs` allows access without a browser, if necessary.


--
Arne Johannessen
<https://arne.johannessen.de/>



G.W. Haywood via perl5-porters

unread,
Aug 16, 2023, 6:15:04 AM8/16/23
to perl5-...@perl.org, Diab Jerius
Hi there,
Thank you.

That's legible, but most links to other documents appear as relative
to some unknown root and are thus inaccessible:

* [motivation.md](docs/motivation.md) - why do we want to do something
* [process.md](docs/process.md) - the initial version of the process
* [template.md](docs/template.md) - the PPC template
* [future.md](docs/future.md) - how we see the process evolving
* [others.md](docs/others.md) - what others do (or did), and what we can learn from them

--

73,
Ged.

G.W. Haywood via perl5-porters

unread,
Aug 16, 2023, 6:30:05 AM8/16/23
to perl5-...@perl.org, Darren Duncan
Hi there,

On Wed, 16 Aug 2023, Darren Duncan wrote:
> On 2023-08-16 12:06 a.m., G.W. Haywood via perl5-porters wrote:
>> On Wed, 16 Aug 2023, Oodler 577 via perl5-porters wrote:
>>> https://github.com/Perl/PPCs/blob/main/README.md
>>
>> I've just spent an hour trying and to all intents and purposes failing
>> to read this document.
>>
>> Am I excluded because <browser>?
>
> This is a simple documentation file on Github, which is a very widely used
> and presumably thoroughly tested site.

Thanks very much for your reply.

Your presumption is, I think, unjustified. I believe there was a time
when github told me my browser wasn't supported, but it doesn't say
that now. It seems sometimes things render, and sometimes they don't.
The most common problem is not this current README.md issue, but the
fact that much of the embellishment renders in Palemoon as a rotating
icon, which apparently performs no function but prevents all further
interaction with this hapless user.

> I can read the page fine on 3 different web browsers, Safari, Firefox,
> Chrome, all fairly new versions.
>
> What browser are you using,

I'm using Palemoon. The only browser addon installed is uBlock Origin
which is disabled for github.

> and can you try a different one? My top recommendation is Firefox.

I switched to Palemoon very reluctantly after using Firefox for more
than a decade when Firefox became unworkable for me. On Palemoon I'm
currently running six windows with between them about 500 open tabs;
for example I have one window more or less devoted to the RFCs with
currently just over a hundred RFCs open in separate tabs. After some
months of experimentation I chose Palemoon because it was the closest
thing to Firefox that I could find which would do what I needed to do.
I'm not in any hurry to go through all that again.

But what if I'd said it was a Braille reader?

Using a different browser isn't a realistic option, and no matter what
browser I started from, if every time somebody suggested that I use a
different browser I actually did that, I think I'd need to be running
every existing browser. My thin desktop client is a Pi4B with 8GBytes
of RAM but even that isn't enough RAM to pander to the 21st century's
bells and whistles mentality. My wife still uses Firefox, but after a
major upgrade recently she's begun to find it unbearably slow and is
currently searching for alternatives.

For three months now we haven't been able to submit a meter reading to
our electricity supplier (Eon) with either Palemoon or Firefox, and my
wife sent the supplier a revised logo, with the 'n' replaced by 'ff'.

The fact that we're even having this conversation is a symptom of an
epic failure in the processes. Remind me why HTML in the first place?

Here at least, the tools are getting in the way so badly that I'm just
going to walk away from it.

--

73,
Ged.

Felipe Gasper via perl5-porters

unread,
Aug 16, 2023, 7:00:06 AM8/16/23
to Oodler 577, perl5-...@perl.org
In all my years of writing Perl, and JS code to consume Perl APIs, the only truly vexing type problem I found was Perl’s inability to distinguish text from byte strings.

FWIW.

-FG

> On Aug 16, 2023, at 00:38, Oodler 577 via perl5-porters <perl5-...@perl.org> wrote:
>
> # Proposed Perl Changes Elevator Pitch for Perl::Types

Martijn Lievaart via perl5-porters

unread,
Aug 16, 2023, 10:00:05 AM8/16/23
to perl5-...@perl.org
Op 16-08-2023 om 11:57 schreef G.W. Haywood via perl5-porters:
> Thank you.
>
> That's legible, but most links to other documents appear as relative
> to some unknown root and are thus inaccessible:
>
> * [motivation.md](docs/motivation.md) - why do we want to do something
> * [process.md](docs/process.md) - the initial version of the process
> * [template.md](docs/template.md) - the PPC template
> * [future.md](docs/future.md) - how we see the process evolving
> * [others.md](docs/others.md) - what others do (or did), and what we
> can learn from them


The root obviously being the path to the current document, as with any
relative link.


HTH,

M4


G.W. Haywood via perl5-porters

unread,
Aug 16, 2023, 11:15:04 AM8/16/23
to Christian Walde, perl5-...@perl.org
Hi there,

Thanks very much for taking an interest in this. Good call on the subject line.

On Wed, 16 Aug 2023, Christian Walde wrote:
> On Wed, 16 Aug 2023, G.W. Haywood wrote:
>>> On Wed, 16 Aug 2023, Oodler 577 via perl5-porters wrote:
>>>>
>>>> https://github.com/Perl/PPCs/blob/main/README.md
>>
>> Am I excluded because <browser>?
>> I'm using Palemoon. ...
>
> No you ain't excluded because browser. Find attached a png of palemoon on my
> system loading the link above just fine.

I'm slightly surprised that a quarter megabyte image got past the list. :)

>> fact that much of the embellishment renders in Palemoon as a rotating icon
>
>> currently running six windows with between them about 500 open tabs;
>
> These might be connected, and i say this because i do the same thing.
>
> As a first line diagnostic, open a tab in palemoon with the link above, hit
> F12 and open the network tab in the newly opened interface, then hit F5 to
> reload the website and see if the network tab indicates any errors.

79 requests for a page of 4333.56 kbytes, 864.82 kBytes actually
transferred, a bunch of 304s for scripts, stylesheets and a single
0-byte image - all presumably cached already - but no actual errors.
The very first file transferred is README.md, of size 197.18 kbytes,
transferred 44.54 kbytes (so I guess it was compressed for the actual
transfer), response code 200. It just doesn't appear on the screen.

> A spinner getting stuck typically means that the page tried to load something
> and network or browser-internal processing issues prevented it from being
> loaded, resulting in an error that's novel to the website.
>
> Depending on what the network tab indicates, ways to redress this are as
> follows:
>
> 1. install https://addons.palemoon.org/addon/suspender/ to reduce the
> background load of open tabs

Thanks, I'll take a look at this one in any case but let's be clear,
the spinner getting stuck is *not* the issue with this particular
page. The issue is that although the document load does complete,
apart from all the window-dressing, the page is completely blank.

> 2. ensure your wifi has good connectivity if you're on wifi

Wired all the way from the cabinet up the road, British Telecom's ADSL
and Ethernet LAN. BT's length of glass fibre is, unfortunately, about
200 yards too short to reach us. (After all it is just an industrial
estate in the British midlands - the heartlands of UK manufacturing.)

> 3. inspect the network meter of your router, and if you see the outbound line
> maxed out consistently, debug your network and identify the culprit, as high
> outbound loads can block downloads

There are no issues of that sort, although if my calculation is
correct the download amplification factor is pretty impressive (the
4.3 Mbytes downloaded to get a 1799 byte file seems like x 2,400).

What version of Palemon are you using? Are you using IPv4 or IPv6?
We've noticed that sometimes websites don't seem to play well with our
IPv6 client addresses, and we've had to disable IPv6 for them. Until
now it hadn't occurred to me that github might be one of them but I'll
look into that too, even though downloading from

raw.githubusercontent.com

seems to be working fine, so I'm not holding my breath.

--

73,
Ged.

Darren Duncan

unread,
Aug 16, 2023, 5:30:04 PM8/16/23
to perl5-...@perl.org
On 2023-08-16 3:40 a.m., Felipe Gasper via perl5-porters wrote:
> In all my years of writing Perl, and JS code to consume Perl APIs, the only truly vexing type problem I found was Perl’s inability to distinguish text from byte strings.
> FWIW.
> -FG

I agree that this is very important.

The Perl 5.36 update that let us finally distinguish booleans from numbers and
text was a huge step forward. Thank you again to everyone who made that work.

I feel that a similar kind of core enhancement to the booleans one that lets us
thoroughly distinguish the intent of a string to be octets/raw versus characters
would be extremely valuable and something that I could use.

And this matter is orthogonal to the Perl::Types and Oshun proposals/discussions
but having it would be a big support for both of them, and for my independent
work on data interchange/serialization mechanisms/formats.

-- Darren Duncan

Dave Mitchell

unread,
Aug 18, 2023, 5:30:05 AM8/18/23
to Oodler 577, perl5-...@perl.org
On Wed, Aug 16, 2023 at 04:37:07AM +0000, Oodler 577 via perl5-porters wrote:
> # Proposed Perl Changes Elevator Pitch for Perl::Types
[...]
> Fortunately, the Perl compiler already provides

By "Perl compiler", do you mean RPerl?

> #!/usr/bin/perl
> use Perl::Types;
>
> sub squared {
> { my number $RETURN_TYPE };
> ( my number $base ) = @ARG;
> return $base ** 2;
> }
>

That's weird perl syntax. What's @ARG and $RETURN_TYPE? Is this something
RPerl related?

In what circumstances are these type checks carried out / enforced? Is it
just on scalar and list assignment? Or more generally? For example, does
this croak?

sub mutate { $_[0] = 'foo' }
my number $x;
mutate($x);

Speaking as a perl internals expert, can you explain to me in general
terms how Perl::Types does its thing?


--
Indomitable in retreat, invincible in advance, insufferable in victory
-- Churchill on Montgomery

Oodler 577 via perl5-porters

unread,
Aug 18, 2023, 11:15:04 PM8/18/23
to Dave Mitchell, perl5-...@perl.org
> Re: PPC Elevator Pitch for Perl::Types
> From: Dave Mitchell
> Date: August 18, 2023 09:19
> Subject: Re: PPC Elevator Pitch for Perl::Types
> Message ID: ZN83kPGe...@iabyn.com

Hi Dave, thank you for your reply. Please see our answer inline,
below.

> On Wed, Aug 16, 2023 at 04:37:07AM +0000, Oodler 577 via perl5-porters wrote:
> > # Proposed Perl Changes Elevator Pitch for Perl::Types
> [...]
> > Fortunately, the Perl compiler already provides

> By "Perl compiler", do you mean RPerl?

Yes.

> > #!/usr/bin/perl
> > use Perl::Types;
> >
> > sub squared {
> > { my number $RETURN_TYPE };
> > ( my number $base ) = @ARG;
> > return $base ** 2;
> > }
> >

> That's weird perl syntax. What's @ARG and $RETURN_TYPE? Is this something
> RPerl related?

`@ARG` is just the alias for `@_`, provided by `English.pm`.

https://perldoc.perl.org/perlvar#@ARG

https://perldoc.perl.org/English

`$RETURN_TYPE` was the simplest pure-Perl syntax we could come up
with, which allows us to specify a subroutine's return type without
changing its behavior. Can you please suggest possible pure-Perl
syntax alternatives for specifying a subroutine return type, without
requiring any changes to the existing Perl internals?

> In what circumstances are these type checks carried out / enforced? Is it
> just on scalar and list assignment? Or more generally? For example, does
> this croak?

> sub mutate { $_[0] = 'foo' }
> my number $x;
> mutate($x);

The Perl compiler currently supports type enforcement for subroutine
calls, so that is our starting point for Perl::Types. Thus, your
example above would not croak, because the subroutine does not
specify any data types for its input arguments. Type checking is
simply disabled for subroutines without input argument types.

If you added `( my number $my_arg ) = @ARG;` to the top of your
`mutate()` subroutine, then yes it would croak with a complaint
`... number value expected but undefined/null value found ...`
because you never assigned a value to `$x`. This is achieved by
inserting calls to the appropriate type-checking C macros or
functions for each typed input argument, inserted immediately
following the `@ARG` statement. So for your `mutate()` subroutine,
Perl::Types would automatically call either the `number_CHECK()`
or `number_CHECKTRACE()` macro on the value received into `$my_arg`,
which is where the croaking occurs:

https://metacpan.org/release/WBRASWELL/RPerl-7.000000/source/lib/RPerl/DataType/Number.h#L137-149

```c
// [[[ TYPE-CHECKING MACROS ]]]
#define number_CHECK(possible_number) \
(not(SvOK(possible_number)) ? \
croak("\nERROR ENV00, TYPE-CHECKING MISMATCH, CPPOPS_PERLTYPES & CPPOPS_CPPTYPES:\nnumber value expected but undefined/null value found,\ncroaking") : \
(not(SvNOKp(possible_number) || SvIOKp(possible_number)) ? \
croak("\nERROR ENV01, TYPE-CHECKING MISMATCH, CPPOPS_PERLTYPES & CPPOPS_CPPTYPES:\nnumber value expected but non-number value found,\ncroaking") : \
(void)0))
#define number_CHECKTRACE(possible_number, variable_name, subroutine_name) \
(not(SvOK(possible_number)) ? \
croak("\nERROR ENV00, TYPE-CHECKING MISMATCH, CPPOPS_PERLTYPES & CPPOPS_CPPTYPES:\nnumber value expected but undefined/null value found,\nin variable %s from subroutine %s,\ncroaking", variable_name, subroutine_name) : \
(not(SvNOKp(possible_number) || SvIOKp(possible_number)) ? \
croak("\nERROR ENV01, TYPE-CHECKING MISMATCH, CPPOPS_PERLTYPES & CPPOPS_CPPTYPES:\nnumber value expected but non-number value found,\nin variable %s from subroutine %s,\ncroaking", variable_name, subroutine_name) : \
(void)0))
```

> Speaking as a perl internals expert, can you explain to me in general
> terms how Perl::Types does its thing?

As you can see in the C macros above, we are exposing the real
native Perl data types by directly accessing the `SvOK()`, `SvIOKp()`,
and `SvNOKp()` internals. Perl::Types is not inventing its own
definition of types, it is only exposing the already-existing real
native Perl data types such as `IV`, `NV`, `PV`, etc. Real native
Perl data structures can likewise be exposed by way of the `AV`
and `HV` Perl data types, by directly accessing `SvAROKp()` and
`SvHROKp()`:

https://metacpan.org/release/WBRASWELL/RPerl-7.000000/source/lib/RPerl/DataStructure/Array/SubTypes1D.cpp#L72-118
https://metacpan.org/release/WBRASWELL/RPerl-7.000000/source/lib/RPerl/DataStructure/Hash/SubTypes1D.cpp#L92-166

```c
boolean number_arrayref_CHECK(SV* possible_number_arrayref, const boolean no_croak)
{
if ( not( SvOK(possible_number_arrayref) ) ) { CROAK_OR_RETURN(no_croak, "\nERROR ENVAVRV00, TYPE-CHECKING MISMATCH, CPPOPS_PERLTYPES & CPPOPS_CPPTYPES:\nnumber_arrayref value expected but undefined/null value found,\ncroaking") }
if ( not( SvAROKp(possible_number_arrayref) ) ) { CROAK_OR_RETURN(no_croak, "\nERROR ENVAVRV01, TYPE-CHECKING MISMATCH, CPPOPS_PERLTYPES & CPPOPS_CPPTYPES:\nnumber_arrayref value expected but non-arrayref value found,\ncroaking") }

AV* possible_number_array;
integer possible_number_array_length;
integer i;
SV** possible_number_array_element;

possible_number_array = (AV*)SvRV(possible_number_arrayref);
possible_number_array_length = av_len(possible_number_array) + 1;

for (i = 0; i < possible_number_array_length; ++i) // incrementing iteration
{
possible_number_array_element = av_fetch(possible_number_array, i, 0);

if (not(SvOK(*possible_number_array_element))) { CROAK_OR_RETURN(no_croak, "\nERROR ENVAVRV02, TYPE-CHECKING MISMATCH, CPPOPS_PERLTYPES & CPPOPS_CPPTYPES:\nnumber value expected but undefined/null value found at index %"INTEGER",\ncroaking", i) }
if (not(SvNOKp(*possible_number_array_element) || SvIOKp(*possible_number_array_element))) { CROAK_OR_RETURN(no_croak, "\nERROR ENVAVRV03, TYPE-CHECKING MISMATCH, CPPOPS_PERLTYPES & CPPOPS_CPPTYPES:\nnumber value expected but non-number value found at index %"INTEGER",\ncroaking", i) }
}

return 1;
}
```

(Please see the links above for `number_arrayref_CHECKTRACE()`,
etc.)

Type checking is currently controlled on a per-file basis using
the `TYPE_CHECKING` preprocessor directive:

https://metacpan.org/release/WBRASWELL/RPerl-7.000000/source/lib/RPerl/Test/TypeCheckingTrace/AllTypes.pm#L1-2

```perl
# [[[ PREPROCESSOR ]]]
# <<< TYPE_CHECKING: TRACE >>>
```

The `TYPE_CHECKING` directive can have a value of `OFF` for disabled,
`ON` to call the `foo_CHECK()` macros/functions, and `TRACE` to
call the `foo_CHECKTRACE()` macros/functions. The only difference
between `ON` and `TRACE` is the inclusion of the offending subroutine
and variable names for easier debugging.

Does that help answer your initial questions?

> --
> Indomitable in retreat, invincible in advance, insufferable in victory
> -- Churchill on Montgomery

Dave Mitchell

unread,
Aug 19, 2023, 3:45:05 AM8/19/23
to Oodler 577, perl5-...@perl.org
On Sat, Aug 19, 2023 at 02:56:13AM +0000, Oodler 577 via perl5-porters wrote:
> Does that help answer your initial questions?

'fraid not :-)

If I am understanding correctly, Perl::Types is intended to be something
which can be used stand-alone, independent of RPerl, and which you want to
be bundled with the perl core.

Within that context, how does adding 'use Perl::Types' at the top of a
perl (not RPerl) program do its thing? What mechanism are you using that
causes this line in a non-RPerl program to croak;

my number $x;
...
$x = 'foo'; # croak

e.g. is it a source filter, set magic attached to $x, or ...?

Also, from your reply about my mutator example not croaking by default,
this seems to imply that it's quite possible for $x to obtain a
non-numeric value under some circumstances. So, by default, what
circumstances will croak and which will silently allow $x to become
something other than a number? E.g. which of these lines croaks?

$x = 'foo';
$x =~ s/1/a/;
substr($x,0,1) = 'foo';
my $y = substr($x,0,1);

Just in general terms I'm still confused as to what effect adding
'Perl::Types' to my program will have, and how it achieves that effect.



--
A problem shared is a problem doubled.

Darren Duncan

unread,
Aug 19, 2023, 7:15:05 AM8/19/23
to perl5-...@perl.org
On 2023-08-15 9:37 p.m., Oodler 577 via perl5-porters wrote:
> # Proposed Perl Changes Elevator Pitch for Perl::Types
> ...
> Respectfully submitted by the _Perl::Types Committee_:
> ...
> * Darren Duncan (DUNCAND)

I want to state for the record that I partially disavow both this proposal and
this group.

I have also, just before writing this current message, formally departed from
the group, and asked that my name be removed from its membership list.

I joined the Perl::Types Committee about 1-2 weeks ago, when the current
incarnation was formed, when Will invited me, because I had a personal interest
in Perl type systems and felt I could benefit the Perl community through
participation in the multiple efforts under way, including this one; I had
likewise also provided feedback to Oshun, and before that Corinna.

I did provide input and feedback during the last 1-2 weeks, which I hope will
make the Perl::Types effort better for the community.

While I support some aspects of its goals, providing more direct, efficient, and
strict access to Perl's existing built-in type system for Perl developers, I
also disagree with other aspects of the initiative, including a seeming lack of
desire to compromise with others.

While my input to the group seemed to be generally appreciated, some proposals
that were more compromising in nature and respecting feedback given here, were
vocally disagreed with.

For example, I proposed using a branded namespace, such as LLPT:: (Low Level
Perl Types) for all its packages like integer/boolean/string etc to expressly
avoid conflict with other namespaces.

I decided I don't want my name associated with this endeavor as a whole, even if
I support some of its goals.

I believe that in principle the alternative Oshun proposal can provide all the
actually workable features of Perl::Types as a subset of its feature set, and do
so in a way that goes out of its way to play nice with everything else.

Oshun's built-in checks should have a set that correspond to stricter
definitions of Perl's built-in types; I'm not a stickler for their having
particular names, just that they are available. But getting into that belongs
on the Oshun Git discussions where input is generally being taken, rather than
in this perl5-porters thread.

Also, as far as I know, from the Git change history for the draft version of
this elevator pitch, Will and Brett are the only ones that actually authored it
directly, with the rest of our names being on it because we were in the group.

I was actually surprised that all the names were on this when it was submitted
to perl5-porters, I didn't expect that the Committee member list was going to be
announced, and assumed it was private.

Apparently we had all assented to it though because we saw a review of the draft
first and didn't object to its content, including the member name list.

This is partially my fault though, I had somehow glossed over the fact it
contained a full member list, so I didn't think to request that the names of
non-authors be excluded when I had the chance.

Going forward, I request that everyone treat me as if my name had never been
announced on the Perl::Types Committee member list.

Instead please treat me as my own person with my own interests and opinions,
which case by case may or may not align with particular individuals.

This says nothing about any relationships I may have with any individuals, but
just with this Committee as its own entity, and with the current elevator pitch.

Thank you.

-- Darren Duncan

Paul "LeoNerd" Evans

unread,
Aug 19, 2023, 7:45:04 AM8/19/23
to perl5-...@perl.org, Oodler 577
On Wed, 16 Aug 2023 04:37:07 +0000
Oodler 577 via perl5-porters <perl5-...@perl.org> wrote:

> # Proposed Perl Changes Elevator Pitch for Perl::Types
...

The following is my personal response, though it is shaped somewhat
along the direction that seems to agree with the PSC's feelings overall.

My short reaction to this: No.


My medium-sized reaction to this: This doesn't sound like the sort of
thing that is either a) a natural extension to the way that people
currently write Perl code, nor b) an end-goal direction that I would be
happy to see the language go in.

------

What now follows is a much longer essay explaining my reasoning for
saying the-above. It's not necessary to read this simply to get my
answer.


## A Natural Extension

When trying to design new Perl features, I am often inspired by two
other languages whose history I have followed - C and Scheme. There's
some interesting parallels. I'm not referring to technical features of
those languages, but of some interesting points of history. Both
languages are defined by a formal specification, with multiple
different implementations and users all trying to share it. ANSI C and
then C89 were both specifications that wrote down and formalized what
had been existing common practice around compilers and implementations.
The same was true for Scheme specs up to R5RS. After that, both C99 and
R6RS did something weird. They both (independently) went off in a
direction where the language spec itself tried to invent new concepts,
before they were commonly implemented or commonly used by users of
those languages. I think it's fair to say that neither spec was
well-received by either its implementors or its users. Sure both had
some good points, but in both cases the spec was found to have
over-reached, promising things that implementors didn't want to create
and users couldn't imagine they'd want. In time both were quietly
retconned. C11 mostly builds atop C89, offering as "optional" a bunch of
things that C99 offered but nobody liked. Scheme R7RS has now been
split into a "small" and a "large" model that basically builds on top
of R5RS and pretends R6 never happened.

(There's also some interesting parallel here with Perl: going up to 5,
trying to invent new things at 6, then splitting off to its own new
name while 5 continues in the hope of an eventual 7. But I digress ;) )

The point I'm trying to make here is that successful languages almost
always come out of observing what people are *actually* doing or
wanting to do but can't for lack of features, and formalizing those
behaviours into convenient concepts within the language so everyone can
operate on common terms.

Lets take a comparison here to Perl's subroutine signatures. At first,
Perl didn't have such a feature natively, but gave users the building
blocks (via the @_ array) to construct something of that nature
themselves. So eventually lots of people were writing code looking
something like

sub f { my ($x, $y, @z) = @_; ... }

When signatures were added, they didn't really add fundamentally new
abilities; they just tidied up what had been existing practice up til
that point. They allowed people to write code in a shorter, neater,
less noisy fashion, that still behaved *as if* it was written in the
longer form.

sub f ($x, $y = 123, @z) { ... }

sub f {
@_ >= 1 or die "Too few arguments";
my $x = $_[0];
my $y = @_ > 1 ? $_[1] : 123;
my @z = @_[2..$#_];
...
}

Lately we've added the //= and ||= operators to signature syntax as
well to permit people to write in signatures what they'd often write
before as stuff like `my $y = $_[1] // 123;`.

Signatures were added in order to provide a short neat concise way for
the programmer to give a standard notation for various behaviours
around creating lexicals and inspecting @_ that *they were already
doing*. Signatures have become popular and well-used precisely because
they are just a neater way to rewrite existing code.

What does this mean for a "type system"? Again, it would do well to
check what existing behaviours people are actually writing now. Almost
universally, the kinds of code people are trying to clean up and
replace are variations on a theme of "Do I like this value?" when being
passed into subroutines or methods, stored in object fields, stored in
regular lexicals, that kind of thing. In effect, where subroutine
signatures tidied up code of the form such as `my $x = shift @_`, so
too should a value constraint system tidy up code of the form
`ACCEPTABLE($_[0]) or die "Cannot accept this argument"`.

Keep that in mind in the following.

## End-Goal Direction

This brings me on to my second point. Back in 2020, I wrote a blog post
that I turned into a presentation at a conference, "Perl in 2025",
where I imagined what kind of Perl code I might be writing five years
hence. Many of the points explained in that talk have set the direction
for things I have been actively working on since then. One I've not
really looked at until you bring it up here, is that "type system".

In my talk (https://www.youtube.com/watch?v=raSRNIoUYig), somewhere
around the 25m mark, I start classifying what various folks mean out of
"type systems". There's three main categories:

1. Static code checks
I.e. Can the compiler (perl -c) tell me "this program is bad"?

2. Dynamic value assertions
I.e. Does the program abort if I give it the wrong data?

3. Compiler hints
I.e. can the runtime run faster because it knows certain
conditions will be impossible?

These categories aren't mutually exclusive of course. For example, C's
type system is very much a mix of categories 1 and 3. TypeScript adds
a category 1 system to JavaScript, and Python also has some optional
typing stuff that again mostly fits category 1.

Perl is a very dynamic language - most of the things that you can do
would violate any sense of "static safety" that category 1 would
attempt to give. Perl isn't built for "performance above all else"
anyway, and category 3 would cut off many situations where we actually
like that flexibility - e.g. being able to use overloaded objects like
bigint, bigrat, String::Tagged, etc... in place of native values. Sure,
I agree that having to check for overloading makes code like `$x + $y`
run a bit slower than if you didn't have to check that, but being able
to transparently pass bigint or bigrat values into existing code and
operate on values larger than native platform IV or NV without losing
any precision at all is a great feature to have.

For these reasons, I feel that really only category 2 is the sort of
thing that is something we can, or should, add to Perl. This is why I
bring attention to the idea that we want to automate away the kinds of
"die if I don't like this value" code that people are already writing.
That's basically what category 2 already is, just manually written out
by hand. Whatever Perl might add in future should be an automation and
standardization of that existing style of code.

Furthermore, because I feel sufficiently strongly that this style of
dynamic value constraints at runtime is the best approach to be taking,
I have tried hard to avoid the word "type" when writing about or
describing it. I've said repeatedly and I'll say again: the whole
thing is verymuch "do we like the look of this value?". The key words
here are "look" and "value". It's about dynamic values that the program
actually operates on. It's about what they look like, not what their
underlying in-memory bit-pattern representation actually is.


# A Critique of Perl::Types

With these points in mind, we are now more prepared to take a closer
look at what your Perl::Types proposal suggests. Overall it's hard to
see what real behaviour is being added by the proposal as the details
in the email are very short. The CPAN dist has almost no code, no
tests, no documentation, so it's very hard for me to guess. I therefore
can't say with 100% certainty that what you propose doesn't fit what
I'm about to explain, but from an initial read of it I find it doubtful.

Perhaps, as a starting point, someone could outline what *kind* of type
system you imagine here, with particular reference to the three
categories I outline above. To what extent does what you propose fit
into each of categories 1, 2 or 3?

## An over-sensitivity to internal data representation

Your email talks about the difference between IVs, NVs and PVs and
honestly that is a tiny internal detail of representation waaay down in
the weeds. Perl - as a language and a culture - has never really cared
about whether a number is really a number, or a string containing some
digit characters to represent it in decimal form. 10 and "10" are mostly
the same thing. Sure, the bits stored in memory are different, but what
you can do with them is the same.

Many people use this to great advantage. For example, if you write a
commandline script that takes some sort of "count" argument, you're
probably going to parse it out of the text contained in the @ARGV
array. By nature that will have arrived as text, but that's OK - it's
Perl. As long as the value looks like a number, we can use it as a
number. It would be most un-Perlish to say that text in @ARGV has to be
converted into a pure-number form just to accept commandline
processing. That kind of conversion would be more at home in languages
such as Python, which make much stronger distinctions about numbers vs.
strings.

I don't see anywhere in your proposal where you account for this; a way
to specify "This value should be usable as if it was a number". Don't
forget things like bigint and bigrat exist and can be used as numbers.
Also when thinking about strings, objects can have overloading on them
to behave like strings ((not quite as well as we'd like currently in
Perl, but that's the subject of PPC0013)).

What I would like to see is something like this; where we imagine (for
sake of current argument) that "Numerical" is something that exists -
its actual nature still to be determined.

my Numerical $n;

$n = 10; # permitted
$n = "10"; # also permitted
$n = bigint->new("10"); # also permitted

$n = "hello"; # not permitted; throws some kind of
# exception at runtime

and of course we can apply those to fields, subroutine parameters,
etc.. in the hopefully-obvious way:

class Point {
field Numerical $x;
method move(Numerical $dX) { ... }
}

sub add(Numerical $x, Numerical $y) { ... }

In all of these cases, the ability to put a value constraint on a field
or parameter is really just a shortcut to writing some "check or die"
code manually. As I tried to hammer in above - this is just an
automation of the way that people can currently write these.

class Point { field Numerical $x; ... }
class Point { field $x; ADJUST { is_Numerical($x) or die "Bad x" }
... }

sub add(Numerical $x) { ... }
sub add($x) { is_Numerical($x) or die "Bad x"; ... }

Admittedly the one on plain lexicals isn't easy to write currently, but
it's possible via a little bit of Magic. It's something I may have a
hack at at some point soon.

## An under-sensitivity to particular values

The other thing that I feel is hugely missing from Perl::Types is
further constraints of values. Whereas I basically never care if a
numerical value is an IV, NV, PV, or some overloaded object or
whatever, what I do often care about is whether it is within some
numerical range. Perhaps it has to be positive. Or positive-or-zero. Or
maybe between two bounds - perhaps a percentage only goes up to 100, or
a mix ratio only goes up to 1.0.

And of course further constraints apply a lot more than just numbers.
Maybe for a string I'd constrain a certain length, or to match a
certain regexp pattern.. or object references have to be within a
certain subclass, or have some matching value for one of their fields,
or... whatever. Whatever Perl code I could have written in my
"IS_ACCEPTABLE($param) or die ..." expression, I should be able to
express in a value constraint. I don't currently see anything like
that in your proposal. That strikes me as a big missing feature.


# What Would I Suggest Instead?

I don't feel it very useful for me to write half a book's-worth of text
as a reply that basically says "no don't do that", without suggesting
something else more preferable instead. So I'm going to end this reply
with a quick look at something I'd much rather be considering.

The module Types::Standard seems to set a standard interface for
performing "constraint checks", that fulfils much of the behaviour I
describe above. It's well-known, well-used (via the Type::Tiny module),
and used by lots of people in lots of places.

As a general shape of model (i.e. true/false assertions on "do we like
this look of this value?") it seems far more aligned with the general
shape I outline above. I've even got as far as writing a little
Object::Pad field attribute module for using these check objects on
field assignments

https://metacpan.org/pod/Object::Pad::FieldAttr::Checked

class Point {
field $x :Checked(Num);
...
}

At some point I may get around to writing a similar attribute for
regular lexical variables. I was going to allow it to apply equally to
subroutine signatures, only I discovered Perl doesn't support those
yet. Hrm. Perhaps something for us to add in 5.39...

my $x :Checked(Num);

# not yet supported
sub add($x :Checked(Num)) { ... }

It's surely not perfect. For one, the syntax needs improving - these
kinds of constraints should be upfront syntax on the fields themselves:

class Point {
field Num $x;
}

my Num $x;

sub add(Num $x) { ... }

Performance-wise it could also be made a lot better. Currently every
checker is stored as a CV pointer, so performing a constraint check
involves an entire call_sv() operation. Internally that'd need a lot of
fixing before we'd consider it for core.

There's also the question of what really is the nature of something
like "Num" in the examples above. As the code currently stands, those
are regular Perl expressions that yield checker object instances at
compiletime, to be used to invoke a `->check` method at runtime. If we
had a truely native constraint-check syntax we'd most likely want to
define what a "check" really is as something more fundamental and new
than just that. It would likely want to operate purely in the C level
in most common cases, avoiding entirely any need for evaluating Perl
expressions just to check the common standard constraints.

But that's relatively small detail on the grand scheme of things.
Overall it's going in about the right direction, and any improvements
to it wouldn't fundamentally alter this shape; just make it better at
doing what it currently does.

What it does is very extensible to more parts of Perl, of course. Once
you have constraint checks that give you a "yes/no" answer and can use
them for accepting or rejecting values at assignment time into lexicals
or fields, or invocation time on function calls (see above examples),
you start to find you can go further than that.

A set of yes/no checks allows you to define multiple dispatch on
subroutines, for example:

check Triangluar :is(Shape) where { $_->points == 3 };
check Rectangular :is(Shape) where { $_->points == 4 };
check Pentagonal :is(Shape) where { $_->points == 5 };

multi sub draw(Triangular $shape) { ... }
multi sub draw(Rectangular $shape) { ... }
multi sub draw(Pentagonal $shape) { ... }

Or perhaps to take part in match/case syntax

match($shape : is) {
case(Triangular) { say "My shape has 3 sides" }
case(Rectangular) { say "My shape has 4 sides" }
...
}

In other words: Once you come up with a good shape for this kind of
thing, you find it's applicable in a lot more places than just
parameters to functions, or field assignments in objects. It's this
sort of force-multiplier that makes good components of languages - one
idea that can be reüsed in lots of different situations.

If people are going to spend their time making "some kind of type
system", the sort of structure I explained here is much more the kind
of thing I'd like to see people making. It has great potential to reüse
existing components, it easily fits into and improves the kind of code
people are already writing and have written for years. Straight away
people will be able to see where - and why - to use this new system.

Great languages are made like Lego kits: a collection of individual
pieces that are each simple to describe, but can be combined in lots of
flexible combinations. We should aim to make good bricks.

--
Paul "LeoNerd" Evans

leo...@leonerd.org.uk | https://metacpan.org/author/PEVANS
http://www.leonerd.org.uk/ | https://www.tindie.com/stores/leonerd/

Paul "LeoNerd" Evans

unread,
Aug 19, 2023, 11:30:04 AM8/19/23
to Christian Walde, perl5-...@perl.org
On Sat, 19 Aug 2023 15:57:55 +0200
"Christian Walde" <walde.c...@gmail.com> wrote:

> > Great languages are made like Lego kits: a collection of individual
> > pieces that are each simple to describe, but can be combined in
> > lots of flexible combinations. We should aim to make good bricks.
>
> Honestly this email should be in the perl core documentation.

It's my tribute to the beginning of the R5RS spec, which begins:

"Programming languages should be designed not by piling feature on
top of feature, but by removing the weaknesses and restrictions that
make additional features appear necessary."

-- https://docs.racket-lang.org/r5rs/r5rs-std/r5rs-Z-H-3.html

Oodler 577 via perl5-porters

unread,
Aug 19, 2023, 3:00:05 PM8/19/23
to Darren Duncan, perl5-...@perl.org
You called me out here, so I am going to reply. This time on my
own behalf, Darren. I have no hard feelings, you have to make your
decisions. None of this is personal for me and should not be for
anyone else.

You're welcome back at any time. We have a very transparent and
unapologetic operation. We're not perfect, but we are striving for
virtue like all good humans; for me it is important that we work
on humilty and meekness. But perseverence and fortitude are also
very important to me. I also get it, this brand of approach makes
people very uncomfortable and is a threat. If this model proves to
be an effective way to refine Perl, then you can bet it will be
used again by us for other things; and it is my hope, emulated by
others.

If anyone is interested in being part of the Perl::Types Committee
moving forward, please let me know. We have regular meetings and
formal levels of membership depending on interest, intellectual
contributions, and actual time given. Membership works by existing
members "sponsoring" (or vouching for) existing members. Provided
you are sincerely interested in working Perl::Type and benefitting
Perl, I would be very happy to vouch for anyone who is interested
and on P5P at this time. Please send me a direct email if so.

Cheers,
Brett

PS: Certain individuals have provided useful feedback here. We are
currently reading it, and will be preparing a response (yes as a
committee). Please be patience, we are finding it does take time
to work this way. But the fruits of this approach, particularly in
this environment, are already being shown to be good. Please continue
to send your feedback. I would like to say, thousands of lines of
code already have existed for years via RPerl. You will see this
is true by visiting the provided links. It should strike you as
sufficiently real should you take some time to view the unit tests.

* Darren Duncan <dar...@darrenduncan.net> [2023-08-19 04:07:29 -0700]:
--

Oodler 577 via perl5-porters

unread,
Aug 22, 2023, 12:30:05 AM8/22/23
to Dave Mitchell, perl5-...@perl.org
> From: Dave Mitchell
> Date: August 19, 2023 07:40
> Subject: Re: PPC Elevator Pitch for Perl::Types
> Message ID: ZOBx23dm...@iabyn.com

> On Sat, Aug 19, 2023 at 02:56:13AM +0000, Oodler 577 via perl5-porters wrote:
> > Does that help answer your initial questions?

> 'fraid not :-)

Sorry, we'll keep trying our best to explain! ;-)

> If I am understanding correctly, Perl::Types is intended to be something
> which can be used stand-alone, independent of RPerl, and which you want to
> be bundled with the perl core.

Yes, that is absolutely correct.

> Within that context, how does adding 'use Perl::Types' at the top of a
> perl (not RPerl) program do its thing? What mechanism are you using that
> causes this line in a non-RPerl program to croak;

> my number $x;
> ...
> $x = 'foo'; # croak

> e.g. is it a source filter, set magic attached to $x, or ...?

Yes you are correct, the current mechanism for enabling type-checking
for subroutine calls is essentially a type of source filter. As
mentioned in our first reply:

> > The Perl compiler currently supports type enforcement for subroutine calls, so that is our starting point for Perl::Types.

This source-filter-like functionality is currently contained in
the Perl compiler's file `Class.pm` and is triggered by including
`use RPerl;` in a Perl source code file. Similarly, this functionality
will eventually be triggered by the line `use Perl::Types;` instead,
once we complete the refactoring of `Perl::Types` into its own
distribution.

You can see how the `TYPE_CHECKING` preprocessor directive is
handled, with minor differences between the `ON` and `TRACE`
settings:

https://metacpan.org/release/WBRASWELL/RPerl-7.000000/source/lib/RPerl/CompileUnit/Module/Class.pm#L673-715

```perl
if ( $CHECK eq 'ON' ) {
my $i = 0; # integer
foreach my $subroutine_argument ( @{$subroutine_arguments} ) {
# only enable type-checking for arguments of supported type;
# NEED UPGRADE: enable checking of user-defined Class types & all other remaining RPerl types
if (exists $TYPES_SUPPORTED->{$subroutine_argument->[0]}) {
$subroutine_arguments_check_code .= q{ rperltypes::} . $subroutine_argument->[0] . '_CHECK( $_[' . $i . '] );' . "\n"; # does work, hard-code all automatically-generated type-checking code to 'rperltypes::' namespace
}
$i++;
}

activate_subroutine_args_checking( $package_name, $subroutine_name, $subroutine_type, $subroutine_arguments_check_code, $module_filename_long );
$inside_subroutine = 0;
$subroutine_arguments_line = q{};
}
```

You can see that both `ON` and `TRACE` call `activate_subroutine_args_checking()`,
which is where the type-checking calls are inserted into a new subroutine,
that wraps around the original un-type-checked subroutine:

https://metacpan.org/release/WBRASWELL/RPerl-7.000000/source/lib/RPerl/CompileUnit/Module/Class.pm#L1016-1183

```perl
# re-define subroutine call to include type checking code; new header style
do
{
no strict;

# create unchecked symbol table entry for original subroutine
*{ $package_name . '::__UNCHECKED_' . $subroutine_name } = \&{ $package_name . '::' . $subroutine_name }; # short form, symbol table direct, not strict

# delete original symtab entry,
undef *{ $package_name . '::' . $subroutine_name };

# re-create new symtab entry pointing to checking code plus unchecked symtab entry
$subroutine_definition_code .=
'*' . $package_name . '::' . $subroutine_name . ' = sub { ' .
$subroutine_definition_diag_code .
($subroutine_arguments_check_code or "\n") .
' return ' . $package_name . '::__UNCHECKED_' . $subroutine_name . '(@ARG);' . "\n" . '};';

# create new checked symtab entries, for use by Exporter
$check_code_subroutine_name = $package_name . '::__CHECK_CODE_' . $subroutine_name;
$subroutine_definition_code .= "\n" . '*' . $package_name . '::__CHECKED_' . $subroutine_name . ' = \&' . $package_name . '::' . $subroutine_name . "\n" . ';';

$subroutine_definition_code .= "\n" . '*' . $check_code_subroutine_name . ' = sub {' . "\n" . ' my $retval ' . q{ =<<'EOF';} . "\n" . $subroutine_arguments_check_code . "\n" . 'EOF' . "\n" . '};' . "\n";
};

eval($subroutine_definition_code) or (RPerl::diag('ERROR ECOPR02, PRE-PROCESSOR: Possible failure to enable type checking for subroutine ' . $package_name . '::' . $subroutine_name . '(),' . "\n" . $EVAL_ERROR . "\n" . 'not croaking'));
if ($EVAL_ERROR) { croak 'ERROR ECOPR03, PRE-PROCESSOR: Failed to enable type checking for subroutine ' . $package_name . '::' . $subroutine_name . '(),' . "\n" . $EVAL_ERROR . "\n" . 'croaking'; }
```

Thus, any call to your example `mutate()` subroutine would actually
end up calling the new wrapper subroutine instead, which would
start off by type-checking the input argument(s) before proceeding
to run the original `mutate()` code. (As mentioned before, this
would require adding `( my number $my_arg ) = @ARG;` to the top of
`mutate()`, so that `activate_subroutine_args_checking()` knows to
insert a call to `number_CHECK()` or `number_CHECKTRACE()`.)

We can enable type-checking for the subroutine return values by
simply extending this same `activate_subroutine_args_checking()`
to include a call to the appropriate `foo_CHECK()` or `foo_CHECKTRACE()`
right before returning back to the original caller.

Regarding your `my number $x; $x = 'foo';` example, this will
require the use of a `tie` or similar mechanism to intercept every
modification of `$x`, inserting a call to `number_CHECK()` or
`number_CHECKTRACE()` as previously described. In the past, we
have always simply allowed the C(++) compiler to provide this
functionality for us; however, this will have to be explicitly
implemented when `Perl::Types` is refactored into its own distribution.
Arbitrarily-nested data structures (arrays and/or hashes) can be
recursively type-checked using the same `tie` approach, intercepting
any modifications to internal elements and calling `foo_CHECK()`
or `foo_CHECKTRACE()` for each change.

> Also, from your reply about my mutator example not croaking by default,
> this seems to imply that it's quite possible for $x to obtain a
> non-numeric value under some circumstances. So, by default, what
> circumstances will croak and which will silently allow $x to become
> something other than a number? E.g. which of these lines croaks?

> $x = 'foo';
> $x =~ s/1/a/;
> substr($x,0,1) = 'foo';
> my $y = substr($x,0,1);

Once the above-mentioned `tie` functionality is implemented, then
all four of the lines above would potentially give an error if
attempting to store a non-`number` value into the `number`-typed
`$x` variable.

> Just in general terms I'm still confused as to what effect adding
> 'Perl::Types' to my program will have, and how it achieves that effect.

If you set `TYPE_CHECKING` to `OFF` and don't use the Perl compiler,
then `use Perl::Types;` will not have any effect other than allowing
you to use the Perl data types (and their associated helper
subroutines), thereby improving the readability of your code.

If you set `TYPE_CHECKING` to `ON` or `TRACE` (default) and don't
use the Perl compiler, then `use Perl::Types;` will utilize the
source filter mechanism for type-checking errors on subroutine
entry and/or exit, and will also utilize the `tie` mechanism for
type-checking errors on variable modification, thereby improving
the correctness of your code.

If you set `TYPE_CHECKING` to `ON` or `TRACE` (default) and do use
the Perl compiler, then `use Perl::Types;` will utilize the C(++)
compiler for type-checking errors on subroutine entry and/or exit,
as well as variable modification, thereby improving the runtime
performance of your code.

So, as mentioned in the original Elevator Pitch, we can "utilize
Perl data types to achieve a number of benefits including but not
limited to":

* increased performance
* code correctness
* type safety (type checking)
* memory safety (bounds checking)
* documentation of code intent
* potential for polymorphism
* potential for derived or synthetic types

Currently, the Perl compiler has well over 4K individual test cases,
a large number of which relate to the Perl data type system. The
exact number of tests which will be moved from the Perl compiler
into `Perl::Types` will be determined when the refactoring process
is complete.

https://metacpan.org/release/WBRASWELL/RPerl-7.000000/source/t

https://metacpan.org/release/WBRASWELL/RPerl-7.000000/source/lib/RPerl/Test

Are we making progress toward answering your initial questions?

Dave Mitchell

unread,
Aug 22, 2023, 6:15:03 AM8/22/23
to Oodler 577, perl5-...@perl.org
On Tue, Aug 22, 2023 at 04:19:04AM +0000, Oodler 577 via perl5-porters wrote:
> Yes you are correct, the current mechanism for enabling type-checking
> for subroutine calls is essentially a type of source filter. As
> mentioned in our first reply:
>
> > > The Perl compiler currently supports type enforcement for subroutine calls, so that is our starting point for Perl::Types.
>
> This source-filter-like functionality is currently contained in
> the Perl compiler's file `Class.pm`

So just for the avoidance of doubt, is the proposal that Perl::Types,
when running in a perl (rather than RPerl) environment, will use perl's
actual source filter mechanism, or that it will use some other
"essentially a type of source filter" thing?

If the latter, please expand.

If the former, note that we generally regard the perl source filter
mechanism as deeply flawed, and wouldn't recommend its use in production
code. The basic problem comes down to the old mantra that "only perl can
parse Perl". A source filter may correctly parse the source 99.9% of the
time, but on those 0.1% occasions, it will get something wrong. Maybe it
will get the start of a // operator confused with the start of a pattern.
Or maybe it will trip over some complex code embeded into a pattern:
/...(?{ $x = '/'; }) .../. Or whatever. At that point, code will get
injected at the wrong point into the source, and the end user gets a
compile error from code that isn't even in their source, which is
completely mystifying and hard to debug.

Switch.pm used source filters, and it was the cause of an endless stream
of tickets. It was eventually deprecated and removed from core in 5.14.0.

> Regarding your `my number $x; $x = 'foo';` example, this will
> require the use of a `tie` or similar mechanism

Again, this is very vague. Do you actually mean perl's tie / magic
mechanism? If not, what "similar mechanism" are you proposing to use?

The problem with using actual ties, is that they make the variable very
slow, even if the actual tie methods such as FETCH() are XS code. That's
because a lot of code paths in the perl interpreter have optimisations for
non-magic values. For example, look at pp_add() in pp_hot.c in the perl
source. This implements perl's '+' operator. Obviously in general the two
operands can be anything - ints, ,nums, strings, magic values, overloaded
objects etc, and mixtures thereof. But in pp_add(), the first thing it
does it check the flags of the two operands, and says:

If they are both non magical and non ref, and if both are either
simple ints or simple nums, then just add the two values, check they
haven't overflowed, set the return value and return. Otherwise go
through the complex 200-lines-of-code path which handles magic, mixed
types etc.

So if, for example, an integer variable was marked with get magic, it
would become a lot slower when being added. Similar considerations apply
in many places.

Also, once tie magic starts being applied to arrays and hashes, you start
to hit edges cases. It's very had to make a tied aggregate behave *exactly*
like a plain array/hash in all circumstances, even ignoring the slowdown.

> So, as mentioned in the original Elevator Pitch, we can "utilize
> Perl data types to achieve a number of benefits including but not
> limited to":
>
> * increased performance

So how would you get increased performance? I've already pointed out that
magic tends to slow things down, and the cost of calling a check routine
will slow things down even further.

> * memory safety (bounds checking)

Can you give an example of where currently perl isn't memory safe, but
Perl::Types would make it so?

> * potential for polymorphism

Please explain further.

Ok, that was the technical side of things. Now on to the policy side.
20 years or so ago, perl went through a phase of adding lots of 'useful'
modules to the perl core. This was widely seen as a mistake.

First, it made a particular module seem to be officially endorsed.
Hypothetically, "among several XML parser modules, we chosen this one as
the best and the one you should use". When design flaws in XML::Parser
(say) are discovered, and the general recommendation is to use
XML::BetterParser instead, XML::Parser is still sitting in the perl core
getting an unfair endorsement. And removing it from core is hard, because
now lots of people used it, and they're using it because, well, we
endorsed it!

Second, if modules stop being actively maintained by their author(s) for
whatever reason, then suddenly we become responsible for maintaining it.
It's enough work just maintaining the core perl interpreter, without
taking on extra responsibilities.

Third, in these days of package managers etc, it's relatively easy for
people to install the CPAN modules they want. They will also get the
newest and best version by default, rather than using the old buggy version
bundled with perl. So there is less good reason to bundle a package with
perl.

So these days the policy is not to bundle CPAN modules with perl unless
they are necessary, usually because they are needed as part of the tool
chain. There have been very few new modules added to the perl core in the
last 15 years or so that are capable of acting as standalone CPAN
distributions instead.

So the short answer is that even if Perl::Types really appealed to us, it
is very unlikely that we would agree to bundle it. And I think we're
far from a consensus yet that it appeals.

On a purely individual note, I am finding Perl::Types very unappealing so
far.

--
I took leave and went to hear Mrs Turner's daughter play on the harpsicon,
but Lord, it was enough to make any man sick to hear her; yet I was forced
to commend her highly.
-- The Diary of Samuel Pepys, 1 May 1663

Oodler 577 via perl5-porters

unread,
Aug 22, 2023, 1:00:05 PM8/22/23
to Dave Mitchell, perl5-...@perl.org
* Dave Mitchell <da...@iabyn.com> [2023-08-22 11:02:53 +0100]:

First, thank you for the reply. I got to your conclusion and understand
your stance. I'd like to still address a few techincal things inline.

> On Tue, Aug 22, 2023 at 04:19:04AM +0000, Oodler 577 via perl5-porters wrote:
> > Yes you are correct, the current mechanism for enabling type-checking
> > for subroutine calls is essentially a type of source filter. As
> > mentioned in our first reply:
> >
> > > > The Perl compiler currently supports type enforcement for subroutine calls, so that is our starting point for Perl::Types.
> >
> > This source-filter-like functionality is currently contained in
> > the Perl compiler's file `Class.pm`
>
> So just for the avoidance of doubt, is the proposal that Perl::Types,
> when running in a perl (rather than RPerl) environment, will use perl's
> actual source filter mechanism, or that it will use some other
> "essentially a type of source filter" thing?

Yes, it uses a source filter to start. Lots of things use source filters,
just like lots of things other parts of Perl. Short of carrying along
patches to core, I am not sure how you would really hook into the process
here.

>
> If the latter, please expand.
>
> If the former, note that we generally regard the perl source filter
> mechanism as deeply flawed, and wouldn't recommend its use in production
> code. The basic problem comes down to the old mantra that "only perl can
> parse Perl". A source filter may correctly parse the source 99.9% of the
> time, but on those 0.1% occasions, it will get something wrong. Maybe it
> will get the start of a // operator confused with the start of a pattern.
> Or maybe it will trip over some complex code embeded into a pattern:
> /...(?{ $x = '/'; }) .../. Or whatever. At that point, code will get
> injected at the wrong point into the source, and the end user gets a
> compile error from code that isn't even in their source, which is
> completely mystifying and hard to debug.
>
> Switch.pm used source filters, and it was the cause of an endless stream
> of tickets. It was eventually deprecated and removed from core in 5.14.0.

Understood.

>
> > Regarding your `my number $x; $x = 'foo';` example, this will
> > require the use of a `tie` or similar mechanism
>
> Again, this is very vague. Do you actually mean perl's tie / magic
> mechanism? If not, what "similar mechanism" are you proposing to use?
>

It was an speculative answer to how we'd do something. It is not currently
possible so we simply do not know.

> The problem with using actual ties, is that they make the variable very
> slow, even if the actual tie methods such as FETCH() are XS code. That's

> because a lot of code paths in the perl interpreter have optimisations for
> non-magic values. For example, look at pp_add() in pp_hot.c in the perl
> source. This implements perl's '+' operator. Obviously in general the two
> operands can be anything - ints, ,nums, strings, magic values, overloaded
> objects etc, and mixtures thereof. But in pp_add(), the first thing it
> does it check the flags of the two operands, and says:
>
> If they are both non magical and non ref, and if both are either
> simple ints or simple nums, then just add the two values, check they
> haven't overflowed, set the return value and return. Otherwise go
> through the complex 200-lines-of-code path which handles magic, mixed
> types etc.
>
> So if, for example, an integer variable was marked with get magic, it
> would become a lot slower when being added. Similar considerations apply
> in many places.
>
> Also, once tie magic starts being applied to arrays and hashes, you start
> to hit edges cases. It's very had to make a tied aggregate behave *exactly*
> like a plain array/hash in all circumstances, even ignoring the slowdown.

Again, what recourse do we have? This is the mechanism by which perl gives
us ways to "implement" our own high level data types (SCALAR, HASH, ARRAY).

This is and the source filter being our only options to hook into fundamental
perl "things" is exactly the pain points we as a community need for there
to be some fundamental improvements in. Perhaps through this effort there
will be some motivation to add a more reliable stage that in the past was
only able to be achieved via filters. And with `tie`, it'd be super if there
was a "better" way to Tie there is not. This is a good role for core developers
to fill.

It is the role of the core development to provide proper programming interfaces
for external parties to propose improvements or integrations without dealing
with gobs of very tedious magic; Perl provides these things currently in 3
fundamental ways:

* source filters
* tie interfaces for SCALAR, ARRAY, HASH
* subroutine prototypes (which are IMO great for creating "keywords" UX)

We've asked before, and we will ask again: what mechanism would you suggest;
and if it doesn't exist or isn't mature enough, what changes would be required
to core to more cleanly/appropriately handle what it is we WANT to do here?
Hiring core developers and internal process people is not an option of us,
we're just volunteers like most, with limited time and zero money to throw at
this.

>
> > So, as mentioned in the original Elevator Pitch, we can "utilize
> > Perl data types to achieve a number of benefits including but not
> > limited to":
> >
> > * increased performance
>
> So how would you get increased performance? I've already pointed out that
> magic tends to slow things down, and the cost of calling a check routine
> will slow things down even further.

Performance increased for type checking because we're taking advantage of the
native type checking in the underlying C or C++, give the source filters enable
more or less a "source to source" translation in differing degrees. This is
in contrast to, e.g., creating a framework that simply allows one to apply
regular expressions all over the place. On one hand regexps are slow, on the
otherhand, we still submit - what options do we really have?

It is also important to get this out front, performance does matter; any costs
for setting up the types constraints should be able to be amortized over the
lifetime of the running program to justify its use. Just like one can make
a program run arbitrarily fast if it is not "correct", it can also become
unacceptibly slow if there is too much overhead in the set up. It's the same
trade off we all see every day in other programming projects. It's no different
here.

So performance is absolution a critical point to consider - be it the overhead
induced but the constraints or the benefits of using real (as in C or C++) based
types and checking, which is where this step actually belongs.

>
> > * memory safety (bounds checking)
>
> Can you give an example of where currently perl isn't memory safe, but
> Perl::Types would make it so?

Again, this leverages the underlying C or C++ data structures and capabilities
provided by these compilers and runtimes. It's all about passing it to
the right level. In our case, it is the fundamental C or C++ data type capabilities
present in the compiler and in their runtimes.

>
> > * potential for polymorphism
>
> Please explain further.

The same way it's facilitated everywhere, by dispatching on what the programmer
is passing into the function - in this case, based on real types.

>
> Ok, that was the technical side of things. Now on to the policy side.
> 20 years or so ago, perl went through a phase of adding lots of 'useful'
> modules to the perl core. This was widely seen as a mistake.
>
> First, it made a particular module seem to be officially endorsed.
> Hypothetically, "among several XML parser modules, we chosen this one as
> the best and the one you should use". When design flaws in XML::Parser
> (say) are discovered, and the general recommendation is to use
> XML::BetterParser instead, XML::Parser is still sitting in the perl core
> getting an unfair endorsement. And removing it from core is hard, because
> now lots of people used it, and they're using it because, well, we
> endorsed it!

Are you suggesting some prudence be applied in endorsing one thing over another?
What is the process in place for vetting such modules or subsystems? It is
a sticky situation, i.e., vouching for things.

>
> Second, if modules stop being actively maintained by their author(s) for
> whatever reason, then suddenly we become responsible for maintaining it.
> It's enough work just maintaining the core perl interpreter, without
> taking on extra responsibilities.

This is already an issue for a lot of things and for a lot of people, literally
anywhere in tech.

>
> Third, in these days of package managers etc, it's relatively easy for
> people to install the CPAN modules they want. They will also get the
> newest and best version by default, rather than using the old buggy version
> bundled with perl. So there is less good reason to bundle a package with
> perl.

This is a fair point.

>
> So these days the policy is not to bundle CPAN modules with perl unless
> they are necessary, usually because they are needed as part of the tool
> chain. There have been very few new modules added to the perl core in the
> last 15 years or so that are capable of acting as standalone CPAN
> distributions instead.

Fair enough. I'd like to ask, what recourse do we have to hook into the perl
interpreter in the way that we are, if not to use the limited options present
in perl? Criticizing source filters and any mention of tie is not fair because
that's all we have. The alternative is also not feasible or fair. So what
do you suggest we do here?

>
> So the short answer is that even if Perl::Types really appealed to us, it
> is very unlikely that we would agree to bundle it. And I think we're
> far from a consensus yet that it appeals.
>
> On a purely individual note, I am finding Perl::Types very unappealing so
> far.

Fair enough, thank you for your time in replying. What technical avenue would
you take if you were in our situation, knowing as much as you know and having
taken the time to understand what we are doing here? Like I said above, beyond
source filters and tie, perl doesn't give us many options that don't include
paying a core developer (or more) to incrementally work on the support necessary
to get this working "fast" or "reliably". Because at the end of the day, that's
what it is going to take - a way to work on both sides of the process in order
to simultaneously deliver an advanced Perl module that is unincumbered by the
traditional limitations and dirth of options to hook deeply into what magick
is happening inside of the perl interpreter. And keep in mind, your reply here
will not just help us.

Thank you again.

Cheers,
Brett

>
> --
> I took leave and went to hear Mrs Turner's daughter play on the harpsicon,
> but Lord, it was enough to make any man sick to hear her; yet I was forced
> to commend her highly.
> -- The Diary of Samuel Pepys, 1 May 1663

--

Paul "LeoNerd" Evans

unread,
Aug 22, 2023, 3:15:05 PM8/22/23
to perl5-...@perl.org, Oodler 577
On Tue, 22 Aug 2023 18:45:44 +0000
Oodler 577 via perl5-porters <perl5-...@perl.org> wrote:

> > I wonder if you are not aware of the keyword plugging system,
> > available since 5.14?
> > It's used extensively by modules like List::Keywords and
> > Object::Pad as ways to prototype new functionality that could
> > eventually be brought into core (and indeed some of it has been,
> > e.g. via Corinna).
>
> Thank you, we had not looked at this but will.

It's very powerful; particularly as exposed by XS::Parse::Keyword and
in some cases XS::Parse::Sublike.

With it I've been able to implement:

* async/await syntax
https://metacpan.org/pod/Future::AsyncAwait

* real object syntax
https://metacpan.org/pod/Object::Pad

* real try/catch syntax (that became core's feature 'try')
https://metacpan.org/pod/Syntax::Keyword::Try

* real match/case syntax
https://metacpan.org/pod/Syntax::Keyword::Match

All of these things are in use right now today in various real
systems, real companies actually using this lot for real production
work.

They all play together, because they're not silly "lets rewrite the
source code with a regexp" trickery; they're properly integrated into
the parser in a properly reëntrant way. E.g. observe the way you can
put a match/case inside a try/catch block in an `async method` of a
class. Of particular note I want to draw attention to the fact that
combining `async` from Future::AsyncAwait and `method` from Object::Pad
works just fine despite the fact that neither module knows about the
other. When I wrote about programming languages being like Lego sets,
this is precisely the sort of thing I mean.


In addition at Perl v5.38 we added another mechanism for defining new
infix operators; so now while we're getting rid of smartmatch we can
continue to experiment with better replacements for it.

https://metacpan.org/pod/Syntax::Operator::Equ

https://metacpan.org/pod/Syntax::Operator::Identical

https://metacpan.org/pod/Syntax::Operator::Matches

and again - these all play together just fine. You can use an `equ` or
`=:=` operator inside match/case inside try/catch inside ... I think my
point is clear here.

These are the core-supported mechanisms we've been using for the past
decade to experiment with new syntax and new ideas that we eventually
bring into the core language.

Oodler 577 via perl5-porters

unread,
Aug 22, 2023, 6:15:05 PM8/22/23
to Christian Walde, Ovid, Oodler 577 via perl5-porters, Dave Mitchell
* Christian Walde <walde.c...@gmail.com> [2023-08-22 23:09:09 +0200]:

> On Tue, 22 Aug 2023 20:43:03 +0200, Oodler 577 via perl5-porters <perl5-...@perl.org> wrote:
>
> > vaporware
>
> ovid never used that word.

I am going to take your word for it, but I believe this statement
is correct in the literal sense.

>
> ovid merely pointed out the basic fact that you have provided no code that
> is executable on the official perl distribution
>
> if you have it, please provide
>
>
>
> it is also notable that the non-functional code you DO have on CPAN
> proposes to provide a string.pm which would violate PAUSE perms, as:
>
> $ cpanm string
> --> Working on string
> Fetching http://www.cpan.org/authors/id/A/AB/ABERGMAN/types-0.05.tar.gz ... OK
>
> something which you have steadfastly refused reply to in any fashion,
> which makes one wonder

Have you inspected the source code of types.pm"?

It is a 21 year old CPAN squatter package that contains the following code:
( direct link, https://metacpan.org/dist/types/source/lib/types.pm):

Note via CPAN, types.pm provides:

* float in lib/types.pm
* int in lib/types.pm
* number in lib/types.pm
* string in lib/types.pm
* unknown in lib/types.pm

And the code, which is unfortunate:

package types;
...
package unknown;
our $dummy = 1;
package int;
our $dummy = 1;
sub check {
return 0 if($_[0] eq 'int' && ($_[1] ne 'number' && $_[1] ne 'int'));
return 1;
}
package float;
use base qw(int);
sub check {
return 0 if($_[1] eq 'string');
return 1;
}
our $dummy = 1;
package number;
use base qw(float);
sub check {
return 0 if($_[1] eq 'string');
return 1;
}
our $dummy = 1;
package string;
use base qw(number);
sub check { return 1};
1;
__END__

And that's just the facts. "Playing nice" with a clear case of CPAN squatting
is hard to do. What do you suggest the path forward is for this pickle?

Cheers,
Brett

>
> --
> With regards,
> Christian Walde

--

Oodler 577 via perl5-porters

unread,
Aug 22, 2023, 10:30:04 PM8/22/23
to Christian Walde, Leon Timmermans, Ovid, perl5-porters, Dave Mitchell
* Christian Walde <walde.c...@gmail.com> [2023-08-23 00:53:12 +0200]:

> On Wed, 23 Aug 2023 00:37:20 +0200, Oodler 577 <oodl...@sdf-eu.org> wrote:
>
> > * Leon Timmermans <faw...@gmail.com> [2023-08-23 00:29:39 +0200]:
> >
> > > On Wed, Aug 23, 2023 at 12:22?AM Christian Walde <walde.c...@gmail.com>
> > > wrote:
> > >
> > > > that said: is there a known pause policy regarding your identified
> > > > behavior of squatting?
> > >
> > > «Perl reserves all lowercase namespaces for pragmas. That doesn't mean you
> > > can't write a pragma, but you should get the blessing of p5p (
> > > perl5-...@perl.org).» [1]
>
> that is a quite different thing from a squatting policy, but very applicable here, thanks leon :)
>
> > Or as it were, for 21 years, PAUSE.
>
> what does this mean?

I didn't think that p5p controlled CPAN, PAUSE Admins (or whatever they are called) do.

>
> > > So there is a contingency policy for namespaces like these, though I don't
> > > think we've ever used it.
> >
> > Sure let me know when you do something about types.pm.
>
> the order of operations here is somewhat different
>
> optimally you would've presented a proposal, gained concensus on it, and with agreement have uploaded a distribution to CPAN, thus grabbing the namespaces will did already grab ( https://pause.perl.org/pause/authenquery?ACTION=peek_perms&pause99_peek_perms_by=a&pause99_peek_perms_query=wbraswell&pause99_peek_perms_sub=Submit )
>
> (you did not do that, you just grabbed them without asking anyone)
>
> then, as well with said concensus, contacted pause admins to enact said concensus on the permissions of items conflicting with yours
>
> if you are asking for pre-concensus unilateral action, then your perl-types dist would currently also be a target
>
> otherwise you will need to ask for this to be enacted, and once concensus has given the go-ahead, you will receive the appropriate replies

Your turn to explain what you're trying to tell me.

Darren Duncan

unread,
Aug 22, 2023, 11:00:04 PM8/22/23
to perl5-...@perl.org
On 2023-08-22 11:43 a.m., Oodler 577 via perl5-porters wrote:
> ... your DbC efforts
> (which btw do not conflict with Perl::Types, a point we've made).
> Perhaps you can show where Perl::Types, as we've demonstrated would
> conflict with Oshun. I am not suggesting they are directly composable,
> but Perl::Types could definitely assist you where otherwise you'd
> just be using regular expressions everywhere (behind some sugar,
> of course).

That last thing you said about "otherwise you'd just be using regular
expressions everywhere" seems like an unfounded assumption to me.

While Perl::Types could serve as a foundation for Oshun, there's also no reason
at all that an Oshun implementation couldn't be written against Perl directly
AND Oshun would use exactly the same methods Perl::Types would to access the
"real" Perl type system directly and NOT using regular expressions.

It is true that some other type implementations in Perl use regular expressions,
but Oshun is a design spec for user-visible syntax and behavior, and there's no
reason at all it would necessarily be implemented with regular expressions.

In fact I would assume the opposite, that an Oshun implementation being more
modern would attach to core Perl very closely and exploit directly everything
that Perl::Types would, and have the same performance potential.

I would expect Oshun to follow the same kind of path Corinna did, which yielded
a very tight and efficient implementation in principle.

-- Darren Duncan

Oodler 577 via perl5-porters

unread,
Aug 22, 2023, 11:30:06 PM8/22/23
to Darren Duncan, perl5-...@perl.org
* Darren Duncan <dar...@darrenduncan.net> [2023-08-22 19:44:50 -0700]:
Why would you expect that?

Cheers,
Brett

>
> -- Darren Duncan
>

--

Darren Duncan

unread,
Aug 22, 2023, 11:45:04 PM8/22/23
to perl5-...@perl.org
On 2023-08-22 8:13 p.m., Oodler 577 via perl5-porters wrote:
>> I would expect Oshun to follow the same kind of path Corinna did, which
>> yielded a very tight and efficient implementation in principle.
>
> Why would you expect that?

I would expect Oshun to not use regular expressions to evaluate fundamental
types because that is the best solution. If Perl::Types can find a better way
than using regular expressions, then Oshun can apply the same better solution
directly as well. Why would this not be a reasonable assumption?

-- Darren Duncan

Oodler 577 via perl5-porters

unread,
Aug 23, 2023, 12:30:05 AM8/23/23
to Darren Duncan, perl5-...@perl.org
* Darren Duncan <dar...@darrenduncan.net> [2023-08-22 20:29:38 -0700]:
I still don't follow. It's okay, I know poeple are dead sick of this thread.

Oodler 577 via perl5-porters

unread,
Sep 2, 2023, 12:15:05 AM9/2/23
to Dave Mitchell, perl5-...@perl.org
> Re: PPC Elevator Pitch for Perl::Types
> Thread Previous | Thread Next
> From: Dave Mitchell
> Date: August 22, 2023 10:03
> Subject: Re: PPC Elevator Pitch for Perl::Types
> Message ID: ZOSHzZ2S...@iabyn.com

> On Tue, Aug 22, 2023 at 04:19:04AM +0000, Oodler 577 via perl5-porters wrote:
> > Yes you are correct, the current mechanism for enabling type-checking
> > for subroutine calls is essentially a type of source filter. As
> > mentioned in our first reply:
> >
> > > > The Perl compiler currently supports type enforcement for subroutine calls, so that is our starting point for Perl::Types.
> >
> > This source-filter-like functionality is currently contained in
> > the Perl compiler's file `Class.pm`

> So just for the avoidance of doubt, is the proposal that Perl::Types,
> when running in a perl (rather than RPerl) environment, will use perl's
> actual source filter mechanism, or that it will use some other
> "essentially a type of source filter" thing?

> If the latter, please expand.

It is not an actual source filter as documented in `perlfilter`,
although it is the same general concept. As mentioned in the
previous response, _"this source-filter-like functionality is
currently contained in the Perl compiler's file `Class.pm` and is
triggered by including `use RPerl;` in a Perl source code file."_
You can see the filter-like implementation in the link and code
snippet from our last response:

https://metacpan.org/release/WBRASWELL/RPerl-7.000000/source/lib/RPerl/CompileUnit/Module/Class.pm#L673-715

```perl
if ( $CHECK eq 'ON' ) {
my $i = 0; # integer
foreach my $subroutine_argument ( @{$subroutine_arguments} ) {
# only enable type-checking for arguments of supported type;
# NEED UPGRADE: enable checking of user-defined Class types & all other remaining RPerl types
if (exists $TYPES_SUPPORTED->{$subroutine_argument->[0]}) {
$subroutine_arguments_check_code .= q{ rperltypes::} . $subroutine_argument->[0] . '_CHECK( $_[' . $i . '] );' . "\n"; # does work, hard-code all automatically-generated type-checking code to 'rperltypes::' namespace
}
$i++;
}

activate_subroutine_args_checking( $package_name, $subroutine_name, $subroutine_type, $subroutine_arguments_check_code, $module_filename_long );
$inside_subroutine = 0;
$subroutine_arguments_line = q{};
}
```

As mentioned, _"you can see that both `ON` and `TRACE` call
`activate_subroutine_args_checking()`, which is where the type-checking
calls are inserted into a new subroutine, that wraps around the
original un-type-checked subroutine"_:

https://metacpan.org/release/WBRASWELL/RPerl-7.000000/source/lib/RPerl/CompileUnit/Module/Class.pm#L1016-1183

```perl
# re-define subroutine call to include type checking code; new header style
do
{
no strict;

# create unchecked symbol table entry for original subroutine
*{ $package_name . '::__UNCHECKED_' . $subroutine_name } = \&{ $package_name . '::' . $subroutine_name }; # short form, symbol table direct, not strict

# delete original symtab entry,
undef *{ $package_name . '::' . $subroutine_name };

# re-create new symtab entry pointing to checking code plus unchecked symtab entry
$subroutine_definition_code .=
'*' . $package_name . '::' . $subroutine_name . ' = sub { ' .
$subroutine_definition_diag_code .
($subroutine_arguments_check_code or "\n") .
' return ' . $package_name . '::__UNCHECKED_' . $subroutine_name . '(@ARG);' . "\n" . '};';

# create new checked symtab entries, for use by Exporter
$check_code_subroutine_name = $package_name . '::__CHECK_CODE_' . $subroutine_name;
$subroutine_definition_code .= "\n" . '*' . $package_name . '::__CHECKED_' . $subroutine_name . ' = \&' . $package_name . '::' . $subroutine_name . "\n" . ';';

$subroutine_definition_code .= "\n" . '*' . $check_code_subroutine_name . ' = sub {' . "\n" . ' my $retval ' . q{ =<<'EOF';} . "\n" . $subroutine_arguments_check_code . "\n" . 'EOF' . "\n" . '};' . "\n";
};

eval($subroutine_definition_code) or (RPerl::diag('ERROR ECOPR02, PRE-PROCESSOR: Possible failure to enable type checking for subroutine ' . $package_name . '::' . $subroutine_name . '(),' . "\n" . $EVAL_ERROR . "\n" . 'not croaking'));
if ($EVAL_ERROR) { croak 'ERROR ECOPR03, PRE-PROCESSOR: Failed to enable type checking for subroutine ' . $package_name . '::' . $subroutine_name . '(),' . "\n" . $EVAL_ERROR . "\n" . 'croaking'; }
```

> If the former, note that we generally regard the perl source filter
> mechanism as deeply flawed, and wouldn't recommend its use in production
> code. The basic problem comes down to the old mantra that "only perl can
> parse Perl". A source filter may correctly parse the source 99.9% of the
> time, but on those 0.1% occasions, it will get something wrong. Maybe it
> will get the start of a // operator confused with the start of a pattern.
> Or maybe it will trip over some complex code embeded into a pattern:
> /...(?{ $x = '/'; }) .../. Or whatever. At that point, code will get
> injected at the wrong point into the source, and the end user gets a
> compile error from code that isn't even in their source, which is
> completely mystifying and hard to debug.

> Switch.pm used source filters, and it was the cause of an endless stream
> of tickets. It was eventually deprecated and removed from core in 5.14.0.

Yes we agree this could be a source of problems.

Rather than using a source filter (or similar mechanism as detailed
above), can you please suggest a more stable and reliable
implementation?

> > Regarding your `my number $x; $x = 'foo';` example, this will
> > require the use of a `tie` or similar mechanism

> Again, this is very vague. Do you actually mean perl's tie / magic
> mechanism? If not, what "similar mechanism" are you proposing to use?

As mentioned, _"in the past, we have always simply allowed the
C(++) compiler to provide this functionality for us; however, this
will have to be explicitly implemented when `Perl::Types` is
refactored into its own distribution."_

Thus, we are not committed to any specific implementation, as long
as we choose a mechanism that allows us to (eventually) handle
_"arbitrarily-nested data structures"_ by _"intercepting any
modifications to internal elements and calling `foo_CHECK()` or
`foo_CHECKTRACE()` for each change."_

> The problem with using actual ties, is that they make the variable very
> slow, even if the actual tie methods such as FETCH() are XS code. That's
> because a lot of code paths in the perl interpreter have optimisations for
> non-magic values. For example, look at pp_add() in pp_hot.c in the perl
> source. This implements perl's '+' operator. Obviously in general the two
> operands can be anything - ints, ,nums, strings, magic values, overloaded
> objects etc, and mixtures thereof. But in pp_add(), the first thing it
> does it check the flags of the two operands, and says:

> If they are both non magical and non ref, and if both are either
> simple ints or simple nums, then just add the two values, check they
> haven't overflowed, set the return value and return. Otherwise go
> through the complex 200-lines-of-code path which handles magic, mixed
> types etc.

> So if, for example, an integer variable was marked with get magic, it
> would become a lot slower when being added. Similar considerations apply
> in many places.

> Also, once tie magic starts being applied to arrays and hashes, you start
> to hit edges cases. It's very had to make a tied aggregate behave *exactly*
> like a plain array/hash in all circumstances, even ignoring the slowdown.

Yes we agree this could also be a source of problems, plus slowdowns.

Rather than using `tie`, can you please suggest a more performant
and reliable implementation?

> > So, as mentioned in the original Elevator Pitch, we can "utilize
> > Perl data types to achieve a number of benefits including but not
> > limited to":
> >
> > * increased performance

> So how would you get increased performance? I've already pointed out that
> magic tends to slow things down, and the cost of calling a check routine
> will slow things down even further.

Adding data types to your Perl source code is the first step on
the path toward compiling your Perl source code, which can provide
anywhere from 10x to 400x (or more) runtime performance increase.
Yes you are correct that enabling type-checking will introduce
runtime overhead to interpreted Perl code, but that slowdown
disappears once your Perl code is fully compiled because the
type-checking is done at compile time rather than runtime.

For those who want type-checking for interpreted Perl code only,
we have done our best to minimize the runtime overhead by allowing
the developer to choose between `foo_CHECKTRACE()` and the slightly
faster `foo_CHECK()`. As mentioned, _"type checking is currently
controlled on a per-file basis using the `TYPE_CHECKING` preprocessor
directive"_:
_"The `TYPE_CHECKING` directive can have a value of `OFF` for
disabled, `ON` to call the `foo_CHECK()` macros/functions, and
`TRACE` to call the `foo_CHECKTRACE()` macros/functions. The only
difference between `ON` and `TRACE` is the inclusion of the offending
subroutine and variable names for easier debugging."_

Furthermore, the type-checking is performed by C macros for scalar
data types, and by C functions (which call those underlying C
macros) for array and hash data structures, which is the fastest
possible solution we could find. We even re-implemented our original
scalar type-checking from C functions to C macros for increased
performance.

Here is an example of the fast (but now-deprecated) C functions
for checking the `number` type AKA `NV`:

https://metacpan.org/release/WBRASWELL/RPerl-7.000000/source/lib/RPerl/DataType/Number.cpp#L18-38

```c
// TYPE-CHECKING SUBROUTINES DEPRECATED IN FAVOR OF EQUIVALENT MACROS
void number_CHECK(SV* possible_number) {
if (not(SvOK(possible_number))) {
croak("\nERROR ENV00, TYPE-CHECKING MISMATCH, CPPOPS_PERLTYPES & CPPOPS_CPPTYPES:\nnumber value expected but undefined/null value found,\ncroaking");
}
if (not(SvNOKp(possible_number) || SvIOKp(possible_number))) {
croak("\nERROR ENV01, TYPE-CHECKING MISMATCH, CPPOPS_PERLTYPES & CPPOPS_CPPTYPES:\nnumber value expected but non-number value found,\ncroaking");
}
};
void number_CHECKTRACE(SV* possible_number, const char* variable_name, const char* subroutine_name) {
if (not(SvOK(possible_number))) {
croak("\nERROR ENV00, TYPE-CHECKING MISMATCH, CPPOPS_PERLTYPES & CPPOPS_CPPTYPES:\nnumber value expected but undefined/null value found,\nin variable %s from subroutine %s,\ncroaking",
variable_name, subroutine_name);
}
if (not(SvNOKp(possible_number) || SvIOKp(possible_number))) {
croak("\nERROR ENV01, TYPE-CHECKING MISMATCH, CPPOPS_PERLTYPES & CPPOPS_CPPTYPES:\nnumber value expected but non-number value found,\nin variable %s from subroutine %s,\ncroaking",
variable_name, subroutine_name);
}
};
```
Here is an example of the functionally-equivalent and even-faster
C macros, as mentioned in our first reply:

https://metacpan.org/release/WBRASWELL/RPerl-7.000000/source/lib/RPerl/DataType/Number.h#L137-149

```c
// [[[ TYPE-CHECKING MACROS ]]]
#define number_CHECK(possible_number) \
(not(SvOK(possible_number)) ? \
croak("\nERROR ENV00, TYPE-CHECKING MISMATCH, CPPOPS_PERLTYPES & CPPOPS_CPPTYPES:\nnumber value expected but undefined/null value found,\ncroaking") : \
(not(SvNOKp(possible_number) || SvIOKp(possible_number)) ? \
croak("\nERROR ENV01, TYPE-CHECKING MISMATCH, CPPOPS_PERLTYPES & CPPOPS_CPPTYPES:\nnumber value expected but non-number value found,\ncroaking") : \
(void)0))
#define number_CHECKTRACE(possible_number, variable_name, subroutine_name) \
(not(SvOK(possible_number)) ? \
croak("\nERROR ENV00, TYPE-CHECKING MISMATCH, CPPOPS_PERLTYPES & CPPOPS_CPPTYPES:\nnumber value expected but undefined/null value found,\nin variable %s from subroutine %s,\ncroaking", variable_name, subroutine_name) : \
(not(SvNOKp(possible_number) || SvIOKp(possible_number)) ? \
croak("\nERROR ENV01, TYPE-CHECKING MISMATCH, CPPOPS_PERLTYPES & CPPOPS_CPPTYPES:\nnumber value expected but non-number value found,\nin variable %s from subroutine %s,\ncroaking", variable_name, subroutine_name) : \
(void)0))
```

For those who want data types in their interpreted code as a form
of annotation only, they can set `TYPE_CHECKING` to `OFF` for even
better performance. You can always turn it back on later.

```perl
# [[[ PREPROCESSOR ]]]
# <<< TYPE_CHECKING: OFF >>>
```

For those who don't want data types in their Perl code at all...
just don't `use Perl::Types;`, it's that simple. Your code won't
be affected in anyway, and you can safely continue without any data
types of any kind, just like Perl has always been in the past.

> > * memory safety (bounds checking)

> Can you give an example of where currently perl isn't memory safe, but
> Perl::Types would make it so?

We are not currently aware of any such issues with the Perl
interpreter, and our goal is not to attempt to point out anything
wrong with the interpreter's memory management. Rather, this is
again primarily related to the need for memory bounds checking for
those who wish to compile their Perl code.

That being said, in the future it may certainly be possible for
the Perl interpreter to utilize data type and data structure
information to implement optimizations in memory and/or performance.

For example, a Perl array can declare its own specific maximum
index (length minus 1) during creation, which is used by the Perl
compiler (and subsequently the C(++) compiler) for standard memory
management purposes. In the following example, the declared
`arrayref` length is 4, with an `undef` being assigned to the
maximum index of 3 (`4 - 1`) in order to avoid `Useless use of
array element in void context` when `use warnings;` is enabled:

```perl
my integer::arrayref $foo->[4 - 1] = undef;
```

The current experimental syntax for declaring an `array` is very similar, but without the need for `undef` and with the unfortunate need for a temporary `$TYPED_foo` scalar:

```perl
my integer::array @foo = my $TYPED_foo->[4 - 1];
```

The Perl interpreter could potentially utilize the array's maximum
index to more effectively organize allocated memory, reduce calls
to garbage collection, increase efficiency of accessing contiguous
array elements, etc.

As with our previously-discussed pure-Perl `$RETURN_TYPE` syntax,
the current experimental syntax for declaring array lenths may
leave a bit to be desired, but it does not require any change to
the Perl parser and was the best we could come up with so far.
(Also, in the `arrayref` example the Perl interpreter actually
creates an anonymous array of length 4, while in the `array` example
it creates an array of length 1.)

Can you please suggest possible pure-Perl syntax alternatives for
specifying the various maximum indices of an arbitrarily-nested
`array` and `arrayref`, without requiring any changes to the existing
Perl internals?

> > * potential for polymorphism

> Please explain further.

There are many different styles or variations of polymorphism in
computer science. For the sake of brevity, we will only address
one style here: function overloading AKA ad hoc polymorphism.
These same ideas can likely be extended to include other styles of
polymorhism as well.

For example, imagine the following expansion of our original
`squared()` subroutine example:

```perl
#!/usr/bin/perl
use strict;
use warnings;

use Perl::Types;

sub squared {
{ my integer $RETURN_TYPE };
( my integer $base ) = @ARG;
return $base ** 2;
}

sub squared {
{ my number $RETURN_TYPE };
( my number $base ) = @ARG;
return $base * $base;
}

sub squared {
{ my string $RETURN_TYPE };
( my string $base ) = @ARG;
return $base x (length $base);
}

print squared(23), "\n";
print squared(21.12), "\n";
print squared('howdy'), "\n";
```

Wouldn't it be nice if we got this...

```
529
446.0544
howdyhowdyhowdyhowdyhowdy
```

... instead of this?

```
Subroutine squared redefined at ./sub_test.pl line 14.
Subroutine squared redefined at ./sub_test.pl line 20.
2323
21.1221.1221.1221.1221.12
howdyhowdyhowdyhowdyhowdy
```
What are your thoughts on this kind of polymorphism, function overloading based on argument and/or return value data type(s)?

> Ok, that was the technical side of things. Now on to the policy side.
> 20 years or so ago, perl went through a phase of adding lots of 'useful'
> modules to the perl core. This was widely seen as a mistake.

> First, it made a particular module seem to be officially endorsed.
> Hypothetically, "among several XML parser modules, we chosen this one as
> the best and the one you should use". When design flaws in XML::Parser
> (say) are discovered, and the general recommendation is to use
> XML::BetterParser instead, XML::Parser is still sitting in the perl core
> getting an unfair endorsement. And removing it from core is hard, because
> now lots of people used it, and they're using it because, well, we
> endorsed it!

Our goal is for Perl::Types to be the official data type system of
Perl, in the same exact way that Corinna is the official class
system of Perl. If a so-called "dual life" distribution is the
wrong way to achieve this, then we're fine with that.

> Second, if modules stop being actively maintained by their author(s) for
> whatever reason, then suddenly we become responsible for maintaining it.
> It's enough work just maintaining the core perl interpreter, without
> taking on extra responsibilities.

Yes we agree, which is why we have formed the Perl::Types Committee
and are in the process of training new Perl::Types developers to
avoid a low bus factor.

> Third, in these days of package managers etc, it's relatively easy for
> people to install the CPAN modules they want. They will also get the
> newest and best version by default, rather than using the old buggy version
> bundled with perl. So there is less good reason to bundle a package with
> perl.

Our goal is for Perl::Types (or its descendent) to be included in
every future version of Perl, in the same exact way that Corinna
will presumably be included in every future version of Perl. We
are fine with handling versioning in the same way as Corinna,
whatever that may be.

> So these days the policy is not to bundle CPAN modules with perl unless
> they are necessary, usually because they are needed as part of the tool
> chain. There have been very few new modules added to the perl core in the
> last 15 years or so that are capable of acting as standalone CPAN
> distributions instead.

> So the short answer is that even if Perl::Types really appealed to us, it
> is very unlikely that we would agree to bundle it. And I think we're
> far from a consensus yet that it appeals.

Since you have made a strong case against a dual-life distribution
being included in the Perl core, can you instead please explain
the specific process which Corinna followed to get merged into the
Perl interpreter?

Perhaps Perl::Types can act like Object::Pad, as the experimental
distribution out of which we can derive the desired Perl interpreter
code in the same way that Corinna was derived from Object::Pad?

> On a purely individual note, I am finding Perl::Types very unappealing so
> far.

Can you please give us a specific list of all the things you find
unappealing?

Dave Mitchell

unread,
Sep 2, 2023, 3:00:04 PM9/2/23
to Oodler 577, perl5-...@perl.org
On Sat, Sep 02, 2023 at 04:11:02AM +0000, Oodler 577 via perl5-porters wrote:
> > If the latter, please expand.
>
> It is not an actual source filter as documented in `perlfilter`,
> although it is the same general concept. As mentioned in the
> previous response, _"this source-filter-like functionality is
> currently contained in the Perl compiler's file `Class.pm` and is
> triggered by including `use RPerl;` in a Perl source code file."_
> You can see the filter-like implementation in the link and code
> snippet from our last response:

We seem to be misunderstanding each other at a fairly fundamental level.

My understanding (and please correct me if I'm wrong) is that your desired
eventual outcome of this discussion is that a distribution called
Perl:Types will be available on CPAN, and will also bundled into the perl
distribution, so that someone with a standard perl install can type into
their code something like:

use Perl::Types;
my integer $x = f(); # croaks if f() doesn't return an int.

This is independent of the existence of RPerl - i.e. some code from RPerl
may be incorporated into Perl::Types source, but the perl use isn't
required to install RPerl or use any of the weird RPerl syntax.

So, with that understanding, I've expressed curiosity as to how you are
going to implement this functionality using only the resources available
in perl. You said "Source filters". I said that was a bad idea. You've now
said "it's something similar to a source filter - look at this RPerl
code".

Why should I look at RPerl code? I'm not interested in RPerl. I Don't like
RPerl.

Do you believe it is possible to implement Perl::Types in perl? If so, how?
If not, are you suggesting proposals for new hooks or APIs that should be
incorporated into perl to make adding type systems easier? Or what?
I really have no idea what it is you're asking.

> Yes we agree this could be a source of problems.
>
> Rather than using a source filter (or similar mechanism as detailed
> above), can you please suggest a more stable and reliable
> implementation?

I have no idea. It may not be possible. It's not my problem.


> Rather than using `tie`, can you please suggest a more performant
> and reliable implementation?

No I can't. I haven't got a clue. I've spent 20 years working on the
internals of perl, and I think what you are requesting is a very difficult
to solve problem that may well have no solution.

> Adding data types to your Perl source code is the first step on
> the path toward compiling your Perl source code, which can provide
> anywhere from 10x to 400x (or more) runtime performance increase.

Ah yes, sprinkle on a bit of magic pixie dust and suddenly perl can be
made 400x faster.

> Yes you are correct that enabling type-checking will introduce
> runtime overhead to interpreted Perl code, but that slowdown
> disappears once your Perl code is fully compiled because the
> type-checking is done at compile time rather than runtime.

That way lies RPerl, surely?

> For those who want type-checking for interpreted Perl code only,
> we have done our best to minimize the runtime overhead by allowing
> the developer to choose between `foo_CHECKTRACE()` and the slightly
> faster `foo_CHECK()`. As mentioned, _"type checking is currently
> controlled on a per-file basis using the `TYPE_CHECKING` preprocessor
> directive"_:

I don't understand that all all. Please stop just pointing at random bits
of RPerl code which I am completely unfamiliar with and expecting that to
be an explanation.

> > > * memory safety (bounds checking)
>
> > Can you give an example of where currently perl isn't memory safe, but
> > Perl::Types would make it so?
>
> We are not currently aware of any such issues with the Perl
> interpreter, and our goal is not to attempt to point out anything
> wrong with the interpreter's memory management. Rather, this is
> again primarily related to the need for memory bounds checking for
> those who wish to compile their Perl code.

So using Perl::Types doesn't actually add any value to user's code as
regards memory safety.

> Can you please suggest possible pure-Perl syntax alternatives for
> specifying the various maximum indices of an arbitrarily-nested
> `array` and `arrayref`, without requiring any changes to the existing
> Perl internals?

Again, stop trying to make everything my responsibility.

> What are your thoughts on this kind of polymorphism, function overloading based on argument and/or return value data type(s)?

I don't have any strong opinions on it, but personally I don't see what
value it adds. It seems to be that, after adding a type system which
unduly limits the flexibility of your code, adding polymorphism based on
type just allows you to then remove *some* of that inconvenience.

I like the fact that in perl I can throw an int or a float or
string at a function, and it will already always do the Right Thing.
In perl I can write

while (<>) {
$foo += $1 if /foo=(\d+)/;
}

without having to worry about string to integer conversions or whatever.

> > On a purely individual note, I am finding Perl::Types very unappealing so
> > far.
>
> Can you please give us a specific list of all the things you find
> unappealing?

Well, the basic problem is that we still don't know what semantics
Perl::Types is supposed to provide or how it will be implemented.

So my objections are partly conjectural. But IIUC, RPerl's "type" system
is really just the CPU-level type system. I.e. what you get in C etc,
where an int is a simple 32-bit or 64-bit entity, which is fast but unsafe.

In C, if you do

int i = 0x7fffffffffffffff;
i *= 4;
printf "%d\n", i;

then you'll get some sort of wrapped-around value.

In perl, if you do

my $i = 0x7fffffffffffffff;
$i *= 4;
printf "%s\n", $i;

you get

3.68934881474191e+19

because internally, perl goes to great lengths to avoid overflows and loss
of precision, automatically converting internally between signed int,
unsigned int and doubles etc.

So I'm not keen on the idea of downgrading perl's dynamic type system into
a C-style type system.

In terms of making perl go a lot faster, I have various ideas, but little
time to realise them - there are always too many basic things to fix.

But I much prefer the idea of keeping perl as *perl* (dynamic typing etc)
and let the interpreter do the clever stuff: such as speculative execution
branches where perl assumes (based on code analysis and previous calls
to that code position) that the result will be an integer, and so skips
using full-blown SVs and just does direct integer arithmetic. If at some
point during execution an overflow is detected or whatever, then perl
jumps back to a checkpoint, and this time takes the "heavy" branch using
full-blown SVs etc.

So in something like $a[$x+$y*$z], perl detects that $x, $y and $z are
usually integer values, and takes a short-cut. If that doesn't work out,
then it still gets the right result, just more slowly.

So the user gets the performance benefits without having to rewrite
all their code to include 'integer' declarations everywhere.

As a final caveat, note that I'm more of an internals guy than a language
design guy. So my views on proposed new language features shouldn't be
taken too seriously. But if I say that a particular proposal will be hard
or impossible to implement, take that seriously.

--
The Enterprise successfully ferries an alien VIP from one place to another
without serious incident.
-- Things That Never Happen in "Star Trek" #7

Oodler 577 via perl5-porters

unread,
Sep 4, 2023, 6:00:04 PM9/4/23
to Christian Walde, Dave Mitchell, Oodler 577 via perl5-porters
* Christian Walde <walde.c...@gmail.com> [2023-09-04 10:08:13 +0200]:

> (originally sent privately, sent to list on explicit request by oodler)
>
> On Sat, 02 Sep 2023 06:11:02 +0200, Oodler 577 via perl5-porters <perl5-...@perl.org> wrote:
>
> > https://metacpan.org/release/WBRASWELL/RPerl-7.000000/source/lib/RPerl/CompileUnit/Module/Class.pm#L673-715
>
> fwiw, some of the rather muted enthusiasm you're seeing for this project stems from the fact that (corroborated by several random perl devs i polled) this code looks harder to maintain than it should be, seemingly not being deduplicated, and not like native perl code at all

The results of your informal poll sound udderly ridiculous.

>
> it feels like it was written by somebody who knows a different programming language really well and preferred not to get too familiar with perl
>
> here's code that does somewhat similar work, but in a way that inspires confidence
>
> https://metacpan.org/release/HAARG/Moo-2.005005/source/lib/Method/Generate/Accessor.pm#L429

Okay, thanks.

Cheers,
Brett

>
> --
> With regards,
> Christian Walde

--

Oodler 577 via perl5-porters

unread,
Sep 4, 2023, 10:30:04 PM9/4/23
to Christian Walde, Oodler 577 via perl5-porters
* Christian Walde <walde.c...@gmail.com> [2023-09-05 01:59:20 +0200]:

> On Mon, 04 Sep 2023 23:44:04 +0200, Oodler 577 <oodl...@sdf-eu.org> wrote:
>
> > > > https://metacpan.org/release/WBRASWELL/RPerl-7.000000/source/lib/RPerl/CompileUnit/Module/Class.pm#L673-715
> > >
> > > fwiw, some of the rather muted enthusiasm you're seeing for this project stems from the fact that (corroborated by several random perl devs i polled) this code looks harder to maintain than it should be, seemingly not being deduplicated, and not like native perl code at all
> > The results of your informal poll sound udderly ridiculous.
>
> why? :)

Because it's BS. Get it? Udderly BS? xD
0 new messages