Re: Next Apocalypse

2003-09-13 Thread martin
On Sat, 13 Sep 2003, Luke Palmer wrote:
> Also, the "standard library", however large or small that will be, will
> definitely be mutable at runtime.  There'll be none of that Java "you
> can't subclass String, because we think you shouldn't" crap.

Java's standard class library is a mishmash of things that represent
containers (variables) and things that represent values (and even some
broken things that try to be both), with no syntactic help to distinguish
them.  And its syntax reserves "const" but doesn't use it for anything.

As long as we have "is rw" and its friends, we can -- with suitable care --
make sure that a subclass of a value-representing class is also a
value-representing class, so there's no semantic need to say "never any
subclasses" but we can still do CSE and other neat stuff at compile time.

Of course having a "no subclasses" tag means the compiler can change a
method call into a direct subroutine call, but I would hope that method
calling will be fast enough that it won't need to.

Will we require methods in subclasses to use the same signatures as the
methods they're overriding?

-Martin

-- 
4GL ... it's code Jim, but not as we know it.




Re: Next Apocalypse

2003-09-15 Thread martin
On Mon, 15 Sep 2003, Dan Sugalski wrote:
> > Great. But will it also be possible to add methods (or modify them)
> > to an existing class at runtime?
>
> Unless the class has been explicitly closed, yes.

That strikes me as back-to-front.

The easy-to-optimise case should be the easy-to-type case; otherwise a lot
of optimisation that should be possible isn't because the programmers are
too inexperienced/lazy/confused to put the "closed" tags in.

And it would be a better chance to warn at compile time about doing things
which are potentially troublesome.

But whichever way this goes, I take it we'll have warnings like:

Changed method definition Class::foo may not take effect in
pending initialiser
 at program.pl line 9.

Overridden method definition MyClass::foo (new subclass of Class) may not
take effect in pending function bar()
 in zot() at Zot.pm line 5
 in other() at Other.pm line 10
 at program.pl line 123.




Spare brackets :-)

2003-01-27 Thread martin

This may sound like a silly idea but ...

Has anyone considered removing with the syntactic distinction between
numeric and string indexing -- that is, between array and hash lookup?

In particular, it would seem that

  %foo[$key]

would be just as easy for the compiler to grok as

  %foo{$key}

but would mean that we could stop worrying about the precedence of
postfix/infix "{", and things like

  if %test { $count++ }

would not require whitespace before the "{" to be disambiguated.

I don't have a complete solution as anonymous array and hash construction would
still need different syntaces, but has anyone else thought about this?

- Martin





Re: L2R/R2L syntax

2003-01-27 Thread martin
On Sat, 25 Jan 2003, Damian Conway wrote:
> As far as I know Larry is not planning to remove the functional
> forms of C, C, etc.
>
> Those forms may, it's true, become mere wrappers for the OO forms.
> But I confidently expect they will still be available.

Hmmm, so that means that they should be overloadable on a per-arrayish-class
basis, no?

Then what happens to

  @A = map { ! $_ } @B, @C;

when @B and @C are different classes?

Does that transmogrify into

  @A = ( @B.map { ! $_ }, @C.map { ! $_ } )

or into

  @A = [ @B, @C ] .map { ! $_ }

?

-Martin






Re: Spare brackets :-)

2003-01-29 Thread martin
>> In particular, it would seem that
>>   %foo[$key]
>> would be just as easy for the compiler to grok as
>>   %foo{$key}

On Mon, 27 Jan 2003 15:39:19 -0800, Damian Conway <[EMAIL PROTECTED]> wrote:
> Sure. But then is this:
>
> $ref[$key]
>
> an array or hash look-up???

Yes, well I suppose that could be considered one of the things I hadn't figured
out yet.

But is seems to me that if we're changing "$X[$n]" to "@X[$n]", then it would
be more consistent to change "$ref->[$key]" to "@$ref[$key]".  Except of course
that mixing prefix and postfix notation is horrible, so perhaps "$ref@[$key]" and
"$ref%[$key]". (I'd assumed that "%[" and "@[" would be single symbols?)

> Decided at runtime?

That might be OK, except (as others have pointed out) for auto-vivification,
where the object doesn't exist before we operate on it.

Maybe we would get away with the shorthand "$ref[$index]" *except* where
autovivification is desired, and then we'd have to use the long-hand
"$ref@[$index]" and "$ref%[$index]" versions?

Hm, actually, I think I could class that as a feature, if the reader --
human or compiler -- could know just by looking whether auto-viv is expected.

-Martin





Re: infectious traits and pure functions

2009-02-16 Thread Martin Kealey
I wrote:
> > In the general case, if your language has both pure and impure
> > functions, proving (at compile time) that something is not impure is an
> > NP-complete problem.

On Mon, 16 Feb 2009, Mark Biggar wrote:
> Worse it's equivalent to the halting problem (I.e., not solvable).

Quite correct, my mistake.

Please read as s/NP-complete/halting problem/g

-Martin


Re: Temporal and purity (was: Re: IO, Trees, and Time/Date)

2009-02-19 Thread Martin Kealey
On Fri, 20 Feb 2009, Timothy S. Nelson wrote:
> On Thu, 19 Feb 2009, Martin D Kealey wrote:
> > Rather, let's have immutable time "values", and methods which return other
> > "values" where various computations (*1) have been applied. Provide
> > constructors which take the Y/M/D/h/m/s/dst_now/dst_rule tuple.
>
> I followed the bits about the computations, and I think I see what
> you're saying about the constructor, but I don't know what you mean by
> 'immutable time "values"'.  Could you expand on this a bit?

We want an "Instant" class whose objects have value semantics rather than
container semantics. Because:

1. It makes them usable in "pure" code

2. "Date isa Instant" works sensibly: anywhere that expects an Instant, you
can give it a Date. (Assuming we all agree that dates start at midnight, but
then we *are* talking specifically Gregorian dates.)

(If you have container objects, that can't work, and neither can the
reverse, tempting though it is. So tempting in fact that it's part of the
Java language definition.  Uggh!)

3. Having separate writable attributes is offering someone a cannon with
which to shoot their own foot off, as far as having buggy code goes.
(Strictly, this doesn't preclude having a container object where you set the
epoch-second, or set the year, month, day, hour, minute and second all at
once, but even if they're not in the design to begin with, sometime someone
naïve is going to add them.

4. Let's face it, they're pretty small objects. They're on a par with a
"Num", and should get similar treatment.

-Martin


Re: Junction Algebra

2009-03-30 Thread Martin Kealey
On Mon, 30 Mar 2009, Mark J. Reed wrote:
> >        ( $a <= any(-1,+1) <= $b ) == ( $a <= any(-1,+1) && any(-1,+1) <= $b 
> > )
>
> Clearly, the RHS is true for $a == $b == 0, but I'm not sure the LHS
> shouldn't also be.  Isn't it just syntactic sugar for the RHS?

I suspect not. Rather I think that

$a <= any(-1,+1) <= $b

corresponds to

$tmp = any(-1,+1);
$a <= $tmp <= $b

and thence to

$tmp = any(-1,+1);
$a <= $tmp && $tmp <= $b

The more I think about this, the more I come to the conclusion that a
junction should appear to have a uniform (single) value in each
"eigenthread".

> Logically, you might want it to mean something like ∃$x: $x == any(-1,+1)
> && $a <= $x && $x <= $b, but I don't think it does.

I think that flows fairly cleanly from the Junction-isa-Object
implementation, and the way that references are taken.

This is not going to play well with subexpression folding: junctions have to
be considered "unclean", in that two junctions must not be merged even if
they're immutable and indistinguishable (except for object identity).

$a = any($x, $y);
$b = any($x, $y);
assert $a !== $b;

Earlier Moritz suggested that one could modify an external object from
within the eigenthreads to accumulate the list of eigenstates, in defiance
of having the !eigenstates() method private.

That's almost reasonable, but it assumes that eigenthreads don't work on
separate snapshot copies of the world, and that those snapshots aren't
discarded after their results are flattened by the junctive operator.

-Martin


Re: junctions and conditionals

2009-04-01 Thread Martin Kealey
On Tue, 31 Mar 2009, Jon Lang wrote:
> Another issue: what happens if conditional code mutates a junction
> that it filtered?  For example:
>
> $x = any (-5 .. 5);
> if $x > 0 { $x++ };
>
> At this point, which of the following does $x equal?
>
> any(-4 .. 6) # the original junction gets mutated
> any(-5 .. 0, 2 .. 6) # the filtered part of the original junction
> gets mutated; the rest is untouched
> any(2 .. 6) # the filtered part of the original junction gets
> mutated; the rest is lost

I choose #3.

Reality can only take one path through a conditional; which one depends
on the one/any/all/none binding of the junction.

Once you've passed the conditional, you have:

one -> single matching value (no longer a junction)
any -> filtered list
all -> original junction
none -> empty (*1)

The "threading" is an implementation detail; the important thing is a
junction is collection of values and a smart way of rewriting
expressions that contain them, with special treatment for comparison
operators (or indeed anything that forces Boolean content):

$x CMP all($y,$z)   $x CMP $y && $x CMP $z
$x CMP one($y,$z)   $x CMP $y ^^ $x CMP $z  (*2)
$x CMP none($y,$z)  all($x !CMP $y, $x !CMP $z)
$x CMP any($y,$z)   $x !CMP none($y, $x)

$x OP all($y,$z)all( $x OP $y, $x OP $z)
$x OP any($y,$z)any( $x OP $y, $x OP $z)
$x OP one($y,$z)one( $x OP $y, $x OP $z)
$x OP none($y,$z)   none($x OP $y, $x OP $z)

-Martin

(*1: An argument could be made that "none" should leave the junction alone,
the same as "all".)

(*2: I would like to suggest that the semantics of "one" be changed to mean
"pick one" (randomly) rather than "exactly one". In this respect it
would be the same as "any" except it wouldn't have the overhead of
filtering *every* match, just at least one.)



Announcing Rakudo Perl 6 Development release #26 ("Amsterdam")

2010-02-19 Thread Martin Berends
On behalf of the Rakudo development team, I'm pleased to announce the
February 2010 development release of Rakudo Perl #26 "Amsterdam".
Rakudo is an implementation of Perl 6 on the Parrot Virtual Machine
(see http://www.parrot.org).  The tarball for the February 2010 release
is available from http://github.com/rakudo/rakudo/downloads .

Rakudo Perl follows a monthly release cycle, with each release named
after a Perl Mongers group.  The February 2010 release is code named
"Amsterdam" for the largest chapter of the Dutch Perl Mongers.  Perl
development enjoys considerable support from the Netherlands, with
donations from NLNet, and hosting of the feather machines and several
important Perl 6 web domains and sites.

This release is the first release based on the new branch of
Rakudo development begun in October 2009.  The branch refactors 
the grammar, object metamodel, and a number of other key features 
to improve compatibility with the Perl 6 specification and give us
a more solid foundation to build on.  Indeed, in many ways the 
development of this new branch has driven important changes to the 
specification in the areas of lists, iterators, slices, and much
more.

However, this release contains a number of significant regressions
from previous compiler releases.  We expect to have full functionality
restored in this branch in the next couple of weeks.  For those
looking to explore a wide variety of Perl 6 features or who have
applications developed using previous releases of Rakudo, you may
wish to continue to use the January 2010 (#25, "Minneapolis") 
release.

This release of Rakudo requires Parrot 2.1.0.  One must still
perform "make install" in the Rakudo directory before the "perl6"
executable will run anywhere other than the Rakudo build directory.
For the latest information on building and using Rakudo Perl, see the
README file section titled "Building and invoking Rakudo".

Some of the specific changes and improvements occuring with this
release include:

*  Now using nqp-rx for parsing and actions

*  Grammar is much closer to STD in many aspects, and makes use of
   protoregexes

*  Closures and lexical/contextual variable declarations in regexes work

*  Laziness is implemented

*  All class and role construction is handled through the meta-model

The Perl 6 language specification is still in flux. Please take note of
the
following changes, which might affect your existing programs. In the next
release of Rakudo, the deprecated features will likely be gone.

* The root of the object hierarchy has been changed from 'Object' to 'Mu'.
  The type 'Object' goes away.

* The term 'undef' is gone. You can replace it with other constructs,
  depending on context:
- 'Nil' is undefined in item context, and the empty list in list
context
- 'Mu' is the most general undefined value which does not flatten in
list
  context
- as a smart matching target, you can replace '$obj ~~ undef'
  by '$obj ~~ *.notdef'

* Builtin classes will derive from 'Cool' (which itself derives from
'Any').
  Most of the builtin methods on these classes will be defined in the
  'Cool' class instead of 'Any'.  See Synopsis 2 for more details.

* Starting with the this release, release identifiers are given
  as ".MM" instead of "-MM" (dot instead of hyphen).
  This is intended to simplify building and packaging for other
  distribution systems.

The development team thanks all of our contributors and sponsors for
making Rakudo Perl possible.  If you would like to contribute,
see http://rakudo.org/how-to-help , ask on the perl6-compi...@perl.org
mailing list, or ask on IRC #perl6 on freenode.

The next release of Rakudo (#27) is scheduled for March 18, 2010.
A list of the other planned release dates and codenames for 2010 is
available in the "docs/release_guide.pod" file.  In general, Rakudo
development releases are scheduled to occur two days after each
Parrot monthly release.  Parrot releases the third Tuesday of each month.

Have fun!

[1] http://www.frozen-perl.org/
[2] http://use.perl.org/~pmichaud/journal/39779
[3] http://use.perl.org/~pmichaud/journal/39874


Re: ./method

2005-05-19 Thread Martin Kuehl
On 5/15/05, Juerd <[EMAIL PROTECTED]> wrote:
> A few days ago, when typing ./pugs,... You can guess the rest :)
> 
> I suggest
> 
> ./method
> 
> to mean $?SELF.method, and
> 
> ../method
> 
> to mean $?SELF.SUPER::method, or however that's normally written.
> 
> This syntax doesn't clash with anything, doesn't introduce whitespace
> asymmetry and doesn't require anything other than ASCII.
> 
> If you go back to what inspired it, the mnemonic becomes clear: unix
> filesystems. However, it's far fetched and none of the people I've asked
> think it's a good one. Still, it works for me and may even work in
> textbooks.
> 
> The best thing about this new proposal is that everyone so far agrees
> that it's feasible, easy to write and not ugly.

I have tried, but I can't make myself like it.  The syntax surely is feasible,
easy to write and not ugly, but it makes me think about objects in terms
of pathnames with . meaning $?SELF and / where "other languages" use
the dot, except I can't use it for anything but a method call on the implicit
receiver.
It also makes me want to propose zsh-extended-glob-compatibility syntax
for objects so I can have method/attribute slices, and then I end up curled
up in a corner, scared and shaking.

But maybe I should just get used to that. :-)

> Juerd

Martin


Re: [perl6/specs] 5277fe: Add expmod and is-prime as built-ins in Int

2012-09-20 Thread Martin Kealey
On Thu, 20 Sep 2012, Stephen Pollei wrote:
> If it says it might be prime it's
> about a 50% 50% split if it's correct.

According to Wolfram, it's 75/25; so a positive result after 10 iterations
leaves about a one-in-a-million chance of being composite (more precisely,
one in 1048576).

> multi method is-prime ( Int $x: Int $tries = 100) is export
> should also at least document that tries is never a negative number,
> or if it is that it has same behaviour as zero.

Logically if "tries" is zero, is-prime shouldn't do any testing at all, and
should always return "true". (There's a chance it might be prime!)

If "tries" is negative, which idiom should we follow:
 * a range iterator (empty, zero tries, return true)
 * arrays etc count-backwards-from-the-end (keep trying until certain)
 * a logical ambiguity (return Any(true,false))
 * you-get-what-you-ask-for (return "PEBKAC":but(false) )
 * a logical contradiction (return an unthrown exception)
 * a formal error (throw an exception)

-Martin


Re: Recommended Perl 6 best practices?

2008-09-30 Thread Martin D Kealey

On Tue, 30 Sep 2008, Patrick R. Michaud wrote:
> Just for pedantic clarity, what C< $directive ne 'VAR' & 'LOOP' & 'IF' >
> really gives is
>
> all( $directive ne 'VAR', $directive ne 'LOOP', $directive ne 'IF' )
>
> In other words, the result of the expression is an all() Junction. In
> boolean context this would indeed evaluate to false if $directive has any
> of the values 'VAR', 'LOOP', or 'IF'.

Does it have to be this way?

In formal logic, distributing a negation over a disjunction products a
conjunction and vice versa.

Perl has a long tradition of dwimmery, so why are we taking a literal
"distribute all symbols the same way" approach?

Surely it is more important that ($a ne $b) should be equivalent to not( $a
eq $b ) regardless of whether either variable contains a junction?

As a start, perhaps we should be marking certain operators (not ! none() !=
ne) with whether they represent a logical inversion, so that conjunctions
and disjunctions can be alternated?

-Martin Kealey


Re: S16: chown, chmod

2008-12-01 Thread Martin D Kealey
On Tue, 25 Nov 2008, Dave Whipp wrote:
> Brandon S. Allbery KF8NH wrote:
> > Still misunderstanding, I think.  Yes, it will fail anyway, but in the
> > general case you're checking to see if as a privileged process it is safe to
> > operate on a given file.
>
> I'd actually been thinking that one would use the check in the opposite
> direction:
>
> if need_priv() {
>   sudo { ... }; # might ask user for passwd
> }
> else {
>   ...
> }
>
> But then I'm not an expert in this area: I just want an API that makes it easy
> to hack simple scripts that do what I need. It was C that I really
> wanted to improve the API for; I touched C only because it was adjacent
> in the POD, and it seems reasonable for the two functions/methods to have
> similar look&feel.

I've been wondering about this idiom, used when copying files:

  my $s = POSIX::stat($filename1);
  POSIX_extensions::setstat($filename2, $s);

where setstat() is a combination of chown, chmod and utime -- in the right
order to make them work as best as possible. The type of check contemplated
in this thread would then come in handy for implementing setstat().

If an unprivileged user can give away a file then that change has to be the
last thing done to the file. Otherwise changing the permissions should be
done last, so as to maintain the set*id bits. So I would envisage it would
look a bit like this (please excuse my obvious hand-waving pseudocode):

sub setstat(String|File $filename, StatBuf $stat) {
  use fatal :everything;

  if $stat.uid != any(POSIX::getuid(), POSIX::geteuid()) |
 $stat.gid != any(POSIX::getgid(), POSIX::getegid(), POSIX::getgroups()) {

# we need to give the file away

my $caps = POSIX_1e::capget();

if $caps.CAP_FOWNER {
  # we're privileged, so it *should* just work.
  POSIX::chown $filename, $stat.uid, $stat.gid;
  POSIX::chmod $filename, Fcntl::ST_PERM($stat.mode);
  POSIX::utime $filename, $stat.mtime, $stat.atime;
  return;
}
if $caps.CAP_CHOWN | !chown.need_priv() {
  # we have enough privilege to give the file away, but not enough to
  # touch it after we've done so.
  POSIX::chmod $filename, Fcntl::ST_PERM($stat.mode);
  POSIX::utime $filename, $stat.mtime, $stat.atime;
  POSIX::chown $filename, $stat.uid, $stat.gid;
  return;
}
if catching_exception(IO_error) {
  throw IO_error(EPERM, $filename, "Can't give file away");
}
  }
  # can't (or don't need to) give file away
  POSIX::chmod $filename, Fcntl::ST_PERM($stat.mode);
  POSIX::utime $filename, $stat.mtime, $stat.atime;
}

-Martin


Re: RFD: Built-in testing

2009-01-28 Thread Martin D Kealey

On Wed, 21 Jan 2009, Damian Conway wrote:
> > Maybe something in all caps. For what it's worth, :OK<> can be typed
> > with one hand while the other holds down the shift key. :)
>
> Typical right-hander fascism!

On the other hands we have :QA ... which also so happens to be an apposite
abbreviation. :-)

-Martin


Re: infectious traits and pure functions

2009-02-16 Thread Martin D Kealey
On Fri, 13 Feb 2009, Jon Lang wrote:
> In reading about functional programming, I ran across the concept of
> the "pure function" - i.e., a function that doesn't produce side
> effects.
[...]
> It occurred to me that this business of marking functions as pure could be
> done in perl by means of traits

Excellent plan.

But it's actually impurity that is infectious -- an impure function being
any function that might modify an object whose lifetime exceeds the
invocation of the function, either directly or by calling another impure
function. In the simple case that devolves to "you're impure if you call
another impure function, or modify anything in an outer scope".

But if you have objects and nested functions, the exact inference rule gets
a whole lot more complicated. With exceptions, threads and co-routines it's a
nightmare. In the general case, if your language has both pure and impure
functions, proving (at compile time) that something is not impure is an
NP-complete problem.

So you really want the programmer to mark them for you, and to have run-time
checking to make sure assumptions are not violated. And to encourage
efficiency generally, you want the Huffman coding for "pure" to be shorter
than the Huffman coding for "impure", or better still, "pure by default".

Perhaps anonymous code using the arrow notation should be implicitly
":pure"?


Another approach would be to treat purity like class finalization: start by
assuming you have pure functions, but go back and regenerate them if you
discover that a sub-function somewhere is actually impure. It won't be
trivial, given that you'll have to restart the regenerated code somewhere in
the middle.


Something else to be considered: we're close to reaching the limit on CPU
clock speed -- maybe only one more order of magnitude over the next couple
of decades. From here on the big gains will be from packing ever more cores
into a CPU, and development massively parallel software to take advantage of
them.

Applicative languages have a huge head-start on that; their no-overwrite
rule ("there are no variables, only values") means that data-flow
dependencies are *always* obvious, so very fine-grained parallel scheduling
can be used get a performance gain from every extra hyperthread (*1).

Although Perl6 will get quite a boost from various code migration
techniques, probably the biggest win will be from such implicit massive
micro-threading. If Perl6 can dispatch lots of threads all the time, not
just with "map" or "grep", then it will make the best possible use of the
available hardware.

However for this to be possible, just being "pure" won't be enough. It will
also need:

(A) cacheable functions whose return value depend only on the declared
parameters (this is orthogonal to not modifying the external environment);
and

(B) truly immutable objects, and declarative ways to guarantee them in all
contexts, such as:

* immutable function parameters (that can't be changed by the function)

* constant function parameters (that can't be changed by someone else 
while the function is looking at them, even by other threads or coroutines)

    * deep auto-cloning mutable "container" objects into immutable "value" 
ones

* auto-boxing immutable "value" objects into "container" objects


-Martin

(*1: Google for the report by G Y Matthews (Sydney University, 1994) on
reformulating the "Magma" mathematical research language as an applicative
language.)


Re: infectious traits and pure functions

2009-02-16 Thread Martin D Kealey
On Mon, 16 Feb 2009, Jon Lang wrote:
> if there's any doubt about the matter (e.g., conclusively proving or
> disproving purity would be NP-complete or a halting problem), then

Deciding whether you have a halting problem IS a halting problem... :-)

-Martin


Re: Detecting side-effects in Perl 6 (Was: Re: infectious traits and pure functions)

2009-02-17 Thread Martin D Kealey
On Tue, 17 Feb 2009, TSa wrote:
> I fully agree that immutability is not a property of types in a signature.
> But a signature should have a purity lock :(Int $i is pure) that snapshots
> an object state
 [...]
> Note that this purity lock doesn't lock the outer object. It is only
> affecting the inner scope controlled by the signature. So there have to be
> extra means of snapshot generation if a mutable object shall be given e.g.
> to multiple invocations with the same snapshot state. This is no problem
> for code downstream of a purity lock because snapshotting a pure object is
> a no-op.

I like the way this is going; ".snapshot" works like ".deepclone" when
you have an ordinary object, but like ".self" on one that already has a
purity lock, OR any time you can prove that the object is actually at
its end of life (*1).


An important class of optimizations in the implementation of pure functional
languages is the destructive re-use of object that have reached their end of
life according to the data-flow analysis; they can be reused to hold some
subsequent value, most typically by doing an in-place update.

So you need an operation that changes a snapshot back into live object.


It's also going to be important that "snapshot" do as little work as
possible even when objects get handed around by impure code; to this end it
would be really useful to be able to pass snapshots to impure code and
guarantee that they won't get mangled, so they can later be passed to more
pure code (*2).


Question: does/should MMD differentiate between :ro and :rw parameters or
invocants that are otherwise identical?

-Martin

*1: actually it's a bit more complicated; a mutable object can be re-tagged
as immutable iff it's at end-of-life according to data-flow analysis AND all
its contained sub-objects are either already immutable or can in turn be
re-tagged as immutable. Otherwise it has to make a shallow clone, and the
process repeated recursively for all contained mutable objects.

*2: There are at least three ways of doing this:

  1. When re-tagging an immutable object as mutable, make a deep clone.

  2. When re-tagging an immutable object as mutable, make a shallow clone.
Any time subsequently an immutable sub-object is about to be used an a
potentially mutating way, re-tag or clone it too.

  3. Wrap the object in a new proxy (*3) object, that defers the cloning
until its actually needed. The big win on this is that if you subsequently
"snapshot" the proxy, it just gives you back the original object.

Possibly methods 2 & 3 can be combined into a self-mutating proxy that
becomes the clone when needed.

*3: I call it a proxy because it defers all non-mutating method calls to the
original object, and for the mutating ones, does the clone thing and then
defers the method to the clone. Which might be itself.


Re: IO, Trees, and Time/Date

2009-02-18 Thread Martin D Kealey
On Wed, 18 Feb 2009, Timothy S. Nelson wrote:
> I'll try and design an API that does what DateTime does, but:

> 1. Uses more variables, of which I expect the getters and setters to be
> overridden.

Please let's NOT have setters on "time" objects.  They're a source of subtle
bugs in such client code AND having mutable objects means you can't use them
in otherwise pure code. (See the separate thread on immutability and
purity.)

Rather, let's have immutable time "values", and methods which return other
"values" where various computations (*1) have been applied. Provide
constructors which take the Y/M/D/h/m/s/dst_now/dst_rule tuple.


And please let's not have any implied "default" timezone. That's not to say
it has to be difficult or cumbersome, just explicit, perhaps something like
one of these:

  my &localtime = DateTime::Gregorian.localize( :host_default );
  my &localtime = DateTime::Gregorian.localize( :user_env );
  my &localtime = DateTime::Gregorian.localize( 
:http_client(%http_client_headers) );
  my &localtime = DateTime::Gregorian.localize( :db_server($odbc_handle) );
  my &gmtime= DateTime::Gregorian.localize( :utc );
  my &swatch= DateTime::Gregorian.localize( :tz('Europe/Geneva'), :no_dst );

-Martin


*1: Operations on localtime objects involve differences, offsets and
baselines, expressed in a range of units.

The core units are seconds, minutes and days which are almost-but-not-quite
exact multiples of each other (consider leap seconds (*2) and daylight
saving). It is up to the client code to choose whether to treat an "hour"
offset as exactly 1/24 day or as exactly 60 minutes. If you want a
sunrise-based local time then that's a different library entirely.

In the Gregorian and Julian calendars a "year" is an exact multiple of a
"month", which is not an exact multiple of any core unit.

A true astronomical calendar will take a "lunar month" to be ~2.551E6
seconds and a "solar year" to be ~3.1557E7 seconds; a tabular calendar will
need them to be yet more separate offset types, and a separate library.


*2: Or not, if you're on a POSIX host, in which case you sometimes get a
peculiar "second" that takes twice as long as most, while a "minute" is
always and precisely 60 "seconds".


Re: Temporal changes (was: Re: r25445 - docs/Perl6/Spec/S32-setting-library)

2009-02-22 Thread Martin D Kealey
On Fri, 20 Feb 2009, Dave Rolsky wrote:
> > > Renamed Temporal::Instant to Temporal::DateTime
> >
> > Hmm.  We had some mailing list discussion about this, and agreed on
> > Instant.  I'd like to see your reasons in favour of DateTime.
>
> Because DateTime makes sense and is a clear description of what the thing
> is. Instant is incredibly ambiguous, and not a common term for such
> things.

I think people are starting to argue at cross purposes here.

An instant and a date-time are NOT the same thing.

Barring limitations imposed by the speed of light and aberrations caused by
relativity, and an instant occurs everyone at the same time.

A date-time, if it's really true to its name, represents some 40-ish
different instants, depending on which timezone it's interpreted in.


At some point you have to decide which fictions are useful vs where you
really need to hold out for reality.

* First fiction: the speed of light is infinite, so instants really are
universal. Unless you're writing GPS control software, you're probably OK
with this.

* Second fiction: the earth rotates at exactly 1/1440 rpm, so UT1=UT.
POSIX's "epoch seconds" pretty much enforce belief in this, so if you don't
want to believe it, you're going to have to build your own time libraries
from scratch.

* Third fiction: the day matches the rotation of the earth. In some places
the law requires you both to believe and disbelieve this simultaneously.
(For example, it may require that you're billed 10 minutes for a phone call
that started at 01:55 and finished at 03:05.)

* Fourth fiction: it's legally the same time everywhere on earth, especially
for registration of births, deaths and marriages. (For example, if I move
from my native New Zealand to, Hawaii, I will 23 hours older at my next
legal birthday than I would be if I remained in NZ. Probably I'd be a day
younger when I die too.)

* Fifth fiction: everyone speaks English.


It seems there is scope for multiple types, starting with Instants (which
must believe fiction 1 and may or may not believe fiction 2), DateTime
(which is agnostic about fiction 3), and "Localtime" and "Date" (which
believe fictions 3 and 4).

For each of these you have corresponding variants of Duration.

So my question is, which of these fictions should the core temporal type(s)
believe or disbelieve? Then we should name them appropriately.

-Martin

PS: IMHO core types should believe 1 & 2, and disbelieve 3 & 4, and avoid
doing anything that depends on believing 5.


Re: Temporal changes (was: Re: r25445 - docs/Perl6/Spec/S32-setting-library)

2009-02-22 Thread Martin D Kealey
On Mon, 23 Feb 2009, Timothy S. Nelson wrote:
> > > > Renamed Temporal::Instant to Temporal::DateTime
> > >
> > >   Hmm.  We had some mailing list discussion about this, and agreed on
> > > Instant.  I'd like to see your reasons in favour of DateTime.
> >
> > Because DateTime makes sense and is a clear description of what the thing
> > is. Instant is incredibly ambiguous, and not a common term for such things.
>
> Hmm.  Ah, I can see why it's ambiguous.  For those who missed it, think of
> what "instant" means in the context of "Instant coffee".  I think I still
> slightly prefer "instant", but I don't mind much any more :).

Ah, we want a noun that isn't readily confused as an adjective.

Suitable terms might include: Instant Jiffy Juncture Moment Occasion Snap Tick 
...

-Martin


Re: Signals question for S16: IPC / IO / Signals

2009-02-23 Thread Martin D Kealey
On Mon, 23 Feb 2009, Timothy S. Nelson wrote:
> I have a quick question here.  S16 claims to be about IPC, IO, and
> Signals.  So far, it's mostly about IO.  My question is, is it intended
> that IPC and/or signals be part of the core, or should they be converted
> to addons like Form.pm?

Conceptually I think they should all go in add-on(s), however I suspect that
when an exception is thrown inside a signal handler, cleanly unwinding the
call chain will need special support in the core.

That's not to say that methods for setting the signal handler needs to be in
the core though, just the low-level code that receives signals and arranges
not to leave a (broken) partially-formed call frame in the chain while
setting up a call frame to invoke the handler function.

-Martin


Re: Comparing inexact values (was "Re: Temporal changes")

2009-02-24 Thread Martin D Kealey
On Tue, 24 Feb 2009, Jon Lang wrote:
>   $y ± 5  # same as ($y - 5) | ($y + 5)
>   $y within 5 # same as ($y - 5) .. ($y + 5)

I suspect that we're running against Huffman here, given the likely
usage -- ranges *should* be used at pretty much every floating point
"equality" test, whereas "any(-x,+x)" would mostly be useful for
expressing solutions to polynomials.

Perhaps we could define infix:± as a range generator and prefix:± as a
set generator:

  $y + ±5   # same as ($y - 5) | ($y + 5) (also same as $y - ±5)
  $y ± 5# same as ($y - 5) .. ($y + 5)

-Martin


Re: Comparing inexact values (was "Re: Temporal changes")

2009-02-24 Thread Martin D Kealey
On Wed, 25 Feb 2009, I wrote:
>   $y + ±5   # same as ($y - 5) | ($y + 5)   (also same as $y - ±5)
>   $y ± 5# same as ($y - 5) .. ($y + 5)

A further question: should such ranges be [closed], (open) or [half-open)?

I would argue for half-open because then exactly one of a set of consecutive
ranges will match; back to the original question, I'd only expect one match
from:

$time ~~ $date-yesterday
$time ~~ $date-today
$time ~~ $date-tomorrow

even if $time falls precisely on midnight.

-Martin


Re: r25490 - docs/Perl6/Spec

2009-02-25 Thread Martin D Kealey
On Wed, 25 Feb 2009, Timothy S. Nelson wrote:
> I'm in favour of retaining the $[ functionality, but lets give it some
> name like $*INDEX_BEGINNING or something like that, so that it's quite
> long for people to type :).

Surely the interpretation of the index should be up to each array-type?

  role OffsetArray[::ElementType = Object;; int $MinIndex = 1]
  {
is Array;
has ElementType @.contents;
method circumflex:? [ ] ? (int $index where { $_ >= $MinIndex } ) {
  return @.contents[$index - $MinIndex];
}
  }

-Martin


Re: Comparing inexact values (was "Re: Temporal changes")

2009-02-26 Thread Martin D Kealey
On Thu, 26 Feb 2009, Jon Lang wrote:
> asin is not the inverse function of sin, although it's probably as close
> as you can get.  And even there, some sort of compiler optimization could
> potentially be done, replacing the composition of asin and sin (both of
> which have the potential to intensify error) with a normalization of the
> value into the -pi ..^ pi range (which might also introduce error).

Hmmm ... the normal mathematical range of arc-sine is (-π,+π], rather than
[-π,+π), especially where complex numbers are concerned: arg(-1) == +π.
(Well, so much for consistently using lower half-open ranges.)

-Martin


Re: r25490 - docs/Perl6/Spec

2009-02-26 Thread Martin D Kealey
On Thu, 26 Feb 2009, Martin D Kealey wrote:
> On Wed, 25 Feb 2009, Timothy S. Nelson wrote:
> > I'm in favour of retaining the $[ functionality, but lets give it some
> > name like $*INDEX_BEGINNING or something like that, so that it's quite
> > long for people to type :).
>
> Surely the interpretation of the index should be up to each array-type?
>
>  role OffsetArray[::ElementType = Object;; int $MinIndex = 1]
>  { [...] }

On Wed, 26 Feb 2009, Larry Wall wrote:
> Oops, too late, by about 23 months.  Please see S09.

Aah yes! The hash-like syntax is much nicer!

S09 (http://perlcabal.org/syn/S09.html#User-defined_array_indexing) saith:
> User-defined array indexing
>
> Any array may also be given a second set of user-defined indices, which need
> not be zero-based, monotonic, or even integers. Whereas standard array
> indices always start at zero, user-defined indices may start at any finite
> value of any enumerable type. Standard indices are always contiguous, but
> user-defined indices need only be distinct and in an enumerable sequence.

But if the indexes are floating point values, do they have error margins?
*Should* they have error margins?

my @labels{ atan(1)*2, exp(1), (1+sqrt(5))/2 } = < pi e golden-mean >;

> To define a set of user-defined indices, specify an explicit or enumerable
> list of the indices of each dimension (or the name of an enumerable type) in
> a set of curly braces immediately after the array name:
>
> my @dwarves{ 1..7 };
> my @seasons{  };
>
> my enum Months
> «:Jan(1) Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec»;
>
> my @calendar{ Months; 1..31; 9..12,14..17 };# Business hours only

Hmmm, that reminds me, I was going to ask about enum types that have
implicit modulus:

my enum Season «Spring Summer Autumn Winter»;
my Season $s = Winter;
++$s;
assert($s == Spring);

-Martin


Re: r25573 - in docs/Perl6/Spec: . S32-setting-library

2009-02-26 Thread Martin D Kealey
On Thu, 26 Feb 2009, pugs-comm...@feather.perl6.nl wrote:
> +The exceptions are:
> +
> + Signal   Action   R Comment
> + --
> + ControlExceptionSigHUPTerm? Hangup detected on controlling terminal 
> or death of controlling process
[...]
> + ControlExceptionSigCHLD   Ign ? Child stopped or terminated
[...]
> + ControlExceptionSigURGIgn ? Urgent condition on socket (4.2BSD)
[...]
> + ControlExceptionSigWINCH  Ign ? Window resize signal (4.3BSD, Sun)
[...]
> +XXX I'm unsure how the actions in the table above can be made to make sense. 
>  The Ign
> +actions are already dealt with because %SIG{CHLD}.exception already defaults 
> to undef.
> +The Term action will probably be self-solving (ie. will terminate the 
> process).  The
> +others I'm just plain unsure about.  XXX

That looks a lot like a mangled version of "man 7 signal" from Linux.

IMHO the default action shouldn't be specified at all by the Perl standard;
it should simply refer to the appropriate external standard.


In POSIX the settings "terminate", "ignore", "catch" and "default" have
3½ distinct meanings.  For *most* signals "default" is the same as
"terminate" (sometimes with a core), but not for all.

In particular, for SIGCHLD, if you "ignore" it, the "wait" call will
always fail (having delayed until all child processes have exited),
whereas if you leave it as "default", your process will still ignore it,
but "wait" will work properly.

On some implementations SIGUSR1 and/or SIGUSR2 are ignored by default.

Core dumps are subject to ulimit controls, even when the signal in question
would normally trigger them.

-Martin


Re: .map/.reduce with larger arity

2009-03-09 Thread Martin D Kealey
On Mon, 9 Mar 2009, Larry Wall wrote:

> the only difference between C and C is that you can only use
> C at the start of a statement.  But we're more liberal about where
> statements are expected in Perl 6, so you can say things like:
>
> my @results = do for @list -> $x {...};
> my @results = (for @list -> $x {...});
>
> and either of those is equivalent to:
>
> my @results = map -> $x {...}, @list;
>
> I also Officially Don't Care if you use map in a void context. :)

(Good.)

 Maybe we should just treat "map" as a synonym for "for". 


I'd like to be able to use grep, map, etc in a currying fashion. Can I do:

my &square_list := -> $x { $x * $x }.map();

And if so, what is the signature of &square_list ?

Maybe that's why there's a difference between "for" and "map"

@list = @array.map(&code);

&iterator = &code.for($signature);
@list = iterator(@list);

But I suspect they should logically be the other way around:

&iterator = &code.map($signature);
@list = iterator(@list);

@list = @array.for(&code);

-Martin


Re: Junction Algebra

2009-03-30 Thread Martin D Kealey
On Mon, 30 Mar 2009, Jon Lang wrote:
> Here's another useful one:
>
> any($x) eqv all($x) eqv one($x) eqv $x
>
> but:
>
> none($x) !eqv $x
>
> That is, applying any, all, or one to a one-item list produces the
> equivalent to a single item.  For an empty list: any() eqv all() eqv
> ().  But what about one() and none()?

It seems to me that "one" is out of step with the "scalarness" of junctions;
it implies that you have to look for two things, firstly that there is some
value in the eigenstates that satisfies whatever condition, and secondly
that every other value does not.

I suspect that the confusion arises because the original intention would
have been to have something along the lines of:

none === !any
something === !all

except that "one" doesn't fit the bill as "something".

But back to the original question, since "none" is just a funny spelling for
"!any", their mutual combination can be flattened accordingly:

   none($a, any($b, $c)) == none($a, $b, $c)

And (given a suitable interpretation of a monadic "none"):

   all($a, none($b, $c)) == all($a, none($b), none($c))

Question:

Or in general, it doesn't matter how many times you mention a simple
scalar in an expression, it always has the same value, so that

( $a <= $x <= $b ) == ( $a <= $x && $x <= $b )

always holds true.

However I suspect that if $x = any(-1, +1) this may no longer be the case.

This would certainly be false:

( $a <= any(-1,+1) <= $b ) == ( $a <= any(-1,+1) && any(-1,+1) <= $b )

Consider if $a and $b are both 0 ...

For this to work it seems that the auto-threading logically must reach back
to the point where the junction is created, or at least to be tied to the
identity of the junction in some way. Which latter would imply that

any($a, $b) !== any($a, $b)

There must be a logical way out, but how? Any other comments?

What about:

$x = any(-1,+1);

$x < $x and die;
# must not happen (same eigenstate must
# be used on both sides of '<' ?)

$x < $x.eigenstates.any() or die;
# matches for "-1 < +1"

-Martin


Re: [Fwd: Re: junctions and conditionals]

2009-04-01 Thread Martin D Kealey
On Wed, 1 Apr 2009, Richard Hainsworth wrote:
> A closer examination of Martin's message indicates that he tends to think
> that hitting a junction ought to thread the entire program throughout the
> rest of the lifespan of said junction

Yes -- and well put, thank-you.

The trick is that since conditionals generally force full or partial
resolution on junctions, that lifetime won't tend to be very long.

Re: Tsa's comment about junctions being "value types". In principle I agree,
except that the value semantics are only within the eigenthreads; outside
that, they are collections of indeterminate state. Indeterminate states
aren't sufficiently "value-like" to justify "constant folding".

-Martin


Re: simultaneous conditions in junctions

2009-04-01 Thread Martin D Kealey

On Wed, 1 Apr 2009, John Macdonald wrote:
> If I understand correctly, (which is by no means assured) a function
> call with a junction as an argument generally acts as if it were
> autothreaded.  So:
>
>   $x = any(1,2,3);
>   $y = f($x);
>
> should work like:
>
> $y = any( f(1), f(2), f(3) );
>
> Right?

In general yes.

However if "f" involves some kind of "truth inversion" then logically

f(any(@x)) == all(map.assuming(&f).(@x))
and
f(all(@x)) == any(map.assuming(&f).(@x))

I have in mind something like these in the "standard preamble":

prefix:«!»(Bool)   does(junctive_inversion)
prefix:«not»(Bool) does(junctive_inversion)
infix:«ne»(String,String)  does(junctive_inversion)
infix:«!=»(Num,Num)does(junctive_inversion)
infix:«!==»(Object,Object) does(junctive_inversion)

(Excuse the rather lose syntax, but I hope you get the idea.)

-Martin


Re: Why pass by reference?

2009-06-18 Thread Martin D Kealey

> Matthew Walton wrote:
> > If a user of your API contrives to make it change while you're
> > running, that's their own foot they've just shot, because they can
> > look at the signature and know the semantics of the parameter
> > passing being used and know that if they change the value externally
> > before you return Bad Things Could Happen.
>
On Tue, 16 Jun 2009, TSa wrote:
> I agree that the caller is responsible for the constness of the value
> he gives to a function. With this we get the best performance.

At the language level this is wrong. Programmers are BAD at this sort of
thing, unless the compiler *always* has enough to throw a compile-time
error, and even then it's dicey because we may defer compilation.

It seems to me this is pushing something onto the author of the caller
that they shouldn't have to deal with, especially when you consider that
the parameter they're passing into the function may come from somewhere
else, which hasn't been made -- and indeed CAN'T be made -- to promise
not to meddle with the value (note *1).

If the compiler can't spot it, how do you expect a fallible human being
to do so?

If a function requires an invariant parameter then the compiler should
ensure that that guarantee is met, and not rely on the programmer to do
something that is impossibly hard in the general case. A simple way
would be to call $parameter := $parameter.INVARIANT()  (*2) on the
caller's behalf before calling the function.

Conversely, when calling a function where the parameter is declared :rw,
the compiler can call $parameter := $parameter.LVALUE() (*3) on the
caller's behalf first if it needs to convert an immutable object to a
mutable one.  (Or throw up its hands and assert that it's not allowed.)

If we really expect the optimizer to make Perl6 run well on a CPU with
1024 cores (*4), we have to make it easy to write programs that will
allow the optimizer to do its job, and (at least a little bit) harder to
write programs that defeat the optimizer.

To that end I would propose that:
 - parameters should be read-only AND invariant by default, and
 - that invariance should be enforced passing a deep immutable clone
   (*5) in place of any object that isn't already immutable.

-Martin

Footnotes:

*1: There are many possible reasons, but for example the caller didn't
declare it :readonly in turn to its callers because it *did* plan to meddle
with it -- but just not by calling this function with its :readonly
parameter.


*2: Yes I made up "INVARIANT". The trick is that the compiler only needs
to insert the call if can't prove the invariance of $parameter, which it
*can* prove when:
 - it arrived in a :readonly parameter; or
 - it's locally scoped, and hasn't "escaped".

In addition the implementation of INVARIANT() could:
 - return $self for any "value" class; and
 - return the encapsulated immutable object for the case outlined in the
   following footnote.

Otherwise the default implementation of INVARIANT() would be like
deepclone().

(Declaring a "value class" would ideally be shorter than declaring a
"container class", but I'm a bit stuck as to how to achieve that. Ideas are
welcome...)


*3: The LVALUE method produces the sort of proxy object that others have
described, but with the reverse function: it acts as a scalar container
that can only hold immutable objects, and proxies all method calls to
it, but allows assignment to replace the contained object.  Calling
INVARIANT on such a container object simply returns the encapsulated
immutable object.


*4: As a generalization, the assumptions floating round that "the
compiler will optimize things" just aren't facing reality: programmers
are about the worst people when it comes to learning from the past
mistakes of others, and future generations of Perl6 programmers will
inevitably create evil container classes with no corresponding value
classes, and thus most parallelizing optimizations will be defeated.


*5: At the language level at least, copying is NOT the enemy of
optimization. On the contrary, if you always copy and *never* mutate,
that ensures that the compiler can always determine the provenance and
visibility of any given datum, and thus has *more* opportunities to
avoid *actually* copying anything. And it can parallelize to the full
extent of available hardware because it can guarantee that updates won't
overlap.


Re: Why pass by reference?

2009-06-18 Thread Martin D Kealey
On Fri, 19 Jun 2009, Martin D Kealey wrote:
> To that end I would propose that:
>  - parameters should be read-only AND invariant by default, and
>  - that invariance should be enforced passing a deep immutable clone
>(*5) in place of any object that isn't already immutable.

Sorry, typo: that last word should have been "invariant", meaning that it
*won't* change, rather than "immutable", meaning that it *can't*.

Compilers can rely on invariance to perform a range of very powerful
optimizations; immutability is one way to guarantee invariance, but not the
only way.

-Martin


Re: XOR does not work that way.

2009-06-24 Thread Martin D Kealey

On Wed, Jun 24, 2009 at 10:35, John Macdonald wrote:
> Which means that short-circuiting is not right here - it must
> go through the entire list to determine whether there are zero
> true selections, find the first of exactly one true selections,
> or die if there are more than one true selections.

On Wed, Jun 24, 2009 at 11:10:39-0700, Jon Lang wrote:
> Which, I believe, is exactly how XOR short-circuiting currently works:
> it short-circuits to false if both sides are true; otherwise, it
> returns true or false as usual for XOR and continues on down the
> chain.

It's not a short-circuit unless you can avoid evaluating at least one
arguments at least some of the time.

When computing "odd parity" no short circuit is ever possible.

When computing "exactly one true" it's only possible if you have at
least 3 arguments; having found two that are true, you know the answer
is "false" without checking any others.

On Wed, 24 Jun 2009, John Macdonald wrote:
> Failing to distinguish "zero" from "more than one" makes cases where
> xor is of any utility even more rare, it would seem to me (and it's
> already quite rare).

Which points to a fairly obvious solution: "more than one" isn't just
false, it's an exception.

So infix:<^^> should return an unthrown exception if both operands are
"true". If one operand is already an unthrown exception, that exception
should be propagated, and the other operand doesn't need to be evaluated.
If one operand is true then return it; otherwise return the right-hand
operand (which should be false).

This solves both the human expectation ("Would you like wine or beer or
juice?" "Beer and juice please" "Sorry...") and the associativity
problem: (a ^^ b) ^^ (c ^^ d) == a ^^ (b ^^ (c ^^ d)).

-Martin

PS: Given that my suggested definition would always return one of the
values, could it be an L-value? Should it? Some cool new ways to
write obfuscated code: ($a ^^ $b) %= 2


Re: XOR does not work that way.

2009-07-02 Thread Martin D Kealey

On Thu, 2 Jul 2009, TSa wrote:
> Martin D Kealey wrote:
> > This solves both the human expectation ("Would you like wine or beer or
> > juice?" "Beer and juice please" "Sorry...") and the associativity
> > problem: (a ^^ b) ^^ (c ^^ d) == a ^^ (b ^^ (c ^^ d)).
>
> I don't understand how the associativity problem is solved when we
> use unthrown exceptions to implement the one of n xor. The expression
> True && True && True is False without parens but (True && True) && True
> evaluates to True

Assuming you meant "^^" rather than "&&", then under my proposal, that's not
the case.

In particular, True ^^ True evaluates to TooManyException. If that exception
is implicitly thrown, then that's what you get from the whole expression.

If not, TooManyException ^^ Anything doesn't evaluate the right operand at
all, and returns the value of the left operand.

So you'd get the same answer regardless of whether you put brackets in or
not.

-Martin


Re: $*CWD and chdir()

2009-08-20 Thread Martin D Kealey
On Wed, 19 Aug 2009, Timothy S. Nelson wrote:
>   ..but Perl is more magic than bash :).  Seriously, I can see both
> sides of the argument, and I'm leaning towards the $*CWD = chdir idea (as an
> option if people want to use it), but I realise that a lot of people are
> leaning the other way.  So I'll argue for it, but don't care if I lose :).

I want both.

I can have both. Or in fact all three:

$*CWD = "foo";# exception -- $*CWD isn't writable
use Cwd :fake;
$*CWD = "foo";# OK, faking it
use Cwd :chdir;
$*CWD = q;  # OK, same as {chdir "/tmp"}

I wonder if this is becoming the new Perl mantra "use lexically scoped
pragmata".

perl6 -MCwd=fake ... # legacy behaviour

-Martin


Re: unusual invocants

2009-10-24 Thread Martin D Kealey
On Wed, 21 Oct 2009, Ben Morrow wrote:
> The most important detail here is that the *class* gets to pick which
> imported methods need to be wrapped.
[but]
> What this doesn't fix is that some other code (outside the class) will be
> expecting C::x to have T1::x semantics, and some will be expecting it to
> have T2::x semantics. If these are contradictory, there is no way to write
> an x which works. That's where the 'hats' idea comes in

Sounds like going back to static typing -- which does sometimes have some
advantages.

One way to implement at would be to use proxy objects, which only do
one of the roles (by passing them through to the appropriate methods on the
original object).

This could be done transparently to formal parameters, so that when they're
used locally they would dispatch the "expected" method based on the locally
declared type for the object.

-Martin


Re: r29113 - docs/Perl6/Spec

2009-11-17 Thread Martin D Kealey


On Tue, 17 Nov 2009, pugs-comm...@feather.perl6.nl wrote:
> +++ docs/Perl6/Spec/S02-bits.pod  2009-11-17 18:37:41 UTC (rev 29113)
> @@ -2735,10 +2735,11 @@
>
>  =item *
>
> -Complex literals are similarly indicated by writing an addition of
> +Complex literals are similarly indicated by writing an addition or 
> subtraction of
>  two real numbers without spaces:
>
>  5.2+1e42i
> +3-1i
>
>  As with rational literals, constant folding would produce the same
>  complex number, but this form parses as a single term, ignoring


What happens then to negation of a literal?

 -5-2i
or even
 - 5-2i

Unless that's also a single term, you'd wind up negating the -2i back to
+2i, which is almost certainly not what's wanted.

Perhaps we could just stick to the "+" form, and add a prefix conjugation
operator? Some possible spellings include:
conj
⎺   high bar (reminiscent of the mathematical over-bar notation)
⌇   verticle squiggly line
⇅   up-and-down arrow (since it inverts imaginary but not real 
parts)

-Martin


Re: numerics, roles, and naming

2010-03-16 Thread Martin D Kealey
On Sun, 14 Mar 2010, Jon Lang wrote:
> Ruud H.G. van Tol wrote:
> > Did you consider "discrete"?
>
> I think that "Discrete" could work quite well as the role that
> encapsulates the ways in which Integer and Gauss are alike.  It may
> even be genralizable beyond that, although there might be some discord
> between theory and practice.

Discrete sounds good to me.

Carl Friedrich Gauß was a very significant figure in the development of
number theory and many other areas of mathematics; to use his name to label
one of his a relatively minor developments doesn't really do him justice.
Not that I have a better label in mind though.

> (In theory, Boolean is every bit as discrete as Integer is; but in
> practice, it has no use for most if not all of the methods in Integer that
> pertain to discreteness (factors, remainders, primes, etc.)

George Boole also worked in several areas of mathematics. One of those was
what he termed "algebra of logic", hence "Boolean algebra" as mathematicians
know it now.

But what we (programmers) call "Boolean", although in line with his original
concept, is a pale shadow of where Boolean Algebra has developed since. In
particular there are things call power sets, and a field using set
intersection and union over those has the same algebraic properties as the
original "algebra of logic", but not with just two "true" and "false"
values.

So mathematically a "Boolean" value doesn't necessarily behave the same way
as a bit, rather it behaves like a structured collection of bits. Treating
an integer value as a vector of bits is certainly one such structure.

Things like primes over Z(2) are not very interesting, but a field or ring
over Z(2)^n does have interesting behaviour that depends on n.

So I'm in favour of a "Boolean" role including things such as a vector of
bits.

I suggest "Predicate" as the name of the role which implements a single
true-or-false value (as distinct from a bit, which implements a 0-or-1
value).

-Martin


Re: numerics, roles, and naming

2010-03-16 Thread Martin D Kealey
On Mon, 15 Mar 2010, Mark J. Reed wrote:
> > Anything that can be made into a list is discrete.
>
> Not quite, since you can create lists whose members belong to
> continuous sets, e.g. real numbers.   Anything that naturally forms a
> list, maybe.

A discrete non-finite set is isomorphic to the set of integers.

This implies that you can pick an ordering, although perhaps not one that is
computational useful. E.g. rational numbers can be mapped onto integers by
laying them out in a 2D array, much like Gauß's complex integers, and then
walking diagonally in one quadrant. If you have more than one quadrant, take
them in turns. Extends to 3D and higher in a logic fashion.

But totally useless as a "greater than/equal to/less than" comparison test.

-Martin


Re: You never have privacy from your children in Perl 6

2010-03-29 Thread Martin D Kealey
> On Mar 27, 2010, at 15:43 , Darren Duncan wrote:
> > For example, say you want to define a graph of some kind, and for
> > elegance you have a separate container and node and side classes,

On Sat, 27 Mar 2010, Brandon S. Allbery KF8NH wrote:
> This sounds like a hackaround for an incomplete implementation of ADTs.

No, it's simply a reflection that the one-to-one relationship between the
attributes of a single storage object is too simplistic to use as the *only*
encapsulation boundary.

Of course, that points towards having access limits that depend not just on
the type, but on the specific object: in Darren's example, nodes should be
able to see the details of the edges and faces they're attached to, but
probably not any other edges or faces. And definitely not the edges or faces
in some completely disconnected mesh or network.

A connected mesh or network is a reasonable ADT, but to implement it you're
going to want several classes. The mesh-object-as-a-whole is the appropriate
encapsulation boundary.

If we had a really sophisticated ADT that could represent a "Network", that
would indeed solve the encapsulation problem. So what tools are we going to
need to build such an ADT? Well, privacy, trust, ...

-Martin


Re: A common and useful thing that doesn't appear to be easy in Perl 6

2010-04-07 Thread Martin D Kealey
On Wed, 7 Apr 2010, yary wrote:
> 2010/4/6 Larry Wall :
> >    Set(Read | Write)   # bogus, R|W is really 3 sets, R, W, and RW!
> >    Set(Read & Write)   # okay, can only represent RW
>
> Set(A | B) doesn't seem so bogus to me, if what you want is the power
> set

Hmm, surely a power-set would be written as

Set(Set(X,Y,...))

or perhaps more mathematically as

    2 ** Set(X,Y,...)

-Martin


Re: perl6 operator precedence table

2002-10-25 Thread Martin D Kealey
On Thu, 24 Oct 2002, Larry Wall wrote:
> It's possible the syntax for substitution should be wrapped around the syntax
> for matching, whatever that turns out to be.

That strikes me as promising...

Going back to Perl5 for a moment, we have

  substr($str,$start,$len) = $newstr

why not simply extend pattern-matching in a similar way to substr, making it
an L-value, so that one gets

  $str ~ /[aeiou]+/ = "vowels($&)"

or

  $str ~ /\d/ {hyper-symbol}= (0) x {size-of-LHS-array};

(hyper, however it's spelt, will have some way for the RHS to reference the
LHS, won't it?)

-Martin

-- 
4GL ... it's code Jim, but not as we know it.




Re: perl6 operator precedence table

2002-10-29 Thread Martin D Kealey
On Tue, 29 Oct 2002, Damian Conway wrote:

> Or one could define a copy-the-invoke method call operator (say, C<+.>):

As a rule I prefer to see "safe" operations have short names and
"dangergous" operations with longer ones.  In this context that means "copy"  
gets the short name and "in place" gets the longer one.

So we should define that methods where possible return new values rather
than acting in-place, but define an apply-assignment operator (say C<.=>) to
use when you want to act in-place.  Of course, the methods can be made aware
of this so that they can optimise where appropriate.

  $str .= chomp;  # store result in-place
  $new = $old . chomp;# return resultant value

  $str .= lcfirst;# store result in-place
  $new = $old . lcfirst;  # return resultant value

  $str .= replace( /foo/ -> {'bar'} );
  $new = $old . replace( /foo/ => { 'bar' } );

Unfortunately that sits badly with things that "return" two non-scalars
(such as "splice" resulting in an portion excised and a remainder) because
it means that this assignment operator doesn't return the "resulting value"  
the way that other assignment operators do.

Also having the in-place version return something different from the copy 
version would be non-obvious to neophites, but that's a problem no matter 
what notation is used.

  @excised = @array .= splice($position,$count,@insertions);

vs

  @excised = @array . slice($position,$count);
  @unexcised = @array . splice($position,$count,@insertions);

So, in

  @a = @b .= grep {/foo/};

should @a be the elements that I contain "foo" or those that I?

-Martin





[OT] linguistics and cultural bias?

2002-10-30 Thread Martin D Kealey
On Tue, 29 Oct 2002, Larry Wall wrote:
> Logically entangle nouns *are* more basic than grade school.  Kids are
> even sophisticated enough to disambiguate "xor" from "or" by context,
> despite the fact that English has no "xor" operator:
> 
> Which do you want?  A popsicle or a Mickey Mouse hat?

Hmmm...

I've heard that this is a culturally driven thing: that whilst people can 
all disambiguate it, people from different cultures may do so differently

In a "western" culture, exclusive-or is the assumed default unless context
implies otherwise.  But in many Pacific island cultures (*), if one offers
"kava or coffee" one would be expected to provide both if answered "yes".

-Martin

(* This from annecdotal memory of 20 years ago, so I don't vouch that it
still applies in any particular culture, but the essential point remains
that the disambiguation is not as universal or consistent as may seem to us
sitting here in Australasia, USA or Europe, speaking English.)




Re: [RFC] Perl6 HyperOperator List

2002-10-30 Thread Martin D Kealey
On Tue, 29 Oct 2002, Larry Wall wrote:
> Maybe we should just say that you can put it anywhere that makes sense,
> and let the perl parser sort out the sheep from the goats.  The basic
> rule is that for any op, [op] is also expected in the same place.

It would be nice to have a fully generalized set of applicative
manipulators.  The basic set in applicative languages like Haskell generally
includes map, zip, fold and do; from these others can be constructed, but
for efficiency in an imperative language we'd probably want a few more like
apply and cross-product.

It strikes me that [op] is a composition of yet more basic facilities; thus

  @a [+] @b

would be something like

  map { $_[0] + $_[1]) } zip @a, @b

In general it would be nice to be able to make shorthands for arbitrary
compositions; eg, with some definition for "zip" that results in the above,
one could then go simply

  @a zip:+ @b

which while not as short as @a [+] @b, is more obviously a specific instance
of a more general construct.

 -=*@*=-

Apropos substitution, I still like the idea of having matched sub-strings as
magic L-values. I think the ".=" assignment operator makes this a lot more
feasible than simply using a straight assignment, which as Larry mentioned
before would be problematic with its right-to-left evaluation. But for an
assignment operator that needn't necessarily be the case, and indeed
implicitly is not the case.  Using the ".=" operator, we could have:

Perl5:  Perl6:

$a =~ s/\d/X/;  $a ~ /(\d)/ = "X";

$a =~ s/\d/X/g; $a ~ /(\d)/ [=] "X";

$a =~ s/\d/ ($&+1)%10 /eg;  $a ~ /(\d)/ [.=] { ($_+1)%10 };

Or if you don't like switching from = to .=, just stick with ".=" and define
that ".literal" always returns the literal, after evaluating and discarding
the LHS, and ".=literal" likewise evaluates the LHS, then sets the LHS to
the literal value.

> So if the user defines a postfix:! for factorial, they automatically get
> _[!] for that as well.

postfix vs infix ... mumble ... parsing nightmare ... mumble ...

> I think we could also allow
> 
> @a [??] @b [::] @c
> 
> But it's not clear whether we can parse
> 
> @a = [undef][...]

What about

  $a = $x lazy:? $y : $z

so that $a is thus an object which when stringified (or numified or 
whatever) chooses whether it's $y or $z, but not until?

-Martin




Re: perl6 operator precedence table

2002-10-30 Thread Martin D Kealey
On Fri, 25 Oct 2002, I wrote:
> > why not simply extend pattern-matching in a similar way to substr, making it
> > an L-value, so that one gets
> > 
> >   $str ~ /[aeiou]+/ = "vowels($&)"
> > 
> > or
> > 
> >   $str ~ /\d/ {hyper-symbol}= (0) x {size-of-LHS-array};

On Thu, 24 Oct 2002, Larry Wall replied:
> Problem with that...the replacement argument has to be lazy, and currently
> the RHS of an assignment is actually evaluated before the left.  You'd
> really need something more like
> 
> $str =~ /\d/ = { 0 }

How about just

$str =~ /\d/ .= "0"

or

$str =~ /\d/ .= { 1 + $_ .& 7 }

in which using "." (apply) would force a fetch of the LHS in advance of
evaluating the RHS. And for global-replace we could use the vector/hyper
notation:

$str =~ /\d/ [.=] "0"

> However, I think readability suffers without a hint on the front what
> you're trying to do.

We don't in general have a "let" on the front of assignment statements; why
should this type of assignment be any different?  (Do we want a "let" keyword?
Personally I don't think so, but what do others think?)

-Martin

-- 
How to build a Caspian Sea oil pipeline - step one: get elected president...




Re: String concatentation operator

2002-11-20 Thread Martin D Kealey
On Mon, 2002-11-18 at 18:10, Dave Whipp wrote:
> Why do we need to use preemptive threads? If Parrot is a VM, then surely 
> the threading can be implemented at its level, or even higher.

And what about *lower*? Like down among the CPUs?

I want Perl to run 128 times faster on a 128 CPU machine... now I know
that's not entirely realistic, but it should be able to run at least say
60 times faster.

It's not that we necessarily want *preemptive* threads, but if we can't
do that, we certainly can't do multiprocessor threads.

-Martin




RE: Unifying invocant and topic naming syntax

2002-11-20 Thread Martin D Kealey
On Wed, 2002-11-20 at 15:01, Brent Dax wrote:
> We need that capability if we're going to have lexically-scoped exports:

Whilst it would be useful for pragmatic modules to access anything and
everything in the current compilation scope, I submit that access to
dynamic scope should (in general) be more closely controlled... and of
course the former can be used to implement the latter:

  use visible '$topic';

  no visible '$_';

-Martin




Re: String concatentation operator

2002-11-20 Thread Martin D Kealey
On Thu, 2002-11-21 at 06:57, Mark Biggar wrote:
> Martin D Kealey wrote:
> > I want Perl to run 128 times faster on a 128 CPU machine... now I know
> > that's not entirely realistic, but it should be able to run at least say
> > 60 times faster.
> 
> Amdahl's law applies here:  "no amount of paralellism will speed up
> an inheirently sequential algorithm"

True in the abstract, but in practice in most languages an awful lot of
algorithms that I inherently sequential get serialized by the
compiler because it can't tell it's safe to do otherwise.

This is where pure-functional or applicative languages can have a big
performance win - because the compile almost alway I see that
things are safe to parallelize.

-Martin




RE: Unifying invocant and topic naming syntax

2002-11-21 Thread Martin D Kealey
On Thu, 2002-11-21 at 20:11, Brent Dax wrote:
> Are you suggesting this?
> 
>   if($error) {
>   use visible '&croak';
>   require Carp;
>   import Carp: 'croak';
>   croak($error);
>   }

No - that would be pointless as well as error-prone.

My idea of "visible" is that it would make a lexically scoped thing
accessible to an inner dynamic scope at run-time.

By default that would only apply to $_, but the mechanism should be
generalisable to any name.

-Martin



L-valueness of Arrays vs. Lists

2003-02-22 Thread Martin D Kealey
On Tue, 11 Feb 2003, Michael Lazzaro wrote:
> What is the utility of the perl5 behavior:
>
>  \($a,$b,$c)
>
> meaning
>
>  (\$a, \$b, \$c)
>
> Do people really do that? ...  Can someone give an example of an actual,
> proper, use?

Yes, I've used it like this:

   for (\($a,$b,$c)) {
  $$_++;
   }

to be sure that it works on all versions, since

   for ($a,$b,$c) {
  $_++;
   }

works differently on different versions.  (Actually, I don't have an
old-enough version on hand to check just when that was, so it must have been
5.004 or before.)

This change didn't start to bite me until P5.6.0, when "values %HASH" became
an Lvalue too, whereupon

   for ( values %HASH ) {
  s/^prefix//;
  ...
   }
   ... do something else with %HASH

stopped working.

So, I would urge making as many things as possible Lvalues (and magical
references) right from the start of P6, just so as we don't break things by
making them so later.

-Martin

-- 
Help Microsoft stamp out software piracy: give Linux to a friend today...




Re: Arrays, lists, referencing

2003-02-22 Thread Martin D Kealey

I would like to chip in in favour of the "list is value, array is container"
side of the argument. However I think that needs clarifying.

A reference is a value; the thing it refers to is a container.

An anonymous container is a container with no references from any symbol
table.  It can lose its anonymity by creating such a reference.

A list is an ordered set of references to (normally anonymous) containers.

An array is a container that contains a list.  When created, an array
contains the empty list. The operations push, pop, shift, unshift, extend,
truncate and element auto-vivify replace the value in the array with another
value similar to the old one. Assignment replaces the value in the array
with an entirely new value.

Operations on individual elements of an array do not affect the value of the
array, just the values in the containers that the array's list members refer
to.

Possible definition:

Except for "obvious" arrays and hashes (those involving "@" or "%" in the
expression), anything evaluated inside a list in R-value context is itself
in reference context.  Named arrays and hashes are in
flatten-to-reference-to-member context.  Anything evaluated inside a list in
Lvalue context is itself in reference context.  Assignment to a list
deferences successive elements of each side.  Passing a list as parameters
dereferences each element unless the prototype says otherwise.

Almost all of these containers are either elidable at compile time, or will
be needed "soon" anyway -- eg, as elements in the formal parameter list; so
there's no practical cost to this definition.


On a related topic...

I like to be able to program in a "pure functional" mode as much as
possible, mainly because it's the easiest to prove correctness, but also
because it also offers the greatest scope for compile-time optimisation.

What I would like is for the language to enable as many compile-time
optimisations as possible, by making the optimisation-friendly choices the
shorter easy-to-type defaults.

One of those, rather inobviously, is choosing pass-by-value rather than
pass-by-reference. And rather deeper pass-by-value than the sort of list
I've talked about above: a list would be a set of actual values, not a set
of references to containers containing values. And we could extend this
to things other than arrays/lists.

It's important to understand that I'm talking about the semantics of the
language, not the implementation. The point is that the implementation is
still free to pass by reference when it can be sure that the receiving
function won't fiddle with it.  That can be guaranteed if you can see (or
infer) all the way down to the leaf function calls at compile time.  (This
gets complicated at trust boundaries, but we can work on that.)

One of the things I found most irksome moving from C++ to Java was that Java
took away both "pass object by value" AND "pass object by const reference".
Couple that with some rather bad choice of "value" vs "container" in the
standard class library, and the result was that one had no way to be sure
that an object wouldn't get modified once you handed a it over as a
parameter or referent to some random method.

Since then languages such as ECMAscript have copied that behaviour, and it
seems that P6 is looking more and more like a clone of that language ... and
that worries me.

I would like to argue in favour of "pass by value" to be the default in the
absence of some explicit prototype, because it allows greater type-safety,
and because the opposite default interacts badly with out-of-order execution
such as parallelism, and bars some optimisations that can be applied to
closures. (We do want Perl to run fast on parallel hardware, don't we?)

The relationship to the array/list thing is this: that it's not just
pass-by-value to functions and methods, it's about implicit R-valueness in
any context that doesn't absolutely require L-valueness.

All this is orthogonal to the concept of "object": in C++ "an object" can be
used to implement either a value (such as "string") or a container (such as
"vector"); it would be nice to be able to do this in P6 too.

-Martin

PS: sorry for the long post...




Re: Suggested magic for "a" .. "b"

2010-08-01 Thread Martin D Kealey
On Wed, 28 Jul 2010, Darren Duncan wrote:
> I think that a general solution here is to accept that there may be more
> than one valid way to sort some types, strings especially, and so
> operators/routines that do sorting should be customizable in some way so
> users can pick the behaviour they want.
>
> The customization could be applied at various levels, such as using an
> extra argument or trait for the operator/function that cares about
> ordering,

That much I agree wholeheartedly with, but ...

> or by using an extra attribute or trait for the types being sorted.

... puts us back where we started: how do we cope if the two endpoints
aren't tagged with the same attribute or trait or locale?

In any case I'd much rather prefer that the behaviour be lexically scoped,
with either adverbs or pragmata, not with the action-at-a-distance that's
caused by tagging something as fundamental as a String.

Yes sometimes you want the behaviour of your range to mimic the locale of
its operands, but then it should be explicit, with a trait that also
explicitly selects either the left or right operand to extract the locale
from. And probably throw an exception if they aren't in the same locale.

If you don't specify that you want locale-dependent behaviour then the
default action should be an unthrown exception unless both endpoints are
inarguably comparable, so IMHO that pretty much rules out any code-points
that are used in more than language, save perhaps raw ASCII. And even then
you really should make an explicit choice between case-sensitive and
case-insensitive comparison.

> When you want to be consistent, the behaviour of "cmp" affects all of the
> other order-sensitive operations, including any working with intervals.

Indeed, the range constructor and the cmp operator should have the same
adverbs and share lexical pragmata.

> So then, "a" cmp "ส้" is always defined, but users can change the
> definition.

I take the opposite approach; it's always undefined (read, unthrown
exception) unless the user tells us how they want it treated. That can be a
command-line switch if necessary.

To paraphrase Dante, "the road to hell is paved with Reasonable Defaults".
Or in programming terms, your reasonable default is the cause of my ugly
work-around.

-Martin


Re: Smart match isn't on Bool

2010-08-03 Thread Martin D Kealey
On the one hand, I've had 25 years of being annoyed about the idiom

if foo() == True ...

So I'd be delighted if P6 were to treat that case as a fatal compile-time
error.

And given that "==" are "!=" are just funny ways of writing "!xor" and
"xor", that prohibition could reasonably be extended to all statically-typed
expressions (not just constants), with the error message suggesting the use
of "!xor" or "xor" instead.

On the other hand it feels it'd be wrong if foo() ~~ bar() simply ignored
the value of one of its operands based on the type of the other.

Overall I'd rather see a solution that factors out the implicit "last" from
the implicit "$_ ~~".

My feeling is that "if" and "when" should be for the implicit "last", since
they're all alphabetic tokens; then it's just a case of deciding how to
spell the contextualizer.  The most obvious would be

 if == VALUE-TO-MATCH {...}
 if ~~ VALUE-TO-MATCH {...}
 when == VALUE-TO-MATCH {...}
 when ~~ VALUE-TO-MATCH {...}

however I'm not sure if that conflicts with any prefix:<~~> or
prefix:<==>, and it also conflicts with Huffmanizing the implicit match
to something shorter than the explicit comparison.

One possibility is to make all options explicit:

 if= VALUE-TO-MATCH{...}  # no implicit last
 if? BOOLEAN-EXPRESSION{...}
 if~ VALUE-TO-SMARTMATCH   {...}
 when= VALUE-TO-MATCH  {...}  # implicit last
 when? BOOLEAN-EXPRESSION  {...}
 when~ VALUE-TO-SMARTMATCH {...}

and then make bald "if" and "when" be DWIMmy shorthand.

Oh, and then "A ~~ B" just works like "?! (A) xor B", if B is a Bool.

-Martin

PS: I also considered some other possibilities, but I don't like them as
much:

 if -> VALUE-TO-MATCH {...}
 when -> VALUE-TO-MATCH {...}

 -> if VALUE-TO-MATCH {...}
 -> when VALUE-TO-MATCH {...}

 .if VALUE-TO-MATCH {...}
 .when VALUE-TO-MATCH {...}

 ==> if VALUE-TO-MATCH {...}
 ==> when VALUE-TO-MATCH {...}


Re: Tweaking junctions

2010-10-27 Thread Martin D Kealey

I have to admit to feeling uneasy about the whole action-at-a-distance
effect that junctions are capable of producing. They sit around pretending
to be a scalar, only to pop up and wreak havoc with ones expectations of
linearity when you're not expecting it.

That unexpected-action-at-a-distance is somewhat mitigated by autothreading
functions where the junction is presented as a direct parameter, but being
able to defer a junction by putting it inside an aggregate seems like asking
for trouble unless we make sure that it behaves as much like an ordinary
scalar as possible when it does finally get collapsed.

I think we need to decide whether junctions are just about flow control, or
are more generalized parallel data handling, typified as a way of handling
sets.

If it's about parallel data handling, then we have to be prepared to
(notionally) fork the entire rest of the runtime, even as far as having a
definition of what return value the parent process sees (from "exit") when
those threads are implicitly collapsed at termination. And deciding what
happens when, in the process of autothreading junction A, you wind up
collapsing junction B in different ways (including perhaps not collapsing
it)? Right now I don't think we're up for all that.

For the sake of flow control, do we have a formal algebra of how we apply
distributive rules so that all the elements of the resulting junction are
booleans and the result of the collapse is "obvious"?

In the simple cases it's (supposedly) obvious:
$foo == ($bar | $zot)   === ($foo == $bar) | ($foo == $zot)

But what about:
$foo != ($bar | $zot)   === not($foo == ($bar | $zot))
=== not(($foo == $bar) | ($foo == $zot))
=== (not($foo == $bar)) & (not($foo == 
$zot))
=== ($foo != $bar) & ($foo != $zot)

Moreover, what about:
$foo < ($bar | $zot)=== ($foo < $bar) | ($foo < $zot)
versus:
$foo < ($bar | $zot)=== not($foo >= ($bar | $zot))
=== not(($foo >= $bar) | ($foo >= $zot))
=== (not($foo >= $bar)) & (not($foot >= 
$zot))
=== ($foo < $bar) & ($foo < $zot)

In short, in order to avoid unexpected action at a distance, it's logical to
invert the junction type, but in doing so you hit some very nasty corner
cases. How do you know whether a function is saying "X has property Y" or
"X does not have property ~Y" ? Which of "Y" or "~Y" are we talking about?

It seems fair enough to infer that equality comparison is "Y" rather than
"~Y", but any other sort of comparison is fraught.

This leads me to the conclusion that collapsing a junction over an ordered
comparison should fail in the same way that an ordered comparison involving
complex numbers or vectors should fail (or more generally, an ordered
comparison of any aggregate should fail unless the aggregate type defines some
sensible ordering; there should be no "default").

Indeed, the whole notion of autothreading a junction over an arbitrary
function (to produce a boolean that can be used for flow control) starts to
sound fishy: how do we decide whether a given function should be treated
like "==", where the distributive rule produces the same junction type, or
like "!=", where the distributive rule produces the inverse junction type?

Or do we not invert junctions, and run the risk of unexpected
action-at-a-distance instead?

-Martin


Re: Tweaking junctions

2010-10-29 Thread Martin D Kealey
On Thu, 28 Oct 2010, Damian Conway wrote:
> The apparent paradox ... is due to the assumption (employed in the
> second interpretation) that < is identical to !>=. Certainly that is
> true for simple scalar numbers, but not always for vector types such
> as tuples, sets, bags, complex numbers...or junctions.

> That doesn't make either < or !>= intrinsically invalid on vector types
> (though they obviously are inappropriate for *some* vector types); it just
> means you can't reasonably treat the two operators as universally
> interchangeable, just because they sometimes are.

Well, I think returning or throwing an "Unordered" exception would be
the appropriate way to handle those, both for complex numbers and for
junctions.

Anyone who thinks they're dealing with real numbers will reasonably
expect "<" and "!>=" to be the same, and a junction can masquerade as
anything (within each thread), including a real number.

And what about when that difference is wrapped up inside a function? In
other words, what's wrong when I expect the following two snippets to
work the same way?

A:

sub anything_is_broken($subject) {
grep { ! .test() } $subject.parts()
}

if anything_is_broken($subject) {
fail($subject)
}
else {
pass($subject)
}

B:

sub everything_is_working($subject) {
! grep { ! .test() } $subject.parts()
}

if everything_is_working($subject) {
pass($subject)
}
else {
fail($subject)
}

Why should it make a difference whether $subject is a junction?

> In summary, the "problem" here seems to be that, algebraically,
> junctions don't behave exactly like non-junctions. Which is true, but no
> more a problem than the fact that, algebraically, complex numbers don't
> behave exactly like non-complex numbers, or that sets don't behave
> exactly like non-sets, or that Rats don't behave exactly like Nums,
> which don't behave exactly like Ints, which don't behave exactly like
> ints either.

When you're talking about built-in operators, that's plausible, because
by looking for "!" in the operator name there are ways to
DWIM-or-throw-an-exception.

That's not true for user-defined functions, so I think the real problem
is that the parallelizing of the expression that contains a junction may
not be "obvious" at the point where it happens.

Hmmm  maybe one way to improve that might be to say that you can't
put a junction into an untyped scalar, or indeed in any variable that
isn't explicitly marked as "this thing might contain a junction". That
would apply, as now, to function parameters and returns, but also to
variables and aggregate members; indeed, *everywhere*.

> And, of course, that's why Perl 6 has strong typing. So that, when
> these differences in behaviour do matter, we can specify what kind(s)
> of data we want to allow in particular variables, parameters or return
> slots...and thereby prevent unexpected kinds of data from sneaking in
> and violating (un)reasonable expectations or inducing (apparent)
> paradoxes. :-)

I don't think strong typing is enough, because we explicitly mask the
application of type constraints by autothreading. Each thread sees a
thing with the type it expects, but the problem comes when the threads
are recombined; the result often won't be what's expected.

Don't get me wrong, I think Junctions are a really clever way of writing
concise conditional expressions, but I think algebraic consistency is
more important than clever conciseness.

-Martin


Re: exponentiation of Duration's

2010-11-18 Thread Martin D Kealey

On Wed, 17 Nov 2010, Richard Hainsworth wrote:
> Once a number has been generated, viz., by obtaining a duration, that number
> can be manipulated however necessary. The interpretation of the number is a
> matter for the programmer, not the language designer.

All true.

However I'd argue that you can very easily obtain a bare number as

my $plain_number = $duration / $one_time_unit

which makes it explicit that you're stripping the dimentionality.

Then you can square it or whatever to your heart's content.

Dimensioned numbers as restrictive types are useful, for uncovering bugs,
including sometimes latent ones in ported code.

Duration is a fairly clear example of a dimensioned quantity, and I think we
should think twice about abandoning its dimensionality, and the
restrictions that implies.

-Martin



Re: Encapsulating the contents of container types

2011-09-10 Thread Martin D Kealey


On Fri, 9 Sep 2011, Carl Mäsak wrote:
> Patrick Michaud said something (I think AFK) that seems essential to
> me: the non-rw-ness of these objects isn't a trait of *the object
> itself*, it's a trait of *the context in which the object is used*.

In one sense that is true, but if that's the only kind of constancy that
gets implemented, then it's only half the story.

It is of course useful to be able to send a "value" to a sub and know that
it won't be mangled when the sub returns, and you do get that from the
"const reference" approach that's implied by Patrick's comment.

But it's also useful, when in the sub, to know that the someone else won't
mess with a "value" while you're working with it. I can't see any way to
enforce that without constancy being a feature of the object rather than the
reference to it.

Moritz Lenz wrote:
> I think we should consider the implications of
> immutability-all-the-way-down before we jump to any conclusions. In
> particular list cases where typical Perl 5 code fails when ported to Perl
> 6.

Perhaps if we could tag the type/class/pmc/whatever when it's constructed
as to whether it defaults to r/o or r/w? Hence things like file handles
would be r/w by default, and most other things would be r/o.

Actually, I'm inclined to think that r/o vs r/w for sub params is a bit of a
blunt instrument. What about the option of treating a "r/w" param as a
shorthand for both an r/o param AND an r/o return? So in effect, changes to
the "container" don't take effect until after the sub returns. (BTW this
would have a lot of benefits for auto-threading code.)

-Martin


Re: [perl6/specs] ff11f1: define %%; clarify that % is not quantmod

2011-09-28 Thread Martin D Kealey
Out of curiosity, I followed this and read through "Str".

When I got to the section on "sprintf", I found a few things I think need
attention.

1. There isn't any description what the flags do, in particular 'v', which
seems to be a P6 enhancement.

2. Not mentioned are 'hh' (native char), 'j' (native maxint_t) and 'l'
(applied to 's' and 'c', native wchar_t).

3. Logically the 'p' conversion applied to an Object should return the
object identity (.id or whatever that's called now), though applied to
non-objects it should probably still throw an exception.

4. In keeping with named parameters, it seems to me that the 'index' should
be extended to allow a name rather than just an integer. Obviously that
would need the name to be disambiguated by some punctuation such as <> or
«».

5. And pretty please could we have infix:<%>(Str,Capture) as an alias for
sprintf? (Not that I'm normally a Python fan, but that feature has a
particularly wholesome appeal about it.)

-Martin

On Sun, 25 Sep 2011, nore...@github.com wrote:
> Date: Sun, 25 Sep 2011 17:33:22 -0700
> From: nore...@github.com
> To: perl6-language@perl.org
> Subject: [perl6/specs] ff11f1: define %%; clarify that % is not quantmod
>
>   Branch: refs/heads/master
>   Home:   https://github.com/perl6/specs
>
>   Commit: ff11f19331bf30327cf729a0f5c9c349caa231c7
>   
> https://github.com/perl6/specs/commit/ff11f19331bf30327cf729a0f5c9c349caa231c7
>   Author: Larry Wall 
>   Date:   2011-09-25 (Sun, 25 Sep 2011)
>
>   Changed paths:
> M S05-regex.pod
>
>   Log Message:
>   ---
>   define %%; clarify that % is not quantmod
>
> ingy++ requested a method of stopping optionally after the separator,
> so that's now %% (with some notion of "evenly divisible" in some kind
> of loose sense).  (Note, if you want to require the separator at the
> end, don't use this construct, just use [x ',']* or such.
>
> sorear++ requested clarification: % (and %%) are not really quantifier
> modifiers; they modify a quantified atom to insert requirements
> between each iteration of that quantified atom.  Hence any quantifier
> may still take an additional control quantmod in addition to a separator.
>
>
>   Commit: 6d7f9f1ad5f42fe3e14d44a10834cda869643cc7
>   
> https://github.com/perl6/specs/commit/6d7f9f1ad5f42fe3e14d44a10834cda869643cc7
>   Author: Larry Wall 
>   Date:   2011-09-25 (Sun, 25 Sep 2011)
>
>   Changed paths:
> M S32-setting-library/IO.pod
>   M S32-setting-library/Str.pod
>
>   Log Message:
>   ---
>   Merge branch 'master' of github.com:perl6/specs
>
>
> Compare: https://github.com/perl6/specs/compare/d7b5637...6d7f9f1
>


Re: Setting private attributes during object build

2012-02-02 Thread Martin D Kealey
> Damian:
> > The whole point of having BUILD() is to separate allocation
> > concerns from initialization concerns.

On Thu, 2 Feb 2012, yary wrote:
> And that's not so good, because it forces BUILD to be used for
> initialization, and precludes initializing private attributes anywhere
> else, like a "bless" called from the "new" method.

Err, isn't that the point: BUILD is for initialization, and bless is for
allocation?

Except that "bless" also does pass-through for to the initializers, which
confuses the mental model. Well, if it's going to do that, perhaps it could
take just one parcel parameter?

(I do find the notion of an inheritable "constructor" a bit odd, upside-down
even. However one of the things I *like* about Perl5 is that a class's
object factory doesn't have to be called "new"; instead it can have a name
that's natural to the domain of the object: File.open, Socket.listen,
Process.run, Timer.start, etc. And object factories can be "instance
methods" too: IO.dup, Socket.accept, String.split, etc.)

The idea of BUILDALL taking care of the hierarchy and each BUILD just
plucking out the named args it needs is quite elegant, but there will
invariably be corner cases where it doesn't fit, particularly if one mixes
in unrelated classes that conflict on their parameter names.

And yet, overriding BUILDALL in an inheritable fashion also seems wrong.

One could revert to the Perl5 and C++ way of doing things: explicitly
calling up the constructor chain. But then how do you make it clear that
BUILDALL is NOT required?

Is there an answer to this conundrum?

-Martin


Re: How to make a new operator.

2012-03-22 Thread Martin D Kealey
On Thu, 22 Mar 2012, Carl Mäsak wrote:
> Jonathan Lang (>>), Daniel (>):
> >>    1, 2, 4 ... 100 # same as 1,2,4,8,16,32,64
> >
> > That last one doesn't work on Rakudo :-(
>
> And it never will. Note that 100 is not a power of 2, and that the goal
> needs to match exactly. This is because smartmatching is used, not some
> other comparison. The sequence will continue to generate numbers until the
> number 100 is generated, which never happens. Rakudo loops forever on this
> one, as per spec.

Hmmm, so it's likely that most times you get a Num rather than an Int or
Rat, those won't stop either?

1, 7 / 6.0 ... 2
1, sqrt(2), 2 ... 8

Question: do we support

1, 2i, -4 ... 256

> If you're wondering why things are factored in this way, it's because
> previous versions of the spec that tried to special-case 100 to work in
> cases like the above, ended up not working out. It turned out that the
> unification of infix:<...> and smartmatching was what did work. It has the
> slight drawback that we have to educate users to write * >= 100 instead of
> 100 in the case of not-exactly-matching goal states. But it's still a net
> win, because this unified semantics works better than anything we had
> before.

Sounds to me like AscendingArithmeticIteratorInclusiveTerminalSmartMatch
could do the same thing as normal SmartMatch except when the LHS is an
IteratorOf{X} and the RHS is an {X}, for X in {Int, Rat, Num} and possibly
other comparable (orderable) types, when ">" would be implied.

Likewise for AscendingArithmeticIteratorExclusiveTerminalSmartMatch (">=")
DescendingArithmeticIteratorInclusiveTerminalSmartMatch ("<") and
DescendingArithmeticIteratorExclusiveTerminalSmartMatch ("<=").

-Martin


Re: [perl6/specs] 5277fe: Add expmod and is-prime as built-ins in Int

2012-09-20 Thread Martin D Kealey
On Wed, 19 Sep 2012, GitHub wrote:
>   Log Message:
>   ---
>   Add expmod and is-prime as built-ins in Int

> +Returns True if C<$x> is known to be a prime, or is likely to be a
> +prime based on a probabilistic Miller-Rabin test.  (The optional
> +argument tells how many times to iterate the probabilistic test,
> +if such is necessary.)
> +
> +Returns False if C<$x> is known not to be a prime, or is unlikely to
> +be a prime after probabilistic testing.

Isn't Miller-Rabin definitive when it disproves primality? In which case the
probabilistic qualifier in the last paragraph isn't needed.

Or is this just to allow that some better (presumably faster or more probable)
non-deterministic primality test might be used in the future? (Though
Miller-Rabin is already pretty fast, so there seems little reason not to
incorporate it as part of any future test.)

But in that case, we should be saying up front that the test might change.

-Martin


Re: Grammars and biological data formats

2014-08-16 Thread Martin D Kealey

Hmmm, what about just implementing mmap-as-string?

Then, assuming the parsing process is somewhat stream-like, the OS will take
care of swapping in chunks as you need them. You don't even need anything
special to support backtracking -- it's just a memory address, after all.

-Martin

On Thu, 14 Aug 2014, Fields, Christopher J wrote:
> Yeah, I'm thinking of a Cat-like class that would chunkify the data and check 
> for matches.
>
> The main reason I would like to stick with a consistent grammar-based 
> approach is I have seen many instances in BioPerl where a parser is 
> essentially rewritten based on its purpose (full parsing, lazy parsing, 
> indexing of flat files, adding to a persistent data store, etc).  Having a 
> way to both parse a full grammar but also subparse for a specific token/rule 
> is very handy, and when Cat comes around even more so.
>
> Chris
>
> Sent from my iPad
>
> > On Aug 14, 2014, at 6:40 AM, "Carl Mäsak"  wrote:
> >
> > I was going to pipe in and say that I wouldn't wait around for Cat,
> > I'd write something that reads chunks and then parses that. It'll be a
> > bit more code, but it'll work today. But I see you reached that
> > conclusion already. :)
> >
> > Lately I've found myself writing more and more grammars that parse
> > just one line of some input. Provided that the same action object gets
> > attached to the parse each time, that's an excellent place to store
> > information that you want to persist between lines. Actually, action
> > objects started to make a whole lot more sense to me after I found
> > that use case, because it takes on the role of a session/lifetime
> > object for the parse process itself.
> >
> > // Carl
> >
> > On Wed, Aug 13, 2014 at 3:19 PM, Fields, Christopher J
> >  wrote:
> >> On Aug 13, 2014, at 8:11 AM, Christopher Fields  
> >> wrote:
> >>
> >>>> On Aug 13, 2014, at 4:50 AM, Solomon Foster  wrote:
> >>>>
> >>>> On Sat, Aug 9, 2014 at 7:26 PM, Fields, Christopher J
> >>>>  wrote:
> >>>>> I have a fairly simple question regarding the feasibility of using 
> >>>>> grammars with commonly used biological data formats.
> >>>>>
> >>>>> My main question: if I wanted to parse() or subparse() vary large files 
> >>>>> (not unheard of to have FASTA/FASTQ or other similar data files exceed 
> >>>>> 100’s of GB) would a grammar be the best solution?  For instance, based 
> >>>>> on what I am reading the semantics appear to be greedy; for instance:
> >>>>>
> >>>>>  Grammar.parsefile($file)
> >>>>>
> >>>>> appears to be a convenient shorthand for:
> >>>>>
> >>>>>  Grammar.parse($file.slurp)
> >>>>>
> >>>>> since Grammar.parse() works on a Str, not a IO::Handle or Buf.  Or am I 
> >>>>> misunderstanding how this could be accomplished?
> >>>>
> >>>> My understanding is it is intended that parsing can work on Cats
> >>>> (hypothetical lazy strings) but this hasn't been implemented yet
> >>>> anywhere.
> >>>>
> >>>> --
> >>>> Solomon Foster: colo...@gmail.com
> >>>> HarmonyWare, Inc: http://www.harmonyware.com
> >>>
> >>> Yeah, that’s what I recall as well.  I see very little in the specs re: 
> >>> Cat unfortunately.
> >>>
> >>> chris
> >>
> >> Ah, nevermind.  I did a search of the IRC channel and found it’s 
> >> considered to be a ‘6.1’ feature:
> >>
> >>http://irclog.perlgeek.de/perl6/2014-07-06#i_8978974
> >>
> >> It is mentioned a few times in the specs, I’m guessing based on where it’s 
> >> thought to fit in best.  For the moment the proposal is to run grammar 
> >> parsing on sized chunks of the input data, which might be how Cat would be 
> >> implemented anyway.
> >>
> >> chris
> >>
>


Re: [perl6/specs] 40163b: reverse associativity on R ops

2015-03-30 Thread Martin D Kealey

Reversing the associativity makes sense, but having equal precedence for
operators with differing associativity sounds -- as you say -- like madness.

Even having non-associative mixed with either-sided-associative sounds like
a problem.

In general, perhaps we should forbid equal precedence with differing
associativity?

Which then would mean that R would have to tweak the precedence slightly, to
avoid an implicit infraction.

So perhaps we could have a rule that meta-ops generate new operators of
marginally looser precedence than the originals?

-Martin

On Sun, 29 Mar 2015, GitHub wrote:
>
>   Branch: refs/heads/master
>   Home:   https://github.com/perl6/specs
>   Commit: 40163b8cab714f0588c5e62cc7b181d5c2272b80
>   
> https://github.com/perl6/specs/commit/40163b8cab714f0588c5e62cc7b181d5c2272b80
>   Author: TimToady 
>   Date:   2015-03-29 (Sun, 29 Mar 2015)
>
>   Changed paths:
> M S03-operators.pod
>
>   Log Message:
>   ---
>   reverse associativity on R ops
>
> This seems slightly less unintuitive than the old semantics.


RE: "All classes imply the existence of a role of the same name."

2008-05-16 Thread Kealey, Martin, ihug-NZ

> -Original Message-
> From: chromatic [mailto:[EMAIL PROTECTED] 

> We are trying to avoid the "java.lang.String is Final" 
> problem here in various ways.  One of them is not allowing
> library designers to mark things as final.

Overloading "final" was Java's rather inept attempt to define objects with 
value semantics rather than container semantics (*1). I would be in favour of 
P6 using some much more explicit way of marking that distinction. And using 
shorter Huffman coding for "value" than for "container". And work nicely with 
"compound literals". And still DWIM. :-)

I'm not entirely convinced that just tagging stuff with ":rw" or ":ro" is the 
right way to go; it has too coarse a granularity, so it misses opportunities 
for optimization. Using "const" works fine in C++ where pass-by-value is the 
default (or at least, has shorter huffman coding) and you get almost-reasonable 
copy constructors generated for you. But as we're currently defining Perl6, 
anything that's an object is passed by reference by default (*2), and object 
aren't actually "inside" other objects, merely referenced by them (*3).

A "const" parameter in C++ lets you pass something to a function and the 
function promises not to modify it; what's missing (from C++) is the ability 
for the caller to promise not to modify it either.

Likewise in P6 we have no way to pass a "value" object to a sub and at the same 
time make a promise to that sub that the "value" won't change under it. Or put 
another way, we have no way to tell the sub that it doesn't have to take a copy 
to be sure it won't change while it's using it.

There are potentially enormous optimisation benefits if you know that an object 
is immutable (for a start, you never have to copy it), but even with lesser 
declarative guarantees, in some circumstances you can infer actual 
immutability, so both types of declarations are useful.

I'd like to see separate, clear:
- declarative separation of "value" and "container";
- implicit conversion between the two;
- promises BY functions that their parameters won't be changed when it 
returns;
- promises TO functions that their parameters won't be changed while 
they're working with them.

In a certain sense doing "values" is easy: simply make a class that has no 
mutators, sets all its fields in its constructor, and where a field references 
another object, require that that object too must likewise be a "value".

The hard bits include:
 - getting the programmer to go to the trouble (making the writing of value 
classes easier for the programmer than writing container classes);
 - extracting and wrapping "values" from "container" classes, if the container 
object isn't implemented simply as a singleton reference to a value object (and 
there may be good efficiency reasons for this too: think "String" vs 
"StringBuf" in Java).

-Martin

(*1:  At least that one works; is you want to see something that doesn't know 
whether it's a value or a container, have a look at the ugliness that is 
java.util.date.)

(*2: While primatives still get passed by value. This is of course how Java 
does it, and indeed pretty much every mainstream OO language created since 
1990. Which explains a lot about what's wrong with Java, and software 
engineering in general: design-by-contract has been reduced to 
design-by-approximate-guideline-if-you-feel-like-it.)

(*3: Compact types not withstanding)
---
Have you seen our website? http://www.vodafone.co.nz

Manage Your Account, check your Vodafone Mail and send web2TXT online: 
http://www.vodafone.co.nz/myvodafone

CAUTION: This correspondence is confidential and intended for the named 
recipient(s) only.
If you are not the named recipient and receive this correspondence in error, 
you must not copy,
distribute or take any action in reliance on it and you should delete it from 
your system and
notify the sender immediately.  Thank you.

Unless otherwise stated, any views or opinions expressed are solely those of 
the author and do
not represent those of Vodafone New Zealand Limited.

Vodafone New Zealand Limited
20 Viaduct Harbour Avenue, Private Bag 92161, Auckland 1030
Telephone + 64 9 355 2000
Facsimile + 64 9 355 2001


RE: "All classes imply the existence of a role of the same name."

2008-05-16 Thread Kealey, Martin, ihug-NZ
object, and acts as a proxy for all other method calls.

Whichever method is used, VALUE() does the corresponding reverse -- either it 
recursively clones an object with container semantics changing the type of each 
member to a constant value type, or it simply extracts the reference member. 
Either way, calling .VALUE() on a value object simply returns SELF.

Option (a) is really only useful if you know how deep to go, which means you 
have to have seen the "container" class definition (and possibly have derived 
the "value" class automatically). So it makes sense to associate these two 
approaches with the suggested Value and Class keywords.

-Martin

(Or you could call them CONSTANT and VARIABLE I suppose; the names aren't 
important at this stage.)
---
Have you seen our website? http://www.vodafone.co.nz

Manage Your Account, check your Vodafone Mail and send web2TXT online: 
http://www.vodafone.co.nz/myvodafone

CAUTION: This correspondence is confidential and intended for the named 
recipient(s) only.
If you are not the named recipient and receive this correspondence in error, 
you must not copy,
distribute or take any action in reliance on it and you should delete it from 
your system and
notify the sender immediately.  Thank you.

Unless otherwise stated, any views or opinions expressed are solely those of 
the author and do
not represent those of Vodafone New Zealand Limited.

Vodafone New Zealand Limited
20 Viaduct Harbour Avenue, Private Bag 92161, Auckland 1030
Telephone + 64 9 355 2000
Facsimile + 64 9 355 2001


RE: assignable mutators (S06/Lvalue subroutines)

2008-06-03 Thread Kealey, Martin, ihug-NZ
> If a routine is rw, you may optionally define a single "slurpy scalar"
> (e.g., '*$value') in its signature.

A good start, but why limit the Lvalue to a scalar? A list l-value seems like a 
pretty useful thing to me.

-Martin

---
Have you seen our website? http://www.vodafone.co.nz

Manage Your Account, check your Vodafone Mail and send web2TXT online: 
http://www.vodafone.co.nz/myvodafone

CAUTION: This correspondence is confidential and intended for the named 
recipient(s) only.
If you are not the named recipient and receive this correspondence in error, 
you must not copy,
distribute or take any action in reliance on it and you should delete it from 
your system and
notify the sender immediately.  Thank you.

Unless otherwise stated, any views or opinions expressed are solely those of 
the author and do
not represent those of Vodafone New Zealand Limited.

Vodafone New Zealand Limited
20 Viaduct Harbour Avenue, Private Bag 92161, Auckland 1030
Telephone + 64 9 355 2000
Facsimile + 64 9 355 2001


RE: Split with negative limits, and other weirdnesses

2008-09-30 Thread Kealey, Martin, ihug-NZ

Hmmm, my understanding was that it stopped *splitting* after the limit, but it 
doesn't stop "consuming" the source; rather the entire remainder is returned as 
the last item in the list, even if it contains the delimiter. A bit like this:

sub split($pat, $src, $limit) {
@r = split($pat, $src);
return @r[0..$limit-2], join($pat, @r[$limit-1..*]);
} 

except of course it works where $pat isn't a string literal, and does sensible 
things if $limit is 0 or 1, and is implemented more efficiently.

-Martin

> -Original Message-
> From: Mark J. Reed [mailto:[EMAIL PROTECTED] 
> Sent: Monday, September 29, 2008 8:44 AM
> To: Chris Davaz
> Cc: Carl Mäsak; Perl6
> Subject: Re: Split with negative limits, and other weirdnesses
> 
> On Sun, Sep 28, 2008 at 11:40 AM, Chris Davaz 
> <[EMAIL PROTECTED]> wrote:
> > Ok, so 0 returns the empty list and -1 violates the 
> signature? In PIR
> > can we have such signatures that put a constraint on the range of
> > values for a given parameter?
> 
> Maybe this has already been proposed and rejected, but why not simply
> define the limit parameter such that
> 
> split($pat, $src, $limit)
> 
> is equivalent, result-wise, to
> 
> split($pat, $src)[0 .. $limit - 1]
> 
> ?  Of course, the limit-parameter case might be able to avoid some
> work compared to the second, which might not always be able to do its
> job lazily, but the return value would be the same.  Then you don't
> have to come up with separate edge case rules for two different
> constructs... the one follows logically from the other.
> 
> $limit is 0?  @foo[0..-1] is the empty list. Check.
> 
> @foo[0..-2] is also the empty list.  So negative parameters 
> don't need to Fail..
> 
> -- 
> Mark J. Reed <[EMAIL PROTECTED]>
> 

---
Have you seen our website? http://www.vodafone.co.nz

Manage Your Account, check your Vodafone Mail and send web2TXT online: 
http://www.vodafone.co.nz/myvodafone

CAUTION: This correspondence is confidential and intended for the named 
recipient(s) only.
If you are not the named recipient and receive this correspondence in error, 
you must not copy,
distribute or take any action in reliance on it and you should delete it from 
your system and
notify the sender immediately.  Thank you.

Unless otherwise stated, any views or opinions expressed are solely those of 
the author and do
not represent those of Vodafone New Zealand Limited.

Vodafone New Zealand Limited
20 Viaduct Harbour Avenue, Private Bag 92161, Auckland 1030
Telephone + 64 9 355 2000
Facsimile + 64 9 355 2001