=head1 Title

 [DRAFT] Synopsis 29 - Builtin Functions [DRAFT]

=head1 Version

 Maintainer:    Rod Adams <rod@rodadams.net>
 Date:          12 Mar 2005
 Last Modified: 03 Apr 2005

This document attempts to document the list of builtin functions in Perl 6.
It assumes familiarity with Perl 5 and prior synopses.

=head1 Notes

In Perl 6, all builtin functions belong to a named package. Not all
functions are guaranteed to be imported into the global package
C<::*>. In addition, the list of functions imported into C<::*> will be
subject to change with each release of Perl. Authors wishing to
"Future Proof" their code should either specifically import the
functions they will be using, or always refer to the functions by their
full name.

After 6.0.0 comes out, global aliases will not be removed lightly,
and will never be removed at all without having gone through a
deprecation cycle of at least a year.  In any event, you can specify
that you want the interface for a particular version of Perl, and
that can be emulated by later versions of Perl to the extent that
security updates allow.

Where code is given here, it is intended to define semantics, not to
dictate implementation.


=head1 Type Declarations

The following type declarations are assumed:

=over

=item Char

The root class of all "character" types, regardless of level. 

This is a subtype of C<Str>, limited to a length of 1 at it's highest
supported Unicode level.

Subclasses (things that are C<isa Char>):

=over

=item LanguageChar aka LChar

=item Grapheme aka Grf

=item CodePoint aka CdPt

=item Byte

Yes, Byte is both a string and a number.

=back



=item MatchTest

 type MatchTest ::= Item | Junction;

Used to supply a test to match against. Assume C<~~> will be used against it.



=back



=head1 Function Packages

=head2 Math::Basic

=over

=item abs

 multi  Num::abs (  Num  $x              --> Num )
 multi Math::Basic::abs ( Num $x? = $+_  --> Num )

Absolute Value.

=item floor

 multi  Num::floor (  Num  $x            --> Int )

Returns the highest integer not greater than $x.

=item ceiling

 multi  Num::ceiling (  Num  $x          --> Int )
 &Num::ceil ::= &Num::ceiling;

Returns the lowest integer not less than $x.

=item round

 multi  Num::round (  Num  $x            --> Int )

Returns the nearest integer to $x, away from zero.  In other words,
the absolute value, rounded up.

=item truncate

 multi  Num::truncate (  Num  $x         --> Int )
 our &Num::int ::= &Num::truncate;

Returns the closest integer to $x, rounding towards 0.  This is the
default rounding function used by an C<int()> cast, for historic
reasons.

=item exp

 multi  Num::exp (  Num  $exponent            : Num :$base --> Num )
 multi Math::Basic::exp ( Num $exponent? = $+_, Num :$base --> Num )

Performs similar to C<$base ** $exponent>. C<$base> defaults to the
constant I<e>.


=item log

 multi  Num::log (  Num  $x             : Num :$base --> Num )
 multi Math::Basic::log ( Num $x? = $+_,  Num :$base --> Num )

Logarithm of base C<$base>, default Natural. Calling with C<$x == 0> is an
error.


=item log10

 &log10 := &log.assuming:base(10);


=item rand

 multi Math::Basic::rand ( Num $x? = 1 --> Num )

Psuedo random number between C<0> and C<$x>.


=item sign

 multi  Num::sign (  Num  $x             --> Int )
 multi Math::Basic::sign ( Num $x? = $+_ --> Int ) {
   if !defined($x) { return undef };
   if $x < 0       { return -1    };
   if $x > 0       { return  1    };
   if $x == 0      { return  0    };
   undef;
 }


=item srand

 multi Math::Basic::srand ( Num $seed)

Seed the generator C<rand> uses. C<$seed> defaults to some combination
of various platform dependent characteristics to yield a non-
deterministic seed.


=item sqrt

 multi  Num::sqrt (  Num  $x              --> Num )
 multi Math::Basic::sqrt ( Num $x? = $+_  --> Num )

C<$x ** 0.5>

=back



=head2 Math::Trig

=over 4

=item I<Standard Trig Functions>

 multi Num::func (  Num  $x            : :$base --> Num )
 multi Math::Trig::func ( Num $x? = $+_, :$base --> Num )

where I<func> is one of:
sin, cos, tan, asin, acos, atan, sec, cosec, cotan, asec, acosec,
acotan, sinh, cosh, tanh, asinh, acosh, atanh, sech, cosech, cotanh,
asech, acosech, acotanh.

Performs the various trigonmetric functions. 

Option C<$base> is used to declare your how you measure your angles.
Given the value of an arc representing a single full revolution.

 $base  	Result
 ----   	-------
 /:i ^r/	Radians  (2*pi)
 /:i ^d/	Degrees  (360)
 /:i ^g/	Gradians (400)
 Num    	Units of 1 revolution. 


=item atan

 multi Math::Trig::atan (Num $y, Num $x? = 1 : Num :$base --> Num )

This second form of C<atan> computes the arctangent of $y/$x, and takes
the quadrant into account. Otherwise behaves as other trigonometric functions.
Replaces Perl 5 C<atan2>.


=item pi

 multi Math::Trig::pi ( --> Num )



=back

=head2 Array

=over

=item delete

 multi method Array::delete (@array : *@indices --> List )

Sets elements specified by C<@indices> in the invocant to a
non-existent state, as if they never had a value. Deleted elements at
the end of an Array shorten the length of the Array, unless doing so
would violate an C<is shape()> definition.

C<@indices> is interpreted the same way as subscripting is in terms of
slices and multidimensionality. See Synopsis 9 for details.

Returns the value(s) previously held in deleted locations.

An unary form is expected. See C<Hash::delete>.


=item exists

 multi method Array::exists (@array : Int *@indices --> Bool )

True if the specified Array element has been assigned to. This
is not the same as being defined.

Supplying a different number of indices than invocant has dimensions is
an error.

An unary form is expected. See C<Hash::delete>.


=item pop

 &Array::pop := &Array::splice.assuming(:offset(-1) :length(1));

 multi Array::pop ( --> Scalar ) {
   Array::pop @+_;
 }


=item push

 multi Array::push (@array is rw : *@values --> Int ) {
   Array::splice(@array, @array.elems, 0, @values);
   @array.elems;
 }


=item shift

 &Array::shift := &Array::splice.assuming(:offset(0) :length(1));

 multi Array::shift ( --> Scalar ) {
   Array::shift @+_;
 }


=item splice

 multi Array::splice (       @array is rw 
                                 : Int $offset = 0,
                                   Int $length,
                                       *@values
                                --> List ) is rw

Behaves similar as Perl 5 C<splice>.

If C<@array> is multidimensional, C<splice> operates only on the first
dimension, and works with Array References.


=item unshift

 multi Array::unshift (@array is rw : *@values --> Int ) {
   Array::splice(@array, 0, 0, @values);
   @array.elems;
 }


=item keys

=item kv

=item pairs

=item values

 multi Array::keys   (@array : MatchTest *@indextests --> Int|List )
 multi Array::kv     (@array : MatchTest *@indextests --> Int|List )
 multi Array::pairs  (@array : MatchTest *@indextests --> Int|(List of Pair) )
 multi Array::values (@array : MatchTest *@indextests --> Int|List )

(XXX these signatures are wrong. -luqui)

Iterates the elements of C<@array>, in order. 

If C<@indextests> are provided, only elements whose indices match
C<$index ~~ any(@indextests)> are iterated.

What is returned at each element of the iteration varies with function.
C<values> returns the value of the associated element; C<kv> returns 
a 2 element list in (index, value) order, C<pairs> a C<Pair(index, value)>.

C<@array> is considered single dimensional. If it is in fact multi-
dimensional, the values returned will be array references to the sub
array.

In Scalar context, they all return the count of elements that would have
been iterated.

=back



=head2 List

=over

=item grep

 multi Array::grep (@values :      Code *&test   --> Lazy )
 multi Array::grep (@values :  MatchTest $test   --> Lazy )
 multi  List::grep (MatchTest $test :   *@values --> Lazy ) {
   gather {
     for @values -> $x {
       take $x if $x ~~ $test;
     }
   }
 }


=item join

 multi Array::join (@values :  Str $delimiter --> Str )
 multi  List::join (Str $delimiter : *@values --> Str ) {
   my $str = ~@values[0];
   for 1..@values.end {
     $str ~= $delimiter ~ @values[$_];
   }
   $str;
 }
 &join := &join.assuming:delimiter(' ');


=item map 

 multi Array::map (@values : Code *&expression --> Lazy ) 
 multi  List::map (Code $expression : *@values --> Lazy ) {
   gather {
     while @values {
       take $expression
          .( splice(@values, 0, $expression.arity) );
     }
   }
 }


=item reduce

 multi Array::reduce (@values : Code *&expression --> Scalar )
 multi  List::reduce (Code $expression : *@values --> Scalar ) {
   my $res;
   for @values -> $cur {
        FIRST {$res = $cur; next;}
     $res = &$expression($res, $cur);
   }
   $res;
 }


=item reverse

 multi Hash::reverse (%hash --> Hash ) is default {
   (my %result){%hash.values} = %hash.keys;
   %result;
 }

 multi Array::reverse (  @values --> Lazy|Str) {
 multi  List::reverse ( *@values --> Lazy|Str) {
   given want {
     when List {
       gather {
         1 while take pop @values;
       }
     }
     when Scalar {
       reverse @values ==> join;
     }
   }
 }


=item sort

 type KeyExtractor  ::= Code(Any --> Any );
 type Comparator    ::= Code(Any, Any --> Int );
 type SortCriterion ::= KeyExtractor
                      | Comparator
                      | Pair(KeyExtractor, Comparator);

 multi Array::sort(                 @values is rw,
                                              *&by
                              :           Bit :$inplace
                             --> Array )

 multi Array::sort(                 @values is rw,
                                SortCriterion  @by
                              :           Bit :$inplace
                             --> Array )

 multi Array::sort(                 @values is rw
                              : SortCriterion :$by = &infix:<cmp>,
                                          Bit :$inplace
                             --> Array )

 multi  List::sort(  SortCriterion  @by
                              :               *@values
                             --> List )

 multi  List::sort( SortCriterion  $by = &infix:<cmp>,
                                              *@values
                             --> List )

Returns C<@values> sorted, using criteria C<$by> or C<@by> for
comparisions. C<@by> differs from C<$by> in that each criteria is
applied, in order, until a non-zero (tie) result is achieved.

Criterion can take a few different forms:

=over 8

=item Comparator

A closure with arity of 2, which returns negative/zero/positive,
signaling the first arguement should be before/tied with/after the
second in the final ordering of the List. aka "The Perl 5 way"

=item KeyExtractor

A closure with arity of 1, which returns the "key" by which to sort. If
the closure returns a Num, C<E<lt>=E<gt>> is used for comparison,
otherwise C<cmp>.

=item Pair(KeyExtractor, Comparator)

A combination of the two methods above, for when one wishs to take
advantage of the internal caching of keys that is expected to happen,
but wishes to compare them with something other than C<E<lt>=E<gt>> or
C<cmp>.

=back

Any Criterion may recieve either or both of the traits C<is descending>
and C<is insensitive> to reverse the order of sort, or the adjust the
case sensitivity of C<cmp> as a Comparator.

If all criteria are exhausted when comparing two elements, sort should
return them in the same relative order they had in C<@values>.

If C<$inplace> is specified, the array is sorted in place.

See L<http://www.nntp.perl.org/group/perl.perl6.language/16578> for more
details and examples.



=item zip

 multi List::zip ( Array *@lists, Bit :$shortest --> Lazy ) {
   gather {
     while $shortest ?? all(@lists) !! any(@lists) {
       for @lists -> @list {
         take shift @list;
       }
     }
   }
 }

[Note: This should be the definition of each() now.  The zip function needs
to build tuples of the "across" values.  Also, it maybe probably be
in terms of longest non-infinite.  -law]

=back



=head2 Hash

=over 4

=item delete

 multi method Hash::delete ( *@keys --> List )
 multi method Hash::delete (   $key --> Scalar ) is default

Deletes the elements specified by C<$key> or C<$keys> from the invocant.
returns the value(s) that were associated to those keys.

=over

=item Unary Form

Implementations should create a suitable macro, or otherwise support the
unary form C<delete %hash{$key}> in all it's forms. Below are some
example translations. This list is I<not> exhaustive.

 delete %hash{$key}                %hash.delete{$key}
 delete %hash<key>                 %hash.delete{'key'}
 delete %hash<key1>{@keys}         %hash<key1>.delete{@keys}


=back


=item exists
 
 multi method Hash::exists ($key --> Bool )

True if invocant has an element whose key matches C<$key>, false
otherwise.

An unary form is expected. See Hash::delete


=item keys

=item kv

=item pairs

=item values

 multi Hash::keys   (%hash : MatchTest *@keytests --> Int|List )
 multi Hash::kv     (%hash : MatchTest *@keytests --> Int|List )
 multi Hash::pairs  (%hash : MatchTest *@keytests --> Int|(List of Pair) )
 multi Hash::values (%hash : MatchTest *@keytests --> Int|List )
 
Iterates the elements of C<%hash> in no apparent order, but the order
will be the same between successive calls to these functions, as long as
C<%hash> doesn't change. 

If C<@keytests> are provided, only elements whose keys evaluate
C<$key ~~ any(@keytests)> as true are iterated.

What is returned at each element of the iteration varies with function.
C<keys> only returns the key; C<values> the value; C<kv> returns both as
a 2 element list in (key, value) order, C<pairs> a C<Pair(key, value)>.

Note that C<kv %hash> returns the same as C<zip(keys %hash; values %hash)>

In Scalar context, they all return the count of elements that would have
been iterated.

The lvalue form of C<keys> is not longer supported. Use the C<.buckets>
property instead.

=back


=head2 Str

General notes about strings:

A Str can exist at several Unicode levels at once. Which level you
interact with typically depends on what your current lexical context has
declared the "working unicode level to be". Default is LChars.

[Q: Can't be LChars because we don't go into "language" mode unless there's
a specific language declaration saying either exactly what language
we're going into, or what environmental parameter to pay attention to
to select our language.  so I suspect the default should be Grf. -law]

Attempting to use a string at a level higher it can support is handled
without warning. The highest supported level is simply mapped char for
char to the desired level. However, attempting to stuff something into
the string at a higher level that doesn't map to the lower level is an
error (for example, attempting to store Kanji in a Byte uplifted to an LChar).

Attempting to use a string at a level lower than what it supports is not
allowed.

If a function takes a C<Str> and returns a C<Str>, the returned C<Str>
will support the same levels as the input, unless specified otherwise.

=over

=item chop

 multi Str::chop ( Str  $string is rw          --> Char )
 multi Str::chop ( Str *@strings = ($+_) is rw --> Char )

Trims the last character from C<$string>, and returns it. Called with a
list, it chops each item in turn, and returns the last character
chopped.


=item chomp

 multi Str::chomp ( Str  $string is rw          --> Int )
 multi Str::chomp ( Str *@strings = ($+_) is rw --> Int )

Related to C<chop>, only removes trailing chars that match C</\n/>. In
either case, it returns the number of chars removed.

Note: Most users should consider setting their I/O handles to autochomp
instead of this step.


=item lc

 multi Str::lc         ( Str $string       --> Str )
 multi Str::lc         ( Str $string = $+_ --> Str )

Returns the input string after converting each character to it's lowercase
form, if uppercase.


=item lcfirst

 multi Str::lcfirst    ( Str $string       --> Str )
 multi Str::lcfirst    ( Str $string = $+_ --> Str )

Like C<lc>, but only affects the first character.


=item uc

 multi Str::uc         ( Str $string       --> Str )
 multi Str::uc         ( Str $string = $+_ --> Str )

Returns the input string after converting each character to it's uppercase
form, if lowercase. This is not a Unicode "titlecase" operation, but a
full "uppercase".


=item ucfirst

 multi Str::ucfirst    ( Str $string       --> Str )
 multi Str::ucfirst    ( Str $string = $+_ --> Str )

Performs a Unicode "titlecase" operation on the first character of the string.


=item capitalize

 multi Str::capitalize ( Str $string       --> Str )
 multi Str::capitalize ( Str $string = $+_ --> Str )

Has the effect of first doing an C<lc> on the entire string, then performing a
C<s:g/(\w+)/{ucfirst $1}/> on it.


=item length

This word is banned in Perl 6.  You must specify units.

=item index 

Needs to be in terms of StrPos, not Int.

=item pack

=item pos

=item quotemeta

=item rindex 

Needs to be in terms of StrPos, not Int.

=item split

 multi Str::split (  Str $delimiter ,  Str $input = $+_, Int $limit = inf --> List )
 multi Str::split ( Rule $delimiter ,  Str $input = $+_, Int $limit = inf --> List )
 multi Str::split (      Str $input :  Str $delimiter          , Int $limit = inf --> List )
 multi Str::split (      Str $input : Rule $delimiter          , Int $limit = inf --> List )
 &split<> := &split<Str>.assuming:delimiter(' ');

String delimiters must not be treated as rules but as constants.  The
default is no longer ' ' since that would be interpreted as a constant.

=item sprintf

=item substr

 multi substr(Str $s, StrPos $start  : StrPos $end,      $replace)
 multi substr(Str $s, StrPos $start,   StrLen $length  : $replace)
 multi substr(Str $s, StrLen $offset : StrLen $length,   $replace)


=item unpack

=item vec

Should replace vec with declared arrays of bit, uint2, uint4, etc.

=back



=head2 Control::Basic

=over

=item eval 
 
 multi Control::Basic::eval ( Str $code = $+_, Grammar :$lang = CALLER::<$?PARSER>)

Execute C<$code> as if it were code written in C<$lang>.  The default
is the language in effect at the exact location of the eval call.

Returns whatever C<$code> returns, or undef on error.



=item evalfile

 multi Control::Basic::evalfile (Str $filename : Grammar :$lang = Perl6)

Behaves like, and replaces Perl 5 C<do EXPR>, with optional C<$lang>
support.


=item exit 

 multi Control::Basic::exit ( Int $status = 0)

Stops all program execution, and returns C<$status> to the calling environment.


=item nothing

 multi Control::Basic::nothing ()

No operation. Literally does nothing.


=item sleep

 multi Control::Basic::sleep ( Num $for = Inf --> Num )

Attempt to sleep for up to C<$for> seconds. Implementations are obligated
to support subsecond resolutions if that is at all possible.

[Q: what about multithreading?  do we just sleep this thread?  need
to coordinate with entire async model.  -law]

=item die 

=item fail

B<TODO>: Research the exception handling system.


=back


=head2 Conversions

=over

=item bless 

 sub 

=item chr

=item ord

B<Question>: I think these should be strictly Code Point level
activitities, but I'm not sure. They likely need to be renamed, as well.


=item list

 multi Conversions::List::list ( *@list --> List )

Forces List Context on it's arguements, and returns them.


=item item

 multi Conversions::Item::item ($item --> Item )

Forces generic Item context on it's argument, and returns it.


=item :16, :8, :2, :10
 
 multi prefix:<:16> ( Str $hexstr = $+_ --> Num )
 multi prefix:<:8>  ( Str $octstr = $+_ --> Num )
 multi prefix:<:2>  ( Str $binstr = $+_ --> Num )
 multi prefix:<:10> ( Str $decstr = $+_ --> Num )
 etc.

Interprets string as a number, with a default
hexadecimal/octal/binary/decimal radix. Any radix mentioned inside the
string will be override this operator, except 0b and 0d will be interpreted
as hex digits by :16.  Returns C<undef> on failure.

These aren't really functions, syntactically, but adverbial forms that
just happen to allow a parenthesize argument.  But more typically you'll
see

    :4<222>
    :16<deadbeef>

and such.

Replaces Perl 5 C<hex> and C<oct>.


=back 


=head2 Time::Local

=over

=item gmtime 

=item localtime 

=item time




=back


=head2 I<TODO>

=over 4

=item study

=item defined

=item undef

=item item 

=item want

=item caller

=back



=head2 Obsolete

=over 4


=item dbmopen, dbmclose

 use DB_File;


=item dump

With Parrot?


=item each

See C<Hash::kv> or C<Hash::pairs> instead.


=item format, formline, write

See Exgesis 7.


=item /[msg|sem|shm].*/

 use IPC::SysV;


=item ref

Can be done with C<$var.meta.name>, but you're likely better off
performing an C<isa>, or just C<$var ~~ TYPE>.


=item reset

Was there a I<good> use for this?


=item prototype

 &func.meta.signature;


=back



=head2 Pending Apocalypse

The following functions are pending a future Apocalypse/Synopsis/p6l
Discussion before progress can be made:

=over 4

=item A/S14: Tied Variables

tie tied untie

=item A/S16: IPC / IO / Signals

-X accept alarm bind binmode chown close closedir connect eof fcntl
fileno flock getc getpeername
/[get|set][host|net|proto|serv|sock].*/ glob ioctl link listen 
lstat mkdir open opendir pipe print printf read readdir readline
readlink readpipe recv rename rewinddir rmdir seek seekdir select(both)
send setsockopt shutdown slurp socket socketpair stat symlink
syscall sysopen sysread sysseek syswrite tell telldir truncate umask
unlink utime warn

=item A/S??: OS Interaction

chroot crypt exec getlogin /[get|set][pw|gr].*/ kill setpgrp setpriority
system times

=item A/S17: Threads and Multiprocessing

fork lock wait waitpid

=back


=head1 Additions

Is your favorite function, which you spent weeks B<successfully> arguing
on perl6-language to get accepted, nowhere on this document? Have no
fear. Email rod@rodadams.net with a brief description and a link to the
thread on L<http://www.nntp.perl.org/group/perl.perl6.language>, and
it'll get listed.

Post errors to perl6-language.
