What does a Pair numify to?
Pugs and Elf currently numify a Pair object to 2, and Rakudo currently dies of despair. My guess is that the semantics of Pugs and Elf falls out naturally form a pair being treated as a list of two elements, or something. The question still deserves to be raised whether always-2 is a good semantics, or whether one would prefer some other default. // Carl
Re: What does a Pair numify to?
HaloO, Carl Mäsak wrote: Pugs and Elf currently numify a Pair object to 2, and Rakudo currently dies of despair. My guess is that the semantics of Pugs and Elf falls out naturally form a pair being treated as a list of two elements, or something. The question still deserves to be raised whether always-2 is a good semantics, or whether one would prefer some other default. My idea is to let a pair numify to whatever the value numifies to. Same thing with stringification. In general I think that a pair should hide its key as far as possible if used as non-pair. Regards, TSa. -- The unavoidable price of reliability is simplicity -- C.A.R. Hoare Simplicity does not precede complexity, but follows it. -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
Re: Smooth numeric upgrades?
HaloO, Darren Duncan wrote: Michael G Schwern wrote: TSa (Thomas Sandlaß) wrote: I want to stress this last point. We have the three types Int, Rat and Num. What exactly is the purpose of Num? The IEEE formats will be handled by num64 and the like. Is it just there for holding properties? Or does it do some more advanced numeric stuff? Int, Rat [1] and Num are all human types. They work like humans were taught numbers work in math class. They have no size limits. They shouldn't lose accuracy. [2] As soon as you imply that numbers have a size limit or lose accuracy you are thinking like a computer. That's why num64 is not a replacement for Num, conceptually nor is int64 a replacement for Int. They have limits and lose accuracy. All agreed. I also agree. But I want to work out a bit more of the semantics of Num. Int and Rat are easy insofar as there are arbitrary precision implementations. This is not the case for irrational numbers. One route here is to go into symbolic math. But this is at best the task of add-on modules. The concept I have in mind is the subtype chain Int : Rat : Num with automatic upgrades and non-automatic downgrades. That is my Int $i = 2/3; my Rat $r = sqrt(2); are conceptually failures and result in exceptions which can of course be converted to warnings or automatic conversions by pragmas. I see the Complex type as a parametric type that replicates the above subtype chain as Complex[Int] : Complex[Rat] : Complex[Num]. This should be the general scheme for other types that implement numeric operations. The Num type is basically an arbitrary precision float as Duncan has proposed together with an .irrational flag that marks it as non-Rat. E.g. the Num implementation of sqrt might even flag sqrt(4) as non-Rat and actually not even achieve 2 numerically. This can be remedied as follows subset SqrInt of Int where { $_ == any(1..* »**» 2) } multi sub sqrt (SqrInt $i -- Int) { # calculate approximate result that will be almost an Int # cast is needed to avoid endless dispatch return round( sqrt( Num $i ) ); } subset SqrRat of Rat where { .numerator ~~ SqrInt .denominator ~~ SqrInt } multi sub sqrt (SqrRat $r -- Rat) { # dispatches to sqrt:(SqrInt -- Int) return round( sqrt( $r.numerator ) ) / round( sqrt( $r.denominator ) ); } The latter implementation has the drawback that it needs to produce two possibly large Ints as intermediate results. So we could instead call the approximate sqrt with $r directly with appropriately set precision demands. The specced behavior of / for two Ints falls out naturally because it returns a Num that simply doesn't happen to have the non-Rat flag set and as such is assignable to a variable with a Rat constraint. It's also easy to get typesafe assignments of Rats with .denominator == 1 to Int variables. That is we have the conceptual subsets subset Rat of Num where { !.irrational } subset Int of Rat where { .denominator == 1 } Functions like sin are not required to flag sin(pi/6) == 1/2 as rational. They might not even achieve the numeric equality unless some additional definitions are made for the equality of Nums with some epsilon. [2] Num should have an optional limit on the number of decimal places it remembers, like NUMERIC in SQL, but that's a simple truncation. I disagree. I disagree as well. But Num should provide an interface to access the underlying approximations made by functions that operate on Nums. The default will be a relative error i.e. a ratio between the difference to the exact value and the exact value---note that this error itself is approximate. This means that the absolute error can be quite large for large numbers. This estimation strategy allows an implementation of Num on top of Rat. For starters, any limit built into a type definition should be defined not as stated above but rather with a simple subtype declaration, eg subtype of Rat where ... that tests for example that the Rat is an exact multiple of 1/1000. The interesting thing that occurred to me is that constraints on variables are known at compile time. If we define that the point in a computation where the rounding takes place is the moment when it comes to storing a value in a variable then the parser can propagate the accuracy of the constraint to all functions called in the expression tree. This means we need a definition language how the Num type performs its approximations. This is then used in the where clause of subset declarations of Num. This means that we have an extensible set of operators and functions that do numerics. All these functions have an approximation interface that the compiler generates input for. If the programmer wishes she can also use that interface directly, of course. Second, any truncation should be done at the operator level not at the type level; for example, the rational division
Roles and IO?
Hi all, I've been thinking about how the IO interface should be organized in perl6. It seems that part of S16 has received little attention so far. One main problem with filehandles is that are rather diverse. The only operation that all of them have in common is close. Reading versus writing is a obvious difference, there are many more differences. One can't seek a socket or a pipe, and likewise one can't accept on a file. A listening socket can't even be read or written to. At the same time, they all do have some parts in common with some other types of handles. Perl 5's solution is to use a fat interface, and raise an error if an unsupported action is tried. I think that approach is needlessly fragile. Another solution is to make a separate class for every variety of handle, but IMO that's a plain fugly solution that simply doesn't scale up very well. What I propose is using role composition for *everything*. Most importantly that includes the roles Readable and Writable, but also things like Seekable, Mapable, Pollable, Statable, Ownable, Buffered (does Readable), Socket, Acceptable (does Pollable), and more. That may however make some interfaces is a bit wordy. I think that can be conveyed using a subset like this (though that may be abusing the feature). subset File of Mapable Pollable Statable Ownable; In this case, these calls: open($filename, :w); would return a Writable File, and Socket::connect($remote_host, $port, :typeinet); would return a Socket Buffered Pollable Writable Regards, Leon Timmermans
Re: Roles and IO?
Leon Timmermans wrote: What I propose is using role composition for *everything*. Most importantly that includes the roles Readable and Writable, but also things like Seekable, Mapable, Pollable, Statable, Ownable, Buffered (does Readable), Socket, Acceptable (does Pollable), and more. That may however make some interfaces is a bit wordy. I think that can be conveyed using a subset like this (though that may be abusing the feature). subset File of Mapable Pollable Statable Ownable; subset is the wrong approach: a subset is about taking an existing role and restricting the range of objects that it will match. What you're really asking for are composite roles: role File does Mappable does Pollable does Statable does Ownable {} One of the things about roles is that once you have composed a bunch of them into another role, they're considered to be composed into whatever that role is composed into. So does File would be equivalent to does Mappable does Pollable does Statable does Ownable (barring potential conflicts between Mappable, Pollable, Statable, and Ownable which File would presumably resolve). -- Jonathan Dataweaver Lang
Re: Roles and IO?
On 2008 Dec 11, at 20:16, Leon Timmermans wrote: One main problem with filehandles is that are rather diverse. The only operation that all of them have in common is close. Reading versus Be glad Xenix is dead. There were filehandles which didn't even support close() (they were actually handles for shared memory and semaphores). -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allb...@kf8nh.com system administrator [openafs,heimdal,too many hats] allb...@ece.cmu.edu electrical and computer engineering, carnegie mellon universityKF8NH
Re: Roles and IO?
On Thu, Dec 11, 2008 at 8:16 PM, Leon Timmermans faw...@gmail.com wrote: What I propose is using role composition for *everything*. Most importantly that includes the roles Readable and Writable, but also things like Seekable, Mapable, Pollable, Statable, Ownable, Buffered (does Readable), Socket, Acceptable (does Pollable), and more. Mapable is better spelled Mappable in English. Arguably, it should be Stattable as well; statable means state-able. That may however make some interfaces is a bit wordy. I think that can be conveyed using a subset like this (though that may be abusing the feature). subset File of Mapable Pollable Statable Ownable; As Jonathan said, I think composition makes more sense here... but what if you have an interface that expects an IO object and does nothing with it but pass it into some other interface? How does it declare that? It seems like there still needs to be a generic superrole that means some non-empty but unspecified subset of these roles - maybe Closable would work, but it's not real clear. -- Mark J. Reed markjr...@gmail.com