r31727 -[spec] Add Real.rand to spec, as it was already in the spectests and Rakudo. Change term:rand description to refer to it.

2010-07-16 Thread pugs-commits
Author: colomon
Date: 2010-07-16 15:15:21 +0200 (Fri, 16 Jul 2010)
New Revision: 31727

Modified:
   docs/Perl6/Spec/S32-setting-library/Numeric.pod
Log:
[spec] Add Real.rand to spec, as it was already in the spectests and Rakudo.  
Change term:rand description to refer to it.

Modified: docs/Perl6/Spec/S32-setting-library/Numeric.pod
===
--- docs/Perl6/Spec/S32-setting-library/Numeric.pod 2010-07-16 13:07:17 UTC 
(rev 31726)
+++ docs/Perl6/Spec/S32-setting-library/Numeric.pod 2010-07-16 13:15:21 UTC 
(rev 31727)
@@ -19,8 +19,8 @@
 
 Created: 19 Mar 2009 extracted from S29-functions.pod
 
-Last Modified: 11 June 2010
-Version: 9
+Last Modified: 16 July 2010
+Version: 10
 
 The document is a draft.
 
@@ -148,8 +148,8 @@
 
 Pseudo random number in range C 0 ..^ 1 .  That is, C0 is
 theoretically possible, while C1 is not.  Note that there is no
-unary Crand function in Perl 6, so just multiply Crand by your
-desired multiplier.  For picking a random integer you probably want
+unary Crand function in Perl 6, but there is a Crand method.  
+For picking a random integer you probably want
 to use something like C(1..6).pick instead.
 
 =item sqrt
@@ -272,6 +272,14 @@
 you Imust call Csrand() yourself if you wish to specify a deterministic 
seed
 (or if you wish to be differently nondeterministic).
 
+=item rand
+
+ our Num multi method rand (Real $x:) is export
+
+Pseudo random number in range C 0 ..^ $x .  That is, C0 is
+theoretically possible, while C$x is not.  For picking a random integer
+you probably want to use something like C(1..6).pick instead.
+
 =item cis
 
 our Complex multi method cis (Real $angle:) is export



Suggested magic for a .. b

2010-07-16 Thread Aaron Sherman
Oh bother, I wrote this up last night, but forgot to send it. Here y'all go:

I've been testing .. recently, and it seems, in Rakudo, to behave like
Perl 5. That is, the magic auto-increment for a .. z works very wonkily,
given any range that isn't within some very strict definitions (identical
Unicode general category, increasing, etc.) So the following:

A .. z

produces very odd results.

I'd like to suggest that we re-define this operator on strings as follows:

RESTRICTIONS:

First off, if either argument contains combining, modifying, undefined,
reserved or other codepoints which either cannot be treated as a single,
independent character or whose Unicode properties are not firmly
established in the Unicode specification, then an exception is immediately
raised. This must be done in order to assure that each character index can
be compared to each corresponding character index without the typical
Unicode ambiguities. Ligatures and other decomposable sequences are treated
by their codepoint in the current encoding, only.

Treatment of strings whose encodings differ should be possible, as all
comparisons are performed on codepoints.

If either argument is zero length, an exception is raised.

If either one argument is *, then it is assumed to stand for the largest
(RHS) or smallest (LHS) codepoint with the same Unicode general properties
as the opposite side (for each character index, if the other value is a
string of length  1).

ALGORITHM:

If both arguments are strings of non-zero length, .. will first determine
which is the shorter. This length is the significant length. Any
characters after this length in the longer sequence are ignored (return
value might be an unthrown exception in this case?)

For all remaining characters, each character is considered with respect to
its correspondingly indexed character in the other string the following
algorithm is applied to determine the range that they represent (the LHS
character is referred to as A, below and the RHS as B)

The binary Unicode general category properties of A and B are considered
from the set of major category classes:

L, M, N, P, S, Z, C

Thus the Lu property or Pe property would be considered. The total range
consists of all codepoints lying between the lower of the two codepoints and
the higher of the two, inclusive, which share either the major and minor
Unicode general category property of A and B (if there is no minor subclass,
then codepoints without a minor subclass are considered with respect to that
endpoint). The ordering is determined by the ordering of A and B.

The range is then restricted to codepoints which share the same script as A
or B.

Thus, latin a and greek lowercase pi would define a range which included
all lower-case letters from the Latin and Greek scripts that fell between
their codepoints.

Having established this range for each correspondingly indexed letter, the
range for multi-character strings is defined by a left-significant counting
sequence. For example:

Ab .. Be

defines the ranges:

A B and b c d e

This results in a counting sequence (with the most significant character on
the left) as follows:

Ab Ac Ad Ae Bb Bc Bd Be

Currently, Rakudo produces this:

Ab, Ac, Ad, Ae, Af, Ag, Ah, Ai, Aj, Ak, Al, Am,
An, Ao, Ap, Aq, Ar, As, At, Au, Av, Aw, Ax, Ay,
Az, Ba, Bb, Bc, Bd, Be

which I don't think is terribly useful.

Many useful results from this suggested change:

C .. A = C B A (Rakudo: )

( .. } = ( ) [ ] { } (because open-paren is Pe and close-brace is Ps,
therefore all Pe and Ps codepoints in the range are included).

Α .. Ω = Α Β Γ Δ Ε Ζ Η Θ Ι Κ Λ Μ Ν Ξ Ο Π Ρ Σ Τ Υ Φ Χ Ψ Ω (notice that
codepoint U+03A2 is gracefully skipped, as it is undefined and thus has no
properties).

apple .. orange = the counting sequence defined by the ranges a ..
o, p .. r, p .. a, l .. n, e .. g (notice that the string
orang will be part of the result set, but orange will not.)

In addition:

One alternative to truncation of strings of differing lengths is to extend
the sequence. For example, if we ask for a .. bc, then we might produce
a b ac bc. Where the extension is the original range plus the same range
where each element has the extended string elements concatenated. This might
even be iterated for every additional codepoint in the longer string. For
example: a .. bcd = a b ac bc acd bcd

... could have similar semantics. In the case of A, B ... C, for length 1
strings, the range A .. B is simply projected forward to until x ge C (if
A..B is increasing, le otherwise). C's properties probably should not be
considered at all. In the case of length  1 strings each character index is
projected forward independently until any one character index ge the
corresponding index in the terminator, and there is no counting:

AAA, BCD ... GGG = AAA BCD CEG

If any index in the sequence does not increment (e.g. AA, AB ... ZZ)
then there is an implication that counting is required. You should be able,
in this case, to imply 

Re: Suggested magic for a .. b

2010-07-16 Thread yary
On Fri, Jul 16, 2010 at 9:40 AM, Aaron Sherman a...@ajs.com wrote:
 For example:

 Ab .. Be

 defines the ranges:

 A B and b c d e

 This results in a counting sequence (with the most significant character on
 the left) as follows:

 Ab Ac Ad Ae Bb Bc Bd Be

 Currently, Rakudo produces this:

 Ab, Ac, Ad, Ae, Af, Ag, Ah, Ai, Aj, Ak, Al, Am,
 An, Ao, Ap, Aq, Ar, As, At, Au, Av, Aw, Ax, Ay,
 Az, Ba, Bb, Bc, Bd, Be

There is one case where Rakudo's current output makes more sense then
your proposal, and that's when the sequence is analogous to a range of
numbers in another base, and you don't want to start at the equivalent
of '' or end up at the equivalent of ''. But that's a less
usual case and there's a workaround. Using your method  example, Ab
.. Az, Ba .. Be would reproduce what Rakudo does now.

In general, I like it. Though it does mean that the sequence generated
incrementing Ab repeatedly will diverge from Ab .. Be after 4
iterations.

-y


r31735 -[spec] Say a bit about Numeric operators and Bridge.

2010-07-16 Thread pugs-commits
Author: colomon
Date: 2010-07-16 20:39:33 +0200 (Fri, 16 Jul 2010)
New Revision: 31735

Modified:
   docs/Perl6/Spec/S32-setting-library/Numeric.pod
Log:
[spec] Say a bit about Numeric operators and Bridge.

Modified: docs/Perl6/Spec/S32-setting-library/Numeric.pod
===
--- docs/Perl6/Spec/S32-setting-library/Numeric.pod 2010-07-16 18:19:27 UTC 
(rev 31734)
+++ docs/Perl6/Spec/S32-setting-library/Numeric.pod 2010-07-16 18:39:33 UTC 
(rev 31735)
@@ -56,10 +56,16 @@
 
 CNumeric is a role for everything that's a scalar number. So CNum, CInt,
 CRat, CComplex and other numeric types do that role. However it is an
-abstract interface, so C$number.WHAT will never return CNumeric. Users who
-provide their own scalar numeric types are encouraged to implement the
-CNumeric role.
+abstract interface, so C$number.WHAT will never return CNumeric. 
 
+Users who provide their own scalar numeric types are encouraged to implement 
the
+CNumeric role.  It is intended that such types such support the basic 
arithmetic
+operators to the extent possible, as well as C==.  In addition, it is hoped 
that
+comparison operators will at least return consistent results, even if there is 
no
+sensible mathemtical ordering of your type.  That allows functions like sort 
to 
+not choke and die if they are handed a value of your type.  (See also the 
CReal
+role for scalar numeric types that represent real numbers.)
+
 The following are all defined in the CNumeric role:
 
 CNumeric provides some constants in addition to the basic
@@ -201,6 +207,15 @@
 a real scalar number (i.e. neither CComplex nor vector-like). For example
 CNum, CInt, CBool and CRat implement the CReal role.
 
+Users who provide their own scalar real numeric types are encouraged to 
implement the
+CReal role.  Because all CReal types are well-ordered, it is desirable 
that any two
+CReal types be mutally compatiable, even if they are not aware of each 
other.  The
+current proposal requires you to define a CBridge method in your CReal 
type, which
+converts your type into a neutral CReal type by restating it in terms of the 
fundamental
+Perl 6 types and calling CBridge on them.  This then makes the default 
CReal methods
+and operators all work with your CReal type.  While the name of this method 
may changed,
+it is hoped that something like this will remain in the spec.
+
 =over
 
 =item Complex



Re: r31735 -[spec] Say a bit about Numeric operators and Bridge.

2010-07-16 Thread Darren Duncan

pugs-comm...@feather.perl6.nl wrote:

Author: colomon
Date: 2010-07-16 20:39:33 +0200 (Fri, 16 Jul 2010)
New Revision: 31735

Modified:
   docs/Perl6/Spec/S32-setting-library/Numeric.pod
Log:
[spec] Say a bit about Numeric operators and Bridge.

+Users who provide their own scalar real numeric types are encouraged to 
implement the
+CReal role.  Because all CReal types are well-ordered, it is desirable 
that any two
+CReal types be mutally compatiable, even if they are not aware of each 
other.  The
+current proposal requires you to define a CBridge method in your CReal 
type, which
+converts your type into a neutral CReal type by restating it in terms of the 
fundamental
+Perl 6 types and calling CBridge on them.  This then makes the default 
CReal methods
+and operators all work with your CReal type.  While the name of this method 
may changed,
+it is hoped that something like this will remain in the spec.


Is there some type or role named Bridge, such that Bridge would be casting 
as such?  Because if not, I would think you'd want the method to not be 
capitalized, unless there is some other precedent for doing so. -- Darren Duncan


Re: Suggested magic for a .. b

2010-07-16 Thread Carl Mäsak
Aaron ():
 [...]

 Many useful results from this suggested change:

 C .. A = C B A (Rakudo: )

Regardless of the other traits of your proposed semantics, I think
permitting reversed ranges such as the one above would be a mistake.

Rakudo gives the empty list for ranges whose lhs exceeds (fsvo
exceeds) its rhs, because that's the way ranges work in Perl. The
reason ranges work that way in Perl (in my understanding) is that it's
the less surprising behavior when the endpoints are determined at
runtime.

For explicitly specifying a reverse list of characters, there's still
`reverse A .. C`, which is not only a straightforward idiom and
huffmanized about right, but also good documentation for the reader.

// Carl


Re: r31735 -[spec] Say a bit about Numeric operators and Bridge.

2010-07-16 Thread Minimiscience

On 16 Jul 2010, at 14:39, pugs-comm...@feather.perl6.nl wrote:

Because all CReal types are well-ordered


Oh, they are?  Just how are we implementing that? http://en.wikipedia.org/wiki/Well-order 
 says that the de facto standard foundations of mathematics are  
insufficient to define a formula for well-ordering the reals.  Even if  
we just consider arbitrary-precision rationals, what's the least  
element of C3 ... { (2 * $^p + 2) / ($^p + 2) }?  This sequence  
consists of infinitely many rationals in which each element is less  
than its predecessor yet greater than sqrt(2), so there is no least  
element under the ≤ ordering.  If only CReal types were required to  
have a *total* ordering rather than a *well*-ordering; things would be  
so much simpler.


-- Minimiscience

r31736 -[Numeric] fix typo and a technicality pointed out by Minimiscience++

2010-07-16 Thread pugs-commits
Author: lwall
Date: 2010-07-17 00:10:05 +0200 (Sat, 17 Jul 2010)
New Revision: 31736

Modified:
   docs/Perl6/Spec/S32-setting-library/Numeric.pod
Log:
[Numeric] fix typo and a technicality pointed out by Minimiscience++


Modified: docs/Perl6/Spec/S32-setting-library/Numeric.pod
===
--- docs/Perl6/Spec/S32-setting-library/Numeric.pod 2010-07-16 18:39:33 UTC 
(rev 31735)
+++ docs/Perl6/Spec/S32-setting-library/Numeric.pod 2010-07-16 22:10:05 UTC 
(rev 31736)
@@ -208,8 +208,9 @@
 CNum, CInt, CBool and CRat implement the CReal role.
 
 Users who provide their own scalar real numeric types are encouraged to 
implement the
-CReal role.  Because all CReal types are well-ordered, it is desirable 
that any two
-CReal types be mutally compatiable, even if they are not aware of each 
other.  The
+CReal role.  Because real numbers are strictly-totally-ordered and
+CReal types try to emulate that property, it is desirable that any two
+CReal types be mutally compatible, even if they are not aware of each other. 
 The
 current proposal requires you to define a CBridge method in your CReal 
type, which
 converts your type into a neutral CReal type by restating it in terms of the 
fundamental
 Perl 6 types and calling CBridge on them.  This then makes the default 
CReal methods



r31737 -[S02,S06] change YOU_ARE_HERE to {YOU_ARE_HERE} to better represent the UNIT block

2010-07-16 Thread pugs-commits
Author: lwall
Date: 2010-07-17 00:41:33 +0200 (Sat, 17 Jul 2010)
New Revision: 31737

Modified:
   docs/Perl6/Spec/S02-bits.pod
   docs/Perl6/Spec/S06-routines.pod
Log:
[S02,S06] change YOU_ARE_HERE to {YOU_ARE_HERE} to better represent the UNIT 
block


Modified: docs/Perl6/Spec/S02-bits.pod
===
--- docs/Perl6/Spec/S02-bits.pod2010-07-16 22:10:05 UTC (rev 31736)
+++ docs/Perl6/Spec/S02-bits.pod2010-07-16 22:41:33 UTC (rev 31737)
@@ -13,8 +13,8 @@
 
 Created: 10 Aug 2004
 
-Last Modified: 11 Jul 2010
-Version: 219
+Last Modified: 16 Jul 2010
+Version: 220
 
 This document summarizes Apocalypse 2, which covers small-scale
 lexical items and typological issues.  (These Synopses also contain
@@ -2492,8 +2492,25 @@
 a CMAIN routine as documented in S06.  In this case the ordinary
 execution of the user's code is suppressed; instead, execution
 of the user's code is entirely delegated to the setting's CMAIN routine,
-which calls back to the user's lexically embedded code with CYOU_ARE_HERE.
+which calls back to the user's lexically embedded code with C{YOU_ARE_HERE}.
 
+The C{YOU_ARE_HERE} functions within the setting as a proxy for
+the user's CUNIT block, so C-n and C-p may be implemented in
+a setting with:
+
+for $*ARGFILES.lines {YOU_ARE_HERE} # -n
+map *.say, do for $*ARGFILES.lines {YOU_ARE_HERE}   # -p
+
+or
+
+map {YOU_ARE_HERE}, $*ARGFILES.lines;   # -n
+map *.say, map {YOU_ARE_HERE}, $*ARGFILES.lines;# -p
+
+and the user may use loop control phasers as if they were directly in
+the loop block.  Any COUTER in the user's code refers to the block
+outside of C{YOU_ARE_HERE}.  If used as a standalone statement,
+C{YOU_ARE_HERE} runs as if it were a bare block.
+
 Note that, since the CUNIT of an eval is the eval string itself,
 the CSETTING of an eval is the language in effect at the point
 of the eval, not the language in effect at the top of the file.

Modified: docs/Perl6/Spec/S06-routines.pod
===
--- docs/Perl6/Spec/S06-routines.pod2010-07-16 22:10:05 UTC (rev 31736)
+++ docs/Perl6/Spec/S06-routines.pod2010-07-16 22:41:33 UTC (rev 31737)
@@ -16,8 +16,8 @@
 
 Created: 21 Mar 2003
 
-Last Modified: 12 Jul 2010
-Version: 141
+Last Modified: 16 Jul 2010
+Version: 142
 
 This document summarizes Apocalypse 6, which covers subroutines and the
 new type system.
@@ -3300,26 +3300,26 @@
 of the current compilation unit.  (The C-n and C-p command-line
 switches are implemented this way.)  In this case the user's mainline
 code is not automatically executed; instead, execution is controlled
-by the setting's CMAIN routine.  That routine calls CYOU_ARE_HERE
+by the setting's CMAIN routine.  That routine calls C{YOU_ARE_HERE}
 at the point where the user's code is to be lexically inserted (in
-the abstract).  A setting may also call CYOU_ARE_HERE outside of
+the abstract).  A setting may also call C{YOU_ARE_HERE} outside of
 a CMAIN routine, in which case it functions as a normal setting,
-and the CYOU_ARE_HERE merely indicates where the user's code
+and the C{YOU_ARE_HERE} merely indicates where the user's code
 goes logically.  (Or from the compiler's point of view, which the
 lexical scope to dump a snapshot of for later use by the compiler
 as the setting for a different compilation unit.)  In this case the
 execution of the user code proceeds as normal.  In fact, the CCORE
-setting ends with a CYOU_ARE_HERE to dump the CCORE lexical
+setting ends with a C{YOU_ARE_HERE} to dump the CCORE lexical
 scope as the standard setting.  In this sense, CCORE functions as
 an ordinary prelude.
 
 If a CMAIN routine is declared both in the setting and in the
 user's code, the setting's CMAIN functions as the actual mainline
 entry point.  The user's CMAIN functions in an embedded fashion;
-the setting's invocation of CYOU_ARE_HERE functions as the main
+the setting's invocation of C{YOU_ARE_HERE} functions as the main
 invocation from the point of view of the user's code, and the
 user's CMAIN routine will be invoked at the end of each call to
-CYOU_ARE_HERE.
+C{YOU_ARE_HERE}.
 
 =head2 Implementation note on autothreading of only subs
 



Re: Suggested magic for a .. b

2010-07-16 Thread Michael Zedeler

On 2010-07-16 18:40, Aaron Sherman wrote:

Oh bother, I wrote this up last night, but forgot to send it. Here y'all go:

I've been testing .. recently, and it seems, in Rakudo, to behave like
Perl 5. That is, the magic auto-increment for a .. z works very wonkily,
given any range that isn't within some very strict definitions (identical
Unicode general category, increasing, etc.) So the following:

A .. z

produces very odd results.

I'd like to suggest that we re-define this operator on strings as follows:

[cut]

Ab .. Be

defines the ranges:

A B  andb c d e

This results in a counting sequence (with the most significant character on
the left) as follows:

Ab Ac Ad Ae Bb Bc Bd Be

Currently, Rakudo produces this:

Ab, Ac, Ad, Ae, Af, Ag, Ah, Ai, Aj, Ak, Al, Am,
An, Ao, Ap, Aq, Ar, As, At, Au, Av, Aw, Ax, Ay,
Az, Ba, Bb, Bc, Bd, Be

which I don't think is terribly useful.
   
I have been discussing the Range operator before on this list, and since 
it often becomes the topic of discussion, something must be wrong with it.


What started it all, was the intention to extend the operator, making it 
possible to evaluate it in list context. Doing so has opened pandoras 
box, because many (most? all?) solutions are inconsistent with the rule 
of least surprise.


For instance, when considering strings, writing up an expression like

'goat' ~~ 'cow' .. 'zebra'

This makes sense in most cases, because goat is lexicographically 
between cow and zebra. So we have a nice ordering of strings that even 
extends to strings of any length (note that the three words used in my 
example are 3, 4 and 5 letters). As you can see, we even have a Range 
operator in there, so everything should be fine. What breaks everything 
is that we expect the Range operator to be able to generate all values 
between the two provided endpoints. Everything goes downhill from there.


With regard to strings, lexicographical ordering is the only prevailing 
ordering we provide the developer with (apart from length which doesn't 
provide a strict ordering that is needed). So anyone using the Range 
operator would assume that when lexicographical ordering is used for 
Range membership test, it is also used for generation of its members, 
naturally leading to the infinite sequence


cow
cowa
cowaa
cowaaa
...
cowb
cowba
cowbaa

For some reason (even though Perl6 supports infinite lists) we are 
currently using a completely new construct: the domain of strings 
limited to the lenght of the longest operand. This is counter intuitive 
since


'cowbell' ~~ 'cow' .. 'zebra'

but

'cow' .. 'zebra'

does not produce 'cowbell' in list context.

Same story applies to other types that come with a natural ordering, but 
have an over countable domain. Although the solutions differ, the main 
problem is the same - they all behave counter intuitive.


5.0001 ~~ 1.1 .. 10.1

but

1.1 .. 10.1

does not (and really shouldn't!) produce 5.0001 in list context.

I'd suggest that if you want to evaluate a Range in list context, you 
may have to provide a hint to the Range generator, telling it how to 
generate subsequent values. Your suggestion that the expansion of 'Ab' 
..  'Be' should yield Ab Ac Ad Ae Bb Bc Bd Be is just an example of a 
different generator (you could call it a different implementation of ++ 
on Str types). It does look useful, but by realizing that it probably 
is, we have two candidates for how Ranges should evaluate in list context.


The same applies to Numeric types.

My suggestion is to eliminate the succ method on Rat, Complex, Real and 
Str and point people in the direction of the series operator if they 
need to generate sequences of things that are over countable.


Regards,

Michael.



Re: Suggested magic for a .. b

2010-07-16 Thread Jon Lang
Aaron Sherman wrote:
 Oh bother, I wrote this up last night, but forgot to send it. Here y'all
 go:

 I've been testing .. recently, and it seems, in Rakudo, to behave like
 Perl 5. That is, the magic auto-increment for a .. z works very
 wonkily,
 given any range that isn't within some very strict definitions (identical
 Unicode general category, increasing, etc.) So the following:

 A .. z

 produces very odd results.

Bear in mind that .. is no longer supposed to be used to generate
lists; for that, you should use   That said, that doesn't
address the issues you're raising; it merely spreads them out over two
operators (.. when doing pattern matching, and ... when doing list
generation).

Your restrictions and algorithms are a good start, IMHO; and at some
point when I have the time, energy, and know-how, I'll read through
them in detail and comment on them.  In the meantime, though, let me
point out a fairly obvious point: sometimes, I want my pattern
matching and list generation to be case-sensitive; other times, I
don't.  More generally, whatever algorithm you decide on should be
subject to tweaking by the user to more accurately reflect his
desires.  So perhaps .. and ... should have an adverb that lets
you switch case sensitivity on (if the default is off) or off (if
the default is on).  And if you do this, there should be function
forms of .. and ... for those of us who have trouble working with
the rules for applying adverbs to operators.  Likewise with other
situations where there might be more than one way to approach things.

-- 
Jonathan Dataweaver Lang


Re: Suggested magic for a .. b

2010-07-16 Thread Aaron Sherman
On Fri, Jul 16, 2010 at 1:14 PM, yary not@gmail.com wrote:

 There is one case where Rakudo's current output makes more sense then

your proposal, and that's when the sequence is analogous to a range of
 numbers in another base, and you don't want to start at the equivalent
 of '' or end up at the equivalent of ''.


If you want a range of numbers, you should be using numbers. Perl should
absolutely not try to guess that you want codepoints to appear in your
result set which were not either expressed in the input or fall between the
range of any two corresponding input codepoints.


 But that's a less
 usual case and there's a workaround. Using your method  example, Ab
 .. Az, Ba .. Be would reproduce what Rakudo does now.


Quite true.



 In general, I like it. Though it does mean that the sequence generated
 incrementing Ab repeatedly will diverge from Ab .. Be after 4
 iterations.


Also true, and I think that's a correct thing.

-- 
Aaron Sherman
Email or GTalk: a...@ajs.com
http://www.ajs.com/~ajs