Re: Test Case: Complex Numbers

2005-11-10 Thread Luke Palmer
Just some initial thoughts and syntax issues.  I'll come back to it on
the conceptual side a little later.

On 11/10/05, Jonathan Lang <[EMAIL PROTECTED]> wrote:
>
> class complexRectilinear {
>   has $.x, $.y;

Hmm, that might need to be

has ($.x, $.y);

However, inlining "has"s isn't possible, so there's really no reason
for that restriction.  But it might be good just for consistency with
"my".  But it also might not, because I'm always annoyed with those
parentheses.

>   method infix:+ ($a is complexRectlinear, $b is complexRectilinear)

method infix:<+> (complexRectilinear $a, complexRectilinear $b)

> returns complexRectilinear {
> return new complexRectilinear($a.x + $b.x, $a.y + $b.y);

return new complexRectilinear: $a.x + $b.x, $a.y + $b.y;

>   }
>   ...
>   method coerce:complexPolar () returns complexPolar {
> return new complexPolar ($.x * $.x + $.y * $.y, atn($.y / $.x) *
> (sgn($.x) || sgn($.y)));
>   }

Hmm. I don't know why you marked this with coerce:?  Maybe coerce:
marks a one-to-one correspondence; i.e. things that can be used
interchangably.  But for now, I think you either mean:

method asComplexPolar ()

Or:

method coerce: (--> complexPolar)

(that might take an argument of some sort)

>   ...
> }
>
> ... and a similar definition for class polar.
>
> (Technically, coerce:complexPolar and infix:+ are "generators" in the
> sense that they create new instances of the class; but ISTR something
> about generators not being allowed in classes.)

Ahh, you read that in theory.pod.  It's not clear that the "factory"
and "generator" abstractions are all that useful (I'm still looking
for a good use though).  I just included them for symmetry (like
Maxwell :-).

Don't think that you're not allowed to return instances of the class
you are defining from methods.  You can.  Generators are more
restrictive: they say that any subclass must return an instance of
*itself* from that method; i.e. it probably wouldn't be able to use
your implementation.  But that breaks subclassing laws, which is why
they aren't allowed in classes.

> You should then be able to say:
>
> union complex {
>   class complexRectilinear;
>   class complexPolar;
> }
>
> ...or something of the sort.  At this point, you have the ability to
> freely represent complex numbers in either coordinate system and to
> switch between them at will.  Am I right so far?

Hmm, that union looks like a backwards role.  That is, you're creating
a role "complex" and saying that the interface of that role is
whatever is common between these two classes.  Interesting idea... not
sure how fruitful that is though.

The idea of several isomorphic implementations of the same thing has
occurred to me several times, but I never figured out how it might
work.  Let me think about that.

> multi exp($a is complex, $b is complex) returns list of complex { ... }

multi exp(complex $a, complex $b) returns List of Complex {...}

> However, if $b's real component isn't a rational number, you won't
> have a finite number of elements in the list.  Here's where I get a
> little fuzzy: IIRC, there's some means of defining a list by providing
> an element generator:
>
> generator element($index) returns complex { ... }
>
> Is there a way of setting things up so that an attempt to ascertain
> the list's length would call a separate generator for that purpose?
>
> generator length() returns complex { ... }
>
> At any point above, am I abusing the concept of theories, or failing
> to use them to their fullest extent?

Well, you're not using generator correctly.

You're really just trying to define a lazy list or an iterator, right?
 That most likely involves implementing some role:

role ComplexPowers does Lazy {...}

or:

role ComplexPowers does Iterator {...}

And then creating one of those objects from within your pow function. 
Nothing deeply type-theoretical going on here.

> If $b's real component is
> rational, it makes some sense to treat [-1] as the last element in the
> list, [-2] as the second-to-last, and so on; but if $b's real
> component is irrational, there _is_ no positive end to the list, and
> it would make sense if [-1] referred to the first result that you
> reach by rotating in the clockwise direction from the primary result.
> Can an "infinitely long" list be set up so that [-1] still has
> meaning?

Hmm.  I don't see why not.  Though we haven't established the array
laws yet, you're probably not breaking any of them by doing that.  
You can consider your array to be transfiniteish:

[ a[1], a[2], ..., a[-2], a[-1] ]

Understanding that no matter how long you iterate going forward,
you'll never get to a[-1].

> As an example,
> let's say that $b = 0.5.  This means that the first result is rotated
> zero radians counterclockwise from $a's direction, and corresponds to
> [0].  [1] would correspond to being rotated pi radians, and the length
> generator would say that there are only two elements in the

Re: given too little

2005-11-10 Thread Rob Kinyon


> But if we have a mandatory type inferencer underneath that is merely
> ignored when it's inconvenient, then we could probably automatically
> delay evaluation of the code.   . . .

I'm not so certain that ignoring the mandatory type inferencer is a
good idea, even when it's inconvenient. I don't know about you, but my
son keeps trying to get me to let him ignore his homework when it's
inconvenient (ie, the gamecube calls) and I don't let him. So, just
because the gamecube is calling, we should probably listen to the
mandatory type inferencer.




Re: given too little

2005-11-10 Thread Miroslav Silovic

[EMAIL PROTECTED] wrote:


If so then my and Eric's wishes are answered:

when { $_ > 5 } { ... }
when { .caloric_value > $doctors_orders } { ... }

This isn't implemented in pugs yet, but I guess it can be once this is 
clarified.
 


Actually

   when $_ > 5 { ... }
   when .caloric_value > $doctors_orders { ... }

should also work because ~~ match table states that Anything ~~ boolean 
returns the boolean on the right.


   Miro



Re: given too little

2005-11-10 Thread Larry Wall
On Thu, Nov 10, 2005 at 10:11:50AM +0100, TSa wrote:
: HaloO,
: 
: Gaal Yahas wrote:
: >I know why the following doesn't work:
: >
: > given $food {
: > when Pizza | Lazagna { .eat }
: > when .caloric_value > $doctors_orders { warn "no, no no" }
: > # ...
: > }
: >
: >The expression in the second when clause is smart-matched against $food,
: >not tested for truth like an if.
: 
: The smart match is hopefully *type* aware. In the above second case
: the match could be :( Item ~~ Code ) the Item is $food, the Code is the
: block { .caloric_value > $doctors_orders }. So far so bad, you say?!
: But I think the type inferencer will type the Code as :(Item --> bool)
: and as such we could specify that a booleanizing, inline block just
: does what you expect. If the same should be the case for
: 
:sub foo:( --> bool) {...}
: 
:given $food
:{
:when foo {...} # call foo and enter if true is returned
:}
: 
: I would like that.

And, in fact, the original Apocalypse specified that behavior for
operators that were known to return boolean.  The problem is that there
are objects that *can* return boolean that you want to nevertheless
want to smartmatch against.  So you want some way to restrict it to
operations that can *only* return boolean, and only do delayed
evaluation of those.  But the phrase "delayed evaluation" says that
the "correct" workaround is:

given $food {
when Pizza | Lazagna { .eat }
when { .caloric_value > $doctors_orders } { warn "no, no no" }
# ...
}

But if we have a mandatory type inferencer underneath that is merely
ignored when it's inconvenient, then we could probably automatically
delay evaluation of the code.  It's not much different from the
problem of

delete %foo{$bar}

realizing that the last operation (returning the looked-up value from
the hash) has to be delayed till after the value is deleted.

In any event, you're right about the fact that it depends only on
the booleanness of the return result, not on whether the expression
"consumes" $_.  A "when true" should always execute whether or not
the topic is true or false.  We'll need to train people that

given $boolean {
when true {...}
when false {...}
}

needs to be rewritten as

given $boolean {
when .true {...}
when .not {...}
}

Fortunately, we can know something is bogus when we see the "when
false".  The question is, is it just semantically bogus or also
syntactically bogus?  The fact is that it can be syntactically bogus
two different ways.

I think this is a good argument for never importing the bool enum
 into the current scope as bare names.  true() is a
predicate, not a value, so it is syntactically bogus because it
will try to eat the {...}.  "true" and "false aren't values in Perl.
The names of the values are bool::true and bool::false, but the values
of the values are 0 and 1.  And the name of the values of the values
is "bit".  (Shades of Lewis Carrol, but hey, it's before breakfast.)
So "false" is not a valid name of a value in standard Perl 6!
The actual values are just bit values.  So another way to write the
switch is:

given $boolean {
when 1 {...}
when 0 {...}
}

Of course, they'll try to outsmart us and write:

given $boolean {
when bool::true {...}
when bool::false {...}
}

which we can still recognize and carp about because the second case
creates unreachable code.

Of course, the best way to rewrite is probably just:

if $boolean {...} else {...}

The long and the short of it is that I think we can depend on the type
inferencer here without the naïve user being aware of it, as long as
we restrict the autodelay to apply only to things that can only return
boolean officially.  We mustn't apply it to things that just happen to
be able to return boolean in boolean context, or things like

when %foo

can't work.

Larry


Re: given too little

2005-11-10 Thread Gaal Yahas
On Thu, Nov 10, 2005 at 07:23:15AM -0700, Eric wrote:
> I'm pretty sure i've heard this discussed but checking S04/Switch
> Statments doesn't make any mention of it.  If it has been settled
> could we get some doc updates?

I looked again more carefully at S04 and saw that Any ~~ Code<$> and
Any ~~ Code<> do in fact have definitions in the smartmatch table.

Any Code<$>   scalar sub truth match if $x($_)
Any Code<>simple closure truth*match if $x() (ignoring $_)

What is Code<$> and Code<>? Closures accepting a single scalar and no
arguments?

If so then my and Eric's wishes are answered:

 when { $_ > 5 } { ... }
 when { .caloric_value > $doctors_orders } { ... }

This isn't implemented in pugs yet, but I guess it can be once this is 
clarified.

-- 
Gaal Yahas <[EMAIL PROTECTED]>
http://gaal.livejournal.com/


Re: given too little

2005-11-10 Thread Eric
On 11/10/05, Gaal Yahas <[EMAIL PROTECTED]> wrote:
> I'm a little bothered that this is consistent but (to me, at least)
> unintuitive. Testing methods on the topic is something people may want
> to do often: is there a way to hide away the control logic? I'm tempted
> to propose that when a ".method" is seen in the when expression, the
> whole thing should become a terminal if. Inconsistent but possibly what
> people want.

That all looks good but you don't realy want it to be just if there is
a .method in there.  It would have to be more magical than that
becuase i might want to do something else.

given $num {
   when > 5 { }
   when < 5 { }
   when == 5 {}
}

I'm not sure that can be done in a whay that makes sense but I would settle for

given $num {
   when $_ > 5 { }
   when $_ < 5 { }
   when $_ == 5 {}
}

I'm pretty sure i've heard this discussed but checking S04/Switch
Statments doesn't make any mention of it.  If it has been settled
could we get some doc updates?

--
--
__
Eric Hodges


Re: given too little

2005-11-10 Thread TSa

HaloO,

Gaal Yahas wrote:

I know why the following doesn't work:

 given $food {
 when Pizza | Lazagna { .eat }
 when .caloric_value > $doctors_orders { warn "no, no no" }
 # ...
 }

The expression in the second when clause is smart-matched against $food,
not tested for truth like an if.


The smart match is hopefully *type* aware. In the above second case
the match could be :( Item ~~ Code ) the Item is $food, the Code is the
block { .caloric_value > $doctors_orders }. So far so bad, you say?!
But I think the type inferencer will type the Code as :(Item --> bool)
and as such we could specify that a booleanizing, inline block just
does what you expect. If the same should be the case for

   sub foo:( --> bool) {...}

   given $food
   {
   when foo {...} # call foo and enter if true is returned
   }

I would like that.
--


given too little

2005-11-10 Thread Gaal Yahas
I know why the following doesn't work:

 given $food {
 when Pizza | Lazagna { .eat }
 when .caloric_value > $doctors_orders { warn "no, no no" }
 # ...
 }

The expression in the second when clause is smart-matched against $food,
not tested for truth like an if. So currently the right way to code this is
something like

 DINER: given $food {
 when Pizza | Lazagna { .eat }
 if .caloric_value > $doctors_orders { warn "no, no no"; leave DINER }
 # ...
 }

(Or whatever the way to address labels is.)

I'm a little bothered that this is consistent but (to me, at least)
unintuitive. Testing methods on the topic is something people may want
to do often: is there a way to hide away the control logic? I'm tempted
to propose that when a ".method" is seen in the when expression, the
whole thing should become a terminal if. Inconsistent but possibly what
people want.

-- 
Gaal Yahas <[EMAIL PROTECTED]>
http://gaal.livejournal.com/