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 la...@wall.org
   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: 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 cma...@gmail.com 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
  cjfie...@illinois.edu wrote:
  On Aug 13, 2014, at 8:11 AM, Christopher Fields cjfie...@illinois.edu 
  wrote:
 
  On Aug 13, 2014, at 4:50 AM, Solomon Foster colo...@gmail.com wrote:
 
  On Sat, Aug 9, 2014 at 7:26 PM, Fields, Christopher J
  cjfie...@illinois.edu 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] 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: [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: 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: 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: [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 la...@wall.org
   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 la...@wall.org
   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: 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: 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: 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: 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: 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: 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: 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 la...@wall.org:
     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: 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: 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


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: 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: 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: $*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/tmp;  # 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: XOR does not work that way.

2009-07-03 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: 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: Why pass by reference?

2009-06-19 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-19 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: [Fwd: Re: junctions and conditionals]

2009-04-02 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-02 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: 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.)



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: 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: .map/.reduce with larger arity

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

 the only difference between Cfor and Cmap is that you can only use
 Cfor 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.)

tongue-in-cheek Maybe we should just treat map as a synonym for for. 
/tongue-in-cheek

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: 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{ Spring Summer Autumn Winter };

 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: 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-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: 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: 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: 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: 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: 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: 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: 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: 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: 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 Cchmod that I really
 wanted to improve the API for; I touched Cchown only because it was adjacent
 in the POD, and it seems reasonable for the two functions/methods to have
 similar lookfeel.

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: 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: 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


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: 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
 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: ./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: 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.




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.




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: 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





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 Cmap, Cgrep, 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: 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



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 Iaren't 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 Ican see that
things are safe to parallelize.

-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: 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 Ido contain foo or those that Idon't?

-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.