develooper Front page | perl.perl5.porters | Postings from November 2017

[perl #132473] smartmatch signatures

Thread Previous | Thread Next
From:
Zefram
Date:
November 20, 2017 14:59
Subject:
[perl #132473] smartmatch signatures
Message ID:
rt-4.0.24-7190-1511189959-1928.132473-75-0@perl.org
# New Ticket Created by  Zefram 
# Please include the string:  [perl #132473]
# in the subject line of all future correspondence about this issue. 
# <URL: https://rt.perl.org/Ticket/Display.html?id=132473 >



This is a bug report for perl from zefram@fysh.org,
generated with the help of perlbug 1.40 running under perl 5.27.5.


-----------------------------------------------------------------
[Please describe your issue here]

Everyone would like to have type constraints in signatures, but a
prohibitive issue is that the core doesn't have a general type system.
(There are classes, but they don't address any of the type distinctions we
frequently need to make between unblessed data types.)	Smartmatch could
become the core's type system, as we've discussed a bit when talking
about the future of smartmatch.

Suppose that the smartmatch/switch discussions lead to a version of
smartmatch that we can all live with.  (In the last round of discussion we
seemed to be agreed on smartmatch semantics, and it's just the given/when
stuff that's holding us back.)	This would be almost entirely based on
explicit overloading of the smartmatch operator by blessed objects that
appear on the rhs of smartmatch.  We would expect to see a rich ecosystem
of matcher object classes that implement all kinds of predicate, including
composite predicates that incorporate subordinate matcher objects.

Matcher objects can then be used as type metaobjects.  In general
they're types in only the minimal sense that they have a concept of type
membership.  Specific kinds of matcher object may also have other kinds
of type-related behaviour; for example, Moose class metaobjects would
presumably overload smartmatch to implement a class membership check,
while also having introspective methods that only make sense for the Moose
concept of a class.  But we don't need to worry about that; for signatures
the only aspect of a type that we care about is the membership predicate.

So a scalar signature item could specify a type constraint by referring
to an appropriate matcher object.  We'd want to permit an arbitrary
expression for the matcher object, to allow for parameterised and
composite types.  So very little signature syntax is required; really
just a signifier for smartmatching and a grammatical slot into which to
put the matcher expression.  Using signature syntax otherwise as it is
today, this would look something like:

    use Smart_Type qw(Num Str union HashRef_of);   # imaginary module
    use feature "signatures";
    sub gronk ($why ~Str, $how_hard ~Num = 5) {...}
    sub annotate ($subject, $msg ~ union(Str, HashRef_of(Str))) {...}
    sub nom ($food ~ My::Food->meta = My::Apple->new) {...}

"~" references the smartmatch operator while not being longer than
necessary.  The matcher expression would have to be restricted to
expressions above some middling precedence level, so that in the case of
an optional parameter it doesn't read the "=" and default value expression
as part of the matcher expression.  But I imagine matcher objects would
also overload the bitwise operators to perform Boolean compositions,
so it would be nice for the threshold to be lower than those operators.
Any expression of lower precedence than the threshold could of course
be parenthesised.  So we'd have things like:

    use Smart_Type qw(Str HashRef_of);
    use feature "signatures";
    sub annotate ($subject, $msg ~ Str | HashRef_of(Str)) {...}
    sub frob ($spec ~ (state $fspec_type = gen_fspec_type())) {...}

With respect to the last of those examples, usually the type we want to
smartmatch against is fixed for all time, and recomputing the matcher
for each execution of the sub would be unwanted expense, potentially
significant.  So making the matcher be implicitly saved in an invisible
state variable might be a better way to go.  However, it's impossible to
get fully dynamic type constraint logic (referring to earlier parameters)
if that's always done, so consideration should then be given to having
a variant of "~" that explicitly makes the matcher expression dynamic.

In optional parameters I imagine the default value expression would be
exempt from the type constraint, but this could go either way.

It's a little more difficult to apply type constraints to array and
hash parameters.  We probably want to apply the type constraint to the
whole array or hash, for maximum flexibility, but the actual smartmatch
operand would have to be *a reference to* the array or hash, so how do
we indicate that in the signature syntax?

It's also necessary to think about how type constraints would interact
with aliasing in signatures [perl #132472].

[Please do not change anything below this line]
-----------------------------------------------------------------
---
Flags:
    category=core
    severity=wishlist
---
Site configuration information for perl 5.27.5:

Configured by zefram at Fri Oct 20 23:24:00 BST 2017.

Summary of my perl5 (revision 5 version 27 subversion 5) configuration:
   
  Platform:
    osname=linux
    osvers=3.16.0-4-amd64
    archname=x86_64-linux-thread-multi
    uname='linux barba.rous.org 3.16.0-4-amd64 #1 smp debian 3.16.43-2+deb8u2 (2017-06-26) x86_64 gnulinux '
    config_args='-des -Dprefix=/home/zefram/usr/perl/perl_install/perl-5.27.5-i64-f52 -Duselargefiles -Dusethreads -Uafs -Ud_csh -Uusesfio -Uusenm -Duseshrplib -Dusedevel -Uversiononly -Ui_db'
    hint=recommended
    useposix=true
    d_sigaction=define
    useithreads=define
    usemultiplicity=define
    use64bitint=define
    use64bitall=define
    uselongdouble=undef
    usemymalloc=n
    default_inc_excludes_dot=define
    bincompat5005=undef
  Compiler:
    cc='cc'
    ccflags ='-D_REENTRANT -D_GNU_SOURCE -fwrapv -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2'
    optimize='-O2'
    cppflags='-D_REENTRANT -D_GNU_SOURCE -fwrapv -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include'
    ccversion=''
    gccversion='4.9.2'
    gccosandvers=''
    intsize=4
    longsize=8
    ptrsize=8
    doublesize=8
    byteorder=12345678
    doublekind=3
    d_longlong=define
    longlongsize=8
    d_longdbl=define
    longdblsize=16
    longdblkind=3
    ivtype='long'
    ivsize=8
    nvtype='double'
    nvsize=8
    Off_t='off_t'
    lseeksize=8
    alignbytes=8
    prototype=define
  Linker and Libraries:
    ld='cc'
    ldflags =' -fstack-protector-strong -L/usr/local/lib'
    libpth=/usr/local/lib /usr/lib/gcc/x86_64-linux-gnu/4.9/include-fixed /usr/include/x86_64-linux-gnu /usr/lib /lib/x86_64-linux-gnu /lib/../lib /usr/lib/x86_64-linux-gnu /usr/lib/../lib /lib
    libs=-lpthread -lnsl -ldb -ldl -lm -lcrypt -lutil -lc
    perllibs=-lpthread -lnsl -ldl -lm -lcrypt -lutil -lc
    libc=libc-2.19.so
    so=so
    useshrplib=true
    libperl=libperl.so
    gnulibc_version='2.19'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs
    dlext=so
    d_dlsymun=undef
    ccdlflags='-Wl,-E -Wl,-rpath,/home/zefram/usr/perl/perl_install/perl-5.27.5-i64-f52/lib/5.27.5/x86_64-linux-thread-multi/CORE'
    cccdlflags='-fPIC'
    lddlflags='-shared -O2 -L/usr/local/lib -fstack-protector-strong'


---
@INC for perl 5.27.5:
    /home/zefram/usr/perl/perl_install/perl-5.27.5-i64-f52/lib/site_perl/5.27.5/x86_64-linux-thread-multi
    /home/zefram/usr/perl/perl_install/perl-5.27.5-i64-f52/lib/site_perl/5.27.5
    /home/zefram/usr/perl/perl_install/perl-5.27.5-i64-f52/lib/5.27.5/x86_64-linux-thread-multi
    /home/zefram/usr/perl/perl_install/perl-5.27.5-i64-f52/lib/5.27.5

---
Environment for perl 5.27.5:
    HOME=/home/zefram
    LANG (unset)
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/home/zefram/usr/perl/perl_install/perl-5.27.5-i64-f52/bin:/home/zefram/usr/perl/util:/home/zefram/pub/x86_64-unknown-linux-gnu/bin:/home/zefram/pub/common/bin:/usr/bin:/bin:/usr/local/bin:/usr/games
    PERL_BADLANG (unset)
    SHELL=/usr/bin/zsh


Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About