Re: Test Case: Complex Numbers
2005/11/11, Larry Wall [EMAIL PROTECTED]: While you're there, also think about the gray area between arrays and hashes, and whether .[...] subscripts are just a specialized form of .{...} subscripts. By the way, are lazy hash slices allowed? %h{1...} I asked this in #perl6 when I was implementing lazy arrays (in the p5 backend), and most people found it was useless. But I thought I would just ask again :) - Flavio S. Glock
Re: Test Case: Complex Numbers
On Fri, Nov 18, 2005 at 06:54:42PM -0200, Flavio S. Glock wrote: : 2005/11/11, Larry Wall [EMAIL PROTECTED]: : : While you're there, also think about the gray area between arrays and hashes, : and whether .[...] subscripts are just a specialized form of .{...} subscripts. : : By the way, are lazy hash slices allowed? : : %h{1...} I don't see why not. Why should people have to write map { %h{$_} } 1... to get the lazy behavior? Plus we can do something intelligent with the size of the dimension in the case of an array that we know the shape of. : I asked this in #perl6 when I was implementing lazy arrays (in the p5 : backend), and most people found it was useless. But I thought I would : just ask again :) For any given feature, I don't care much about the people who find it useless--I care more about the people who find it useful. :-) (That is, of course, as long as it doesn't get in the way of people who aren't interested in the feature.) Larry
Re: Test Case: Complex Numbers
On Thu, Nov 17, 2005 at 10:18:19PM +0100, TSa wrote: : Another idea is to model nums to have a directional bit where the : polar complex have a full range angle. This whole thing strikes me as a units problem. Much like we don't care if the internal representation is meters or furlongs, so long as we can make 2.54`cm and 1`inch come out to the same thing. Larry
Re: Test Case: Complex Numbers
HaloO, Jonathan Lang wrote: Complex numbers come in two representations: rectilinear coordinates and polar coordinates: I think there's also the Riemanian two angle form of the complex number sphere with r = 0.5 around (0,0,0.5) touching the plane at the origin (0,0) and reaching up to (0,0,1) in space. But admittedly the resulting math is that of projective space. Then there is the classic fact that you should make e.g. role Complex an intentional supertype of Num while the class Complex needs a wider extensional type with the added imaginary part in one form or another. As Luke pointed out, a plain role/class pair might not be enough to model the structural properties of the communalities and differences of Num and Complex. We need to define a family of related types that manage the different interpretations of a 2-tupel of Nums while sharing the underlying data layout---not to mention to be compatible with more generic vector stuff like the scalar product. Another idea is to model nums to have a directional bit where the polar complex have a full range angle. --
Re: Test Case: Complex Numbers
On Fri, 11 Nov 2005, Jonathan Lang wrote: That wasn't the intent; the intent was to define a something-or-other Ccomplex that represents the fact that whatever does this sometimes behaves like a complexRectilinear and other times behaves like a complexPolar. Even the underlying information (the attributes involved) may vary from role to role, though what those attributes represent ought to be the same regardless of which role is in use. I must say that I didn't follow the discussion very much. But this makes me think of this too: the two representations are handy for different calculations. It would be nice if they somehow declared what they can do better (or at all) and have the union take care of which one's methods to use. In another situation, one may implement a system for doing integer arithmetics say in base twelve, and in this case one may have an union to decide to use its .division() method to perform division by three, possibly holding a flag telling that the most accurate status is that held in it. Michele -- Caro Bongo questa ? la civilt?: hai tutto quello che non vuoi, quando non ti serve. - Toto' Tarzan
Re: Test Case: Complex Numbers
At 15:59 +0100 11/14/05, Michele Dondi wrote: I must say that I didn't follow the discussion (complex) very much. But this makes me think of this too: the two representations are handy for different calculations. It would be nice if they somehow declared what they can do better (or at all) and have the union take care of which one's methods to use. In another situation, one may implement a system for doing integer arithmetics say in base twelve, and in this case one may have an union to decide to use its .division() method to perform division by three, possibly holding a flag telling that the most accurate status is that held in it. Someday I may become competent to think in perl6 but if we're expanding on the topic. . . Complex numbers are much like 2-D vectors, the real ones and not the ordered lists that are used with hyper operators. A union structure that allows for 3-D vectors some of which are pseudovectors would be interesting. It would also be possible to represent vectors in 3-D spherical coordinates. Oh. . . A pseudovector differs from a vector in that it doesn't change direction when reflected in a plane mirror. The cross product of two ordinary vectors is a pseudovector. So is a magnetic field. As for complex operations which have multiple results I think a principle value approach makes more sense than a list. It's well established for the inverse trigonometric functions. Leave RootOf( ) to Maple and Mathematica. -- -- Halloween == Oct 31 == Dec 25 == Christmas --
Re: Test Case: Complex Numbers
Doug McNutt wrote: As for complex operations which have multiple results I think a principle value approach makes more sense than a list. It's well established for the inverse trigonometric functions. Leave RootOf( ) to Maple and Mathematica. In the hypothetical module that I'm describing, the principle value approach _would_ be used - in scalar context. The only time the list of all possible results approach would be used would be if you use list context. If you have no need of the list feature, then you don't have to use it. I believe that what I have outlined is a reasonable approach to handling complex numbers. It may or may not be the best way to do so (and I suspect that it isn't), but that isn't really the point. The point is that it _is_ reasonable, and I'd like to see how well Perl 6 handles it. Michele Dondi wrote: I must say that I didn't follow the discussion very much. But this makes me think of this too: the two representations are handy for different calculations. It would be nice if they somehow declared what they can do better (or at all) and have the union take care of which one's methods to use. That's one of the points I had in mind. Rectilinear coordinates are useful for addition and subtraction, while polar coordinates fare better for multiplication, division, powers, logs, trigonometric functions, and hyperbolic functions. So define addition and subtraction for the rectilinear coordinate system and define the remaining operations for the polar coordinate system. The problem is that the two coordinate systems don't just differ in terms of which methods they make available; they also differ in terms of how they represent the value that they represent. So if you want to multiply two complex numbers that were defined using rectilinear coordinates, you'd need to transform them to polar coordinates first, and then multiply those numbers. Phrased in terms of roles, the rectilinear role would have $.x and $.y attributes (which its methods would use), while the polar role would have $.magnitude and $.direction attributes (which _its_ methods would use). That's two sets of attributes which contain identical data in vastly different formats; simply having one class or role do both of these roles would result in extra memory usage (as both sets of attributes would need storage allocated to them), not to mention the likelihood that the two sets of attributes may end up getting out of synch with each other. What I'm looking at is a way to declare that the two roles are different representatives of the same thing. Memory would be allocated to exactly one set of attributes at a time, and transformations between the different sets would be called whenever you change the underlying representation of the data. In the former regard, this would be much like C's union; but it would differ from them in that it would be designed to preserve the logical value (what the data represents) rather than the physical value (the sequence of bits in memory). -- Jonathan Dataweaver Lang
Re: Test Case: Complex Numbers
Jonathan Lang wrote: In the hypothetical module that I'm describing, the principle value approach _would_ be used - in scalar context. The only time the list of all possible results approach would be used would be if you use list context. If you have no need of the list feature, then you don't have to use it. This might suprise people: @a = (1,4,9); @b = @a.map:{sqrt}; ok([EMAIL PROTECTED] == [EMAIL PROTECTED]); # fails because of list context The problem is that the two coordinate systems don't just differ in terms of which methods they make available; they also differ in terms of how they represent the value that they represent And they also differ in what values they can represent, assuming the underlying representation of real numbers uses a finite number of bits. In the former regard, this would be much like C's union; but it would differ from them in that it would be designed to preserve the logical value (what the data represents) rather than the physical value (the sequence of bits in memory). Which is not possible in the general case. That probably doesn't mean that there isn't a good use for the concept, but I'd be wary of it for precision math stuff.
Re: Test Case: Complex Numbers
On Fri, Nov 11, 2005 at 06:21:53AM +, Luke Palmer wrote: : 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 hass 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. It's not about inlining in general, but particularly about the relationship of precedence with assignment. And you presumably *can* say: has ($.x, $.y) = (1, 2); to mean the same as: has $.x = 1; has $.y = 2; Likewise state ($.x, $.y) = (1, 2); means state $.x = 1; state $.y = 2; :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; rampantspeculation Given the new relationship between $obj.method(...) and $obj.method: ..., I'm wondering if we can make the same relationship between method $obj(...) method $obj: ... That is, : becomes more of a Haskellish $ operator. I speculated this earlier when I wanted to change $obj.method :{...} into $obj.method: {...} But foo $bar(...) is probably too ambiguous with a possible foo list operator unless we were to require : on all calls to list operators: print: 1,2,3 That's likely to inspire mutiny. Though we could perhaps get away with requiring the colon only on list operators that have more than one argument, on the theory that foo 1; is always the same as 1.foo; /rampantspeculation : 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. And what's the common role of a scalar that can have a string implementation in several abstraction levels, plus any number of native integer/float and bignum/bigfloat implementations hiding behind it? Interesting question. : 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]. I believe we already said you could pop or refer to the end of an infinite array in A6/Appendix B. : 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 list. : Could you set things up so that you could nonetheless access [2] : (which is rotated by 2*pi radians), [3] (rotated by 3*pi radians), or : possibly even have [-1] represent a rotation by -pi radians? : : Well, it would certainly be okay to have an infinite list that had : that property. However, having the list report that its length is, : say, finite $n, and then having @list[$n] be something besides undef : may be breaking some law (but maybe not[1]). : : What you're really doing is defining the indices mod $n. Maybe : there's some way to tell the compiler that your indices are defined : that way to allow this sort of behavior. Maybe you could make a : subclass of Array called ModArray or something that allowed this. : Maybe you're simply not allowed to use square brackets in a case where : the list is finite but defined for all indices. All is fair if you predeclare. : But that's all theoretical formality. For the Perl practicioner, feel : free to break the laws if it helps you get your job done. :-) : : Luke : : [1] I think I'm going to embark on writing down the laws for a few of : our basic types so we can actually talk about this without
Re: Test Case: Complex Numbers
Luke Palmer wrote: Just some initial thoughts and syntax issues. I'll come back to it on the conceptual side a little later. I'm looking forward to it. Jonathan Lang wrote: 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:? Neither do I; I was assuming that the purpose of coerce: is to allow implicit type conversions - that is, if I feed a complexRectilinear object into an argument slot that's looking for a complexPolar object, this method would be called implicitly and the result would be used instead. ... } ... 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 :-). FWIW, I didn't read theory.pod as thoroughly as I probably should have, nor did I grasp it as well as I would like. But when I looked at the concept of virtual lists, the union/factory/generator triad seemed to be, conceptually, a perfect fit: the virtual list is actually a union, whose factory includes generators that produce information about the list on demand. More generally, a union would be the appropriate tool for the magic behind what Perl 5 used ties for. 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. I'm not sure I'm following this. 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. That wasn't the intent; the intent was to define a something-or-other Ccomplex that represents the fact that whatever does this sometimes behaves like a complexRectilinear and other times behaves like a complexPolar. Even the underlying information (the attributes involved) may vary from role to role, though what those attributes represent ought to be the same regardless of which role is in use. 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. Cunion was probably a bad name for it, especially considering that theory.pod already uses Cunion for a very specific purpose. Cchoice might have been a better name. 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. That's the most traditional way, yes; but is there anything wrong with the concept of implementing it based on a factory instead of a role? 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
Re: Test Case: Complex Numbers
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 hass 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:as (-- 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 list. Could you set things up so that you could nonetheless access [2]
Test Case: Complex Numbers
The following is an attempt to put a number of Perl6 concepts into practice, in order to see how useful and intuitive they actually are. Complex numbers come in two representations: rectilinear coordinates and polar coordinates: class complexRectilinear { has $.x, $.y; method infix:+ ($a is complexRectlinear, $b is complexRectilinear) returns complexRectilinear { 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))); } ... } ... 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.) 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? Next: multi exp($a is complex, $b is complex) returns complex { ... } This defines a function that raises one complex number to the power of another complex number and returns a third complex number. One problem is that if $b's real component isn't an integer, there's no guarantee that there will be a unique answer. To address this, we could provide a second version of this function: multi exp($a is complex, $b is complex) 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? With this example, it would be useful if the list of results could extend in both directions, so that one could advance through them in a clockwise or counterclockwise direction. 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? Also, even if $b's real component is rational, there are times that one might want to access a version of the result that is rotated some multiple of 2*pi radians from one of the main results. 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 list. Could you set things up so that you could nonetheless access [2] (which is rotated by 2*pi radians), [3] (rotated by 3*pi radians), or possibly even have [-1] represent a rotation by -pi radians? -- Jonathan Dataweaver Lang